From cde4866844063088f11e96ec9c23d8ebee2ffd3c Mon Sep 17 00:00:00 2001 From: Daniel Markstedt Date: Fri, 23 Dec 2022 16:13:52 -0800 Subject: [PATCH] Allow generating ISO image from local file (#1046) - Break out generate_iso() into its own class method in file_cmds - Add form and handling of using local file to generate iso image - Reorder index page sections to group actions that create new image files --- python/common/src/piscsi/file_cmds.py | 56 ++-- python/web/src/static/themes/modern/style.css | 3 +- python/web/src/templates/index.html | 269 ++++++++++-------- python/web/src/web.py | 12 +- python/web/tests/api/test_files.py | 48 +++- 5 files changed, 248 insertions(+), 140 deletions(-) diff --git a/python/common/src/piscsi/file_cmds.py b/python/common/src/piscsi/file_cmds.py index 57bc0e63..dd942009 100644 --- a/python/common/src/piscsi/file_cmds.py +++ b/python/common/src/piscsi/file_cmds.py @@ -635,30 +635,48 @@ class FileCmds: ) tmp_full_path.unlink(True) - try: - run( - [ - "genisoimage", - *iso_args, - "-o", - str(iso_filename), - tmp_dir, - ], - capture_output=True, - check=True, - ) - except CalledProcessError as error: - logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8")) - return {"status": False, "msg": error.stderr.decode("utf-8")} + process = self.generate_iso(iso_filename, Path(tmp_dir), *iso_args) + + if not process["status"]: + return {"status": False, "msg": process["msg"]} - parameters = {"value": " ".join(iso_args)} return { "status": True, - "return_code": ReturnCodes.DOWNLOADFILETOISO_SUCCESS, - "parameters": parameters, - "file_name": iso_filename.name, + "return_code": process["return_code"], + "parameters": process["parameters"], + "file_name": process["file_name"], } + def generate_iso(self, iso_file, target_path, *iso_args): + """ + Takes + - (Path) iso_file - the path to the file to create + - (Path) target_path - the path to the file or dir to generate the iso from + - (*str) iso_args - the tuple of arguments to pass to genisoimage + """ + try: + run( + [ + "genisoimage", + *iso_args, + "-o", + str(iso_file), + str(target_path), + ], + capture_output=True, + check=True, + ) + except CalledProcessError as error: + logging.warning(SHELL_ERROR, " ".join(error.cmd), error.stderr.decode("utf-8")) + return {"status": False, "msg": error.stderr.decode("utf-8")} + + return { + "status": True, + "return_code": ReturnCodes.DOWNLOADFILETOISO_SUCCESS, + "parameters": {"value": " ".join(iso_args)}, + "file_name": iso_file.name, + } + # noinspection PyMethodMayBeStatic def download_to_dir(self, url, save_dir, file_name): """ diff --git a/python/web/src/static/themes/modern/style.css b/python/web/src/static/themes/modern/style.css index c460d24d..741b9fd4 100644 --- a/python/web/src/static/themes/modern/style.css +++ b/python/web/src/static/themes/modern/style.css @@ -741,7 +741,8 @@ section#files p { } section#files table#images form.file-attach input[type="submit"], - section#attach-devices form.device-attach input[type="submit"] { + section#attach-devices form.device-attach input[type="submit"], + section#create-iso form.iso-attach input[type="submit"] { background: #efefef url("icons/file-device-attach.svg") no-repeat 0.5rem center; background-size: 1rem; padding-left: 2rem; diff --git a/python/web/src/templates/index.html b/python/web/src/templates/index.html index 952963e3..429240ff 100644 --- a/python/web/src/templates/index.html +++ b/python/web/src/templates/index.html @@ -382,6 +382,161 @@
+
+
+ + {{ _("Create CD-ROM Image With File") }} + +
    +
  • {{ _("HFS is for Mac OS, Joliet for Windows, and Rock Ridge for POSIX.") }}
  • +
  • {{ _("If the downloaded file is a zip archive, we will attempt to unzip it and store the resulting files.") }}
  • +
+
+ +
+
+ + + + + + + +
+
+
+
+ + + + + + + +
+
+
+ +
+ +
+
+ + {{ _("Create Empty Disk Image File") }} + +
    +
  • {{ _("Please refer to wiki documentation to learn more about the supported image file types.", url="https://github.com/PiSCSI/piscsi/wiki/Supported-Device-Types#image-types") }}
  • +
  • {{ _("It is not recommended to use the Lido hard disk driver with the Macintosh Plus.") }}
  • +
+
+ +
+ + + + + + + + + + + +
+
+ +
+

{{ _("Create Disk Image With Properties") }}

+
+ +
+ +
@@ -482,120 +637,6 @@
-
-
- - {{ _("Download File and Create CD-ROM Image") }} - -
    -
  • {{ _("Create an ISO file system CD-ROM image with the downloaded file, and mount it on the given SCSI ID.") }}
  • -
  • {{ _("HFS is for Mac OS, Joliet for Windows, and Rock Ridge for POSIX.") }}
  • -
  • {{ _("If the downloaded file is a zip archive, we will attempt to unzip it and store the resulting files.") }}
  • -
-
- -
- - - - - - - -
-
- -
- -
-
- - {{ _("Create Empty Disk Image File") }} - -
    -
  • {{ _("Please refer to wiki documentation to learn more about the supported image file types.", url="https://github.com/PiSCSI/piscsi/wiki/Supported-Device-Types#image-types") }}
  • -
  • {{ _("It is not recommended to use the Lido hard disk driver with the Macintosh Plus.") }}
  • -
-
- -
- - - - - - - - - - - -
-
- -
-

{{ _("Create Disk Image With Properties") }}

-
- -
- -
{{ _("Logging") }} diff --git a/python/web/src/web.py b/python/web/src/web.py index 4e043b74..6be30300 100644 --- a/python/web/src/web.py +++ b/python/web/src/web.py @@ -879,7 +879,7 @@ def shutdown(): return response(error=True, message=message) -@APP.route("/files/download_to_iso", methods=["POST"]) +@APP.route("/files/create_iso", methods=["POST"]) @login_required def download_to_iso(): """ @@ -888,6 +888,7 @@ def download_to_iso(): scsi_id = request.form.get("scsi_id") url = request.form.get("url") iso_type = request.form.get("type") + local_file = request.form.get("file") if iso_type == "HFS": iso_args = ["-hfs"] @@ -907,7 +908,14 @@ def download_to_iso(): message=_("%(iso_type)s is not a valid CD-ROM format.", iso_type=iso_type), ) - process = file_cmd.download_file_to_iso(url, *iso_args) + if url: + process = file_cmd.download_file_to_iso(url, *iso_args) + elif local_file: + server_info = piscsi_cmd.get_server_info() + file_path = Path(server_info["image_dir"]) / local_file + iso_path = Path(str(file_path) + ".iso") + process = file_cmd.generate_iso(iso_path, file_path, *iso_args) + process = ReturnCodeMapper.add_msg(process) if not process["status"]: return response( diff --git a/python/web/tests/api/test_files.py b/python/web/tests/api/test_files.py index 4ad2a4df..1fc4e919 100644 --- a/python/web/tests/api/test_files.py +++ b/python/web/tests/api/test_files.py @@ -328,9 +328,8 @@ def test_download_url_to_dir(env, httpserver, http_client, list_files, delete_fi delete_file(file_name) -# route("/files/download_to_iso", methods=["POST"]) -def test_download_url_to_iso( - env, +# route("/files/create_iso", methods=["POST"]) +def test_create_iso_from_url( httpserver, http_client, list_files, @@ -354,7 +353,7 @@ def test_download_url_to_iso( ) response = http_client.post( - "/files/download_to_iso", + "/files/create_iso", data={ "scsi_id": SCSI_ID, "type": ISO_TYPE, @@ -380,6 +379,47 @@ def test_download_url_to_iso( delete_file(iso_file_name) +# route("/files/create_iso", methods=["POST"]) +def test_create_iso_from_local_file( + http_client, + create_test_image, + list_files, + list_attached_images, + detach_devices, + delete_file, +): + test_file_name = create_test_image() + iso_file_name = f"{test_file_name}.iso" + + ISO_TYPE = "HFS" + + response = http_client.post( + "/files/create_iso", + data={ + "scsi_id": SCSI_ID, + "type": ISO_TYPE, + "file": test_file_name, + }, + ) + + response_data = response.json() + + assert response.status_code == 200 + assert response_data["status"] == STATUS_SUCCESS + assert iso_file_name in list_files() + assert iso_file_name in list_attached_images() + + assert ( + response_data["messages"][0]["message"] + == f"CD-ROM image {iso_file_name} with type {ISO_TYPE} was created " + f"and attached to SCSI ID {SCSI_ID}" + ) + + # Cleanup + detach_devices() + delete_file(iso_file_name) + + # route("/files/diskinfo", methods=["POST"]) def test_show_diskinfo(http_client, create_test_image): test_image = create_test_image()