From 342ab56735bb0f951d06c2f129014d0aac9f66d9 Mon Sep 17 00:00:00 2001 From: Daniel Markstedt Date: Fri, 1 Dec 2023 13:30:30 +0900 Subject: [PATCH] Web UI: Rework the Attach Device section to be universal --- python/web/src/templates/index.html | 242 +++++++++++++++------------ python/web/src/web.py | 86 +++------- python/web/tests/api/test_devices.py | 22 +-- 3 files changed, 166 insertions(+), 184 deletions(-) diff --git a/python/web/src/templates/index.html b/python/web/src/templates/index.html index 01e4967b..db898716 100644 --- a/python/web/src/templates/index.html +++ b/python/web/src/templates/index.html @@ -83,11 +83,10 @@ {{ device.device_name }} {% if "No Media" in device.status %} -
+ - + {% for key, value in device_types[type]["params"] | dictsort %} + + {% if value.isnumeric() %} + + {% elif key == "interface" %} + + {% else %} + + {% endif %} + {% endfor %} + {% if type in DISK_DEVICE_TYPES %} + + + + + {% endif %} + + + + + +
+ + + {% endfor %} + + + +
+
@@ -218,7 +351,7 @@
{% for subdir, group in formatted_image_files.items() %} -
+
{{ subdir }} @@ -307,9 +440,8 @@ {% else %} -
+ - - {% for key, value in device_types[type]["params"] | dictsort %} - - {% if value.isnumeric() %} - - {% elif key == "interface" %} - - {% else %} - - {% endif %} - {% endfor %} - {% if type in REMOVABLE_DEVICE_TYPES %} - - - {% endif %} - - - - - -
- - - {% endfor %} - -
-
{% endblock content %} diff --git a/python/web/src/web.py b/python/web/src/web.py index fbed803f..18af950a 100644 --- a/python/web/src/web.py +++ b/python/web/src/web.py @@ -125,6 +125,7 @@ def get_env_info(): "image_dir": server_info["image_dir"], "image_root_dir": Path(server_info["image_dir"]).name, "shared_root_dir": Path(FILE_SERVER_DIR).name, + "hd_suffixes": tuple(server_info["schd"]), "cd_suffixes": tuple(server_info["sccd"]), "rm_suffixes": tuple(server_info["scrm"]), "mo_suffixes": tuple(server_info["scmo"]), @@ -651,12 +652,13 @@ def log_level(): @login_required def attach_device(): """ - Attaches a peripheral device that doesn't take an image file as argument + Attaches device of any type """ scsi_id = request.form.get("scsi_id") unit = request.form.get("unit") device_type = request.form.get("type") drive_name = request.form.get("drive_name") + file_name = request.form.get("file_name") if not scsi_id: return response(error=True, message=_("No SCSI ID specified")) @@ -690,11 +692,29 @@ def attach_device(): "device_type": device_type, "params": params, } + + if file_name: + kwargs["params"]["file"] = file_name + + # If drive_props is defined use properies from this dict, + # otherwise fall back to the properties file if it exists if drive_props: kwargs["vendor"] = drive_props["vendor"] kwargs["product"] = drive_props["product"] kwargs["revision"] = drive_props["revision"] kwargs["block_size"] = drive_props["block_size"] + else: + drive_properties = Path(CFG_DIR) / f"{file_name}.{PROPERTIES_SUFFIX}" + if drive_properties.is_file(): + process = file_cmd.read_drive_properties(drive_properties) + process = ReturnCodeMapper.add_msg(process) + if not process["status"]: + return response(error=True, message=process["msg"]) + conf = process["conf"] + kwargs["vendor"] = conf["vendor"] + kwargs["product"] = conf["product"] + kwargs["revision"] = conf["revision"] + kwargs["block_size"] = conf["block_size"] process = piscsi_cmd.attach_device(scsi_id, **kwargs) process = ReturnCodeMapper.add_msg(process) @@ -711,70 +731,6 @@ def attach_device(): return response(error=True, message=process["msg"]) -@APP.route("/scsi/attach", methods=["POST"]) -@login_required -def attach_image(): - """ - Attaches a file image as a device - """ - file_name = request.form.get("file_name") - file_size = request.form.get("file_size") - scsi_id = request.form.get("scsi_id") - unit = request.form.get("unit") - device_type = request.form.get("type") - - if not scsi_id: - return response(error=True, message=_("No SCSI ID specified")) - if not file_name: - return response(error=True, message=_("No image file to insert")) - - kwargs = {"unit": int(unit), "params": {"file": file_name}} - - if device_type: - kwargs["device_type"] = device_type - device_types = piscsi_cmd.get_device_types() - expected_block_size = min(device_types["device_types"][device_type]["block_sizes"]) - - # Attempt to load the device properties file: - # same file name with PROPERTIES_SUFFIX appended - drive_properties = Path(CFG_DIR) / f"{file_name}.{PROPERTIES_SUFFIX}" - if drive_properties.is_file(): - process = file_cmd.read_drive_properties(drive_properties) - process = ReturnCodeMapper.add_msg(process) - if not process["status"]: - return response(error=True, message=process["msg"]) - conf = process["conf"] - kwargs["vendor"] = conf["vendor"] - kwargs["product"] = conf["product"] - kwargs["revision"] = conf["revision"] - kwargs["block_size"] = conf["block_size"] - expected_block_size = conf["block_size"] - - process = piscsi_cmd.attach_device(scsi_id, **kwargs) - process = ReturnCodeMapper.add_msg(process) - if process["status"]: - if int(file_size) % int(expected_block_size): - logging.warning( - "The image file size %s bytes is not a multiple of %s. " - "PiSCSI will ignore the trailing data. " - "The image may be corrupted, so proceed with caution.", - file_size, - expected_block_size, - ) - return response( - message=_( - "Attached %(file_name)s as %(device_type)s to " - "SCSI ID %(id_number)s LUN %(unit_number)s", - file_name=file_name, - device_type=get_device_name(device_type), - id_number=scsi_id, - unit_number=unit, - ) - ) - - return response(error=True, message=process["msg"]) - - @APP.route("/scsi/detach_all", methods=["POST"]) @login_required def detach_all_devices(): diff --git a/python/web/tests/api/test_devices.py b/python/web/tests/api/test_devices.py index f13c6887..f5b7219f 100644 --- a/python/web/tests/api/test_devices.py +++ b/python/web/tests/api/test_devices.py @@ -2,20 +2,18 @@ import pytest from conftest import ( SCSI_ID, - FILE_SIZE_1_MIB, STATUS_SUCCESS, ) -# route("/scsi/attach", methods=["POST"]) -def test_attach_image(http_client, create_test_image, detach_devices): +# route("/scsi/attach_device", methods=["POST"]) +def test_attach_device_with_image(http_client, create_test_image, detach_devices): test_image = create_test_image() response = http_client.post( - "/scsi/attach", + "/scsi/attach_device", data={ "file_name": test_image, - "file_size": FILE_SIZE_1_MIB, "scsi_id": SCSI_ID, "unit": 0, "type": "SCHD", @@ -26,7 +24,7 @@ def test_attach_image(http_client, create_test_image, detach_devices): assert response.status_code == 200 assert response_data["status"] == STATUS_SUCCESS assert response_data["messages"][0]["message"] == ( - f"Attached {test_image} as Hard Disk Drive to SCSI ID {SCSI_ID} LUN 0" + f"Attached Hard Disk Drive to SCSI ID {SCSI_ID} LUN 0" ) # Cleanup @@ -110,10 +108,9 @@ def test_detach_device(http_client, create_test_image): test_image = create_test_image() http_client.post( - "/scsi/attach", + "/scsi/attach_device", data={ "file_name": test_image, - "file_size": FILE_SIZE_1_MIB, "scsi_id": SCSI_ID, "unit": 0, "type": "SCHD", @@ -145,10 +142,9 @@ def test_detach_all_devices(http_client, create_test_image, list_attached_images test_images.append(test_image) http_client.post( - "/scsi/attach", + "/scsi/attach_device", data={ "file_name": test_image, - "file_size": FILE_SIZE_1_MIB, "scsi_id": scsi_id, "unit": 0, "type": "SCHD", @@ -170,10 +166,9 @@ def test_eject_device(http_client, create_test_image, detach_devices): test_image = create_test_image() http_client.post( - "/scsi/attach", + "/scsi/attach_device", data={ "file_name": test_image, - "file_size": FILE_SIZE_1_MIB, "scsi_id": SCSI_ID, "unit": 0, "type": "SCCD", # CD-ROM @@ -203,10 +198,9 @@ def test_show_device_info(http_client, create_test_image, detach_devices): test_image = create_test_image() http_client.post( - "/scsi/attach", + "/scsi/attach_device", data={ "file_name": test_image, - "file_size": FILE_SIZE_1_MIB, "scsi_id": SCSI_ID, "unit": 0, "type": "SCHD",