From 80e746b20942e380bc31be65c3cf0f8b74b3ad2b Mon Sep 17 00:00:00 2001 From: Daniel Markstedt Date: Sat, 2 Oct 2021 09:33:31 -0700 Subject: [PATCH] Feature show drive properties in webui (#290) * Implement pad_image method * Reintroduce list_files method, rename the other to list_images * Add iso file padding UI * HDD image UI * Tweak label * Store padded image in the right dir * Show only images that need padding * Support padding MO images * Cleanup * UI flow to show drive properites (#270) * Adjust MO padding to align with current develop * Add docstrings * Remove image padding code * Cleanup * Cleanup --- src/web/file_cmds.py | 70 ++++++++++++++++++++++++++++-------- src/web/templates/index.html | 6 ++++ src/web/web.py | 30 +++++++++++++--- 3 files changed, 88 insertions(+), 18 deletions(-) diff --git a/src/web/file_cmds.py b/src/web/file_cmds.py index 5db0cdc5..ae37d118 100644 --- a/src/web/file_cmds.py +++ b/src/web/file_cmds.py @@ -11,23 +11,33 @@ from settings import * import rascsi_interface_pb2 as proto -def list_files(): - command = proto.PbCommand() - command.operation = proto.PbOperation.DEFAULT_IMAGE_FILES_INFO - - data = send_pb_command(command.SerializeToString()) - result = proto.PbResult() - result.ParseFromString(data) - files = [] - for f in result.image_files_info.image_files: - size_mb = "{:,.1f}".format(f.size / 1024 / 1024) - dtype = proto.PbDeviceType.Name(f.type) - files.append({"name": f.name, "size": f.size, "size_mb": size_mb, "detected_type": dtype}) - - return {"status": result.status, "msg": result.msg, "files": files} +def list_files(file_types): + """ + Takes a list or tuple of str file_types - e.g. ('hda', 'hds') + Returns list of lists files_list: + index 0 is str file name and index 1 is int size in bytes + """ + files_list = [] + for path, dirs, files in os.walk(base_dir): + # Only list selected file types + files = [f for f in files if f.lower().endswith(file_types)] + files_list.extend( + [ + ( + file, + os.path.getsize(os.path.join(path, file)) + ) + for file in files + ] + ) + return files_list def list_config_files(): + """ + Returns a list of RaSCSI config files in base_dir: + list of str files_list + """ files_list = [] for root, dirs, files in os.walk(base_dir): for file in files: @@ -36,6 +46,38 @@ def list_config_files(): return files_list +def list_images(): + """ + Sends a IMAGE_FILES_INFO command to the server + Returns a dict with boolean status, str msg, and list of dicts files + + """ + command = proto.PbCommand() + command.operation = proto.PbOperation.DEFAULT_IMAGE_FILES_INFO + + data = send_pb_command(command.SerializeToString()) + result = proto.PbResult() + result.ParseFromString(data) + + # Get a list of all *.properties files in base_dir + from pathlib import PurePath + prop_data = list_files(PROPERTIES_SUFFIX) + prop_files = [PurePath(x[0]).stem for x in prop_data] + + files = [] + for f in result.image_files_info.image_files: + # Add flag for whether an image file has an associated *.properties file + if PurePath(f.name).stem in prop_files: + prop = True + else: + prop = False + size_mb = "{:,.1f}".format(f.size / 1024 / 1024) + dtype = proto.PbDeviceType.Name(f.type) + files.append({"name": f.name, "size": f.size, "size_mb": size_mb, "detected_type": dtype, "prop": prop}) + + return {"status": result.status, "msg": result.msg, "files": files} + + def create_new_image(file_name, file_type, size): """ Takes str file_name, str file_type, and int size diff --git a/src/web/templates/index.html b/src/web/templates/index.html index 530277c3..5f8fa3b1 100644 --- a/src/web/templates/index.html +++ b/src/web/templates/index.html @@ -140,6 +140,12 @@ + {% if file["prop"] %} +
+ + +
+ {% endif %} {% endfor %} diff --git a/src/web/web.py b/src/web/web.py index 5ad4e830..53b40119 100644 --- a/src/web/web.py +++ b/src/web/web.py @@ -12,8 +12,8 @@ from flask import ( ) from file_cmds import ( - list_files, list_config_files, + list_images, create_new_image, download_file_to_iso, delete_file, @@ -57,8 +57,8 @@ def index(): disk = disk_space() devices = list_devices() device_types=get_device_types() - files=list_files() - config_files=list_config_files() + files = list_images() + config_files = list_config_files() sorted_image_files = sorted(files["files"], key = lambda x: x["name"].lower()) sorted_config_files = sorted(config_files, key = lambda x: x.lower()) @@ -139,7 +139,7 @@ def drive_list(): d["size_mb"] = "{:,.2f}".format(d["size"] / 1024 / 1024) rm_conf.append(d) - files=list_files() + files=list_images() sorted_image_files = sorted(files["files"], key = lambda x: x["name"].lower()) hd_conf = sorted(hd_conf, key = lambda x: x["name"].lower()) cd_conf = sorted(cd_conf, key = lambda x: x["name"].lower()) @@ -595,6 +595,28 @@ def delete(): return redirect(url_for("index")) +@app.route("/files/prop", methods=["POST"]) +def show_properties(): + file_name = request.form.get("image") + from pathlib import PurePath + file_name = str(PurePath(file_name).stem) + "." + PROPERTIES_SUFFIX + + process = read_drive_properties(base_dir + file_name) + prop = process["conf"] + + if process["status"]: + flash("=== DRIVE PROPERTIES ===") + flash(f"File Name: {file_name}") + flash(f"Vendor: {prop['vendor']}") + flash(f"Product: {prop['product']}") + flash(f"Revision: {prop['revision']}") + flash(f"Block Size: {prop['block_size']}") + return redirect(url_for("index")) + else: + flash(f"Failed to get drive properties for {file_name}", "error") + return redirect(url_for("index")) + + if __name__ == "__main__": app.secret_key = "rascsi_is_awesome_insecure_secret_key" app.config["SESSION_TYPE"] = "filesystem"