From ea4486d1c099bdda42a687f97b8e7f0c766c5fbc Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Sat, 31 Jul 2021 10:52:09 -0500 Subject: [PATCH] Speed up web uploads and various fixes (#158) * Move to bjoern * Stream upload * wip * Streams * check for filename * Allow easyinstall to be scripted * Tell user we're done * show help * ignore hfdisk * fix var * Allow override of remote by setting GIT_REMOTE, default to origin * Better handling of local changes * Give user more info * Fix #156 - show all supported types in web interface * *.mos does not seem to be valid - ractl throws error * Try some minor optomizations Error handling --- .gitignore | 1 + easyinstall.sh | 161 +++++++++++++++++++++-------------- src/web/file_cmds.py | 4 +- src/web/ractl_cmds.py | 6 +- src/web/requirements.txt | 4 +- src/web/start.sh | 3 +- src/web/templates/index.html | 11 ++- src/web/web.py | 56 +++++++----- 8 files changed, 153 insertions(+), 93 deletions(-) diff --git a/.gitignore b/.gitignore index e17ba71f..b2368f8d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ core __pycache__ src/web/current src/oled_monitor/current +src/raspberrypi/hfdisk/ diff --git a/easyinstall.sh b/easyinstall.sh index c88bed29..d9cc1505 100755 --- a/easyinstall.sh +++ b/easyinstall.sh @@ -25,6 +25,7 @@ HFS_FORMAT=/usr/bin/hformat HFDISK_BIN=/usr/bin/hfdisk LIDO_DRIVER=~/RASCSI/lido-driver.img GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +GIT_REMOTE=${GIT_REMOTE:-origin} function initialChecks() { currentUser=$(whoami) @@ -41,7 +42,7 @@ function initialChecks() { } function installPackages() { - sudo apt-get update && sudo apt install git libspdlog-dev libpcap-dev genisoimage python3 python3-venv nginx libpcap-dev protobuf-compiler bridge-utils -y + sudo apt-get update && sudo apt install git libspdlog-dev libpcap-dev genisoimage python3 python3-venv nginx libpcap-dev protobuf-compiler bridge-utils python3-dev libev-dev libevdev2 -y } # install all dependency packages for RaSCSI Service @@ -102,12 +103,22 @@ function installRaScsiWebInterface() { } function updateRaScsiGit() { - echo "Updating checked out branch $GIT_BRANCH" + echo "Updating checked out branch $GIT_REMOTE/$GIT_BRANCH" cd ~/RASCSI - git fetch origin - git stash - git rebase origin/$GIT_BRANCH - git stash apply + stashed=0 + if [[ $(git diff --stat) != '' ]]; then + echo 'There are local changes, we will stash and reapply them.' + git stash + stashed=1 + fi + + git fetch $GIT_REMOTE + git rebase $GIT_REMOTE/$GIT_BRANCH + + if [ $stashed -eq 1 ]; then + echo "Reapplying local changes..." + git stash apply + fi } function updateRaScsi() { @@ -128,6 +139,7 @@ function updateRaScsiWebInterface() { updateRaScsiGit sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html + echo "Restarting rascsi-web services..." sudo systemctl restart rascsi-web sudo systemctl restart nginx } @@ -150,7 +162,7 @@ function createDriveCustom() { read driveName done - createDrive $driveSize "$driveName" + createDrive "$driveSize" "$driveName" } function formatDrive() { @@ -167,17 +179,17 @@ function formatDrive() { git clone git://www.codesrc.com/git/hfdisk.git cd hfdisk make - + sudo cp hfdisk /usr/bin/hfdisk fi # Inject hfdisk commands to create Drive with correct partitions - (echo i; echo ; echo C; echo ; echo 32; echo "Driver_Partition"; echo "Apple_Driver"; echo C; echo ; echo ; echo "${volumeName}"; echo "Apple_HFS"; echo w; echo y; echo p;) | $HFDISK_BIN "$diskPath" + (echo i; echo ; echo C; echo ; echo 32; echo "Driver_Partition"; echo "Apple_Driver"; echo C; echo ; echo ; echo "${volumeName}"; echo "Apple_HFS"; echo w; echo y; echo p;) | $HFDISK_BIN "$diskPath" partitionOk=$? if [ $partitionOk -eq 0 ]; then if [ ! -f $LIDO_DRIVER ];then - echo "Lido driver couldn't be found. Make sure RASCSI is up-to-date with git pull" + echo "Lido driver couldn't be found. Make sure RaSCSI is up-to-date with git pull" return 1 fi @@ -217,7 +229,7 @@ function createDrive() { driveName=$2 mkdir -p $VIRTUAL_DRIVER_PATH drivePath="${VIRTUAL_DRIVER_PATH}/${driveSize}MB.hda" - + if [ ! -f $drivePath ]; then echo "Creating a ${driveSize}MB Drive" truncate --size ${driveSize}m $drivePath @@ -230,6 +242,75 @@ function createDrive() { fi } +function runChoice() { + case $1 in + 0) + echo "Installing RaSCSI Service + Web interface" + installRaScsi + installRaScsiWebInterface + createDrive600MB + showRaScsiStatus + echo "Installing RaSCSI Service + Web interface - Complete!" + ;; + 1) + echo "Installing RaSCSI Service" + installRaScsi + showRaScsiStatus + echo "Installing RaSCSI Service - Complete!" + ;; + 2) + echo "Installing RaSCSI Web interface" + installRaScsiWebInterface + echo "Installing RaSCSI Web interface - Complete!" + ;; + 3) + echo "Updating RaSCSI Service + Web interface" + updateRaScsi + updateRaScsiWebInterface + showRaScsiStatus + echo "Updating RaSCSI Service + Web interface - Complete!" + ;; + 4) + echo "Updating RaSCSI Service" + updateRaScsi + showRaScsiStatus + echo "Updating RaSCSI Service - Complete!" + ;; + 5) + echo "Updating RaSCSI Web interface" + updateRaScsiWebInterface + echo "Updating RaSCSI Web interface - Complete!" + ;; + 6) + echo "Creating a 600MB drive" + createDrive600MB + echo "Creating a 600MB drive - Complete!" + ;; + 7) + echo "Creating a custom drive" + createDriveCustom + echo "Creating a custom drive - Complete!" + ;; + -h|--help|h|help) + showMenu + ;; + *) + echo "${1} is not a valid option, exiting..." + exit 1 + esac +} + +function readChoice() { + choice=-1 + + until [ $choice -ge "0" ] && [ $choice -le "7" ]; do + echo -n "Enter your choice (0-7) or CTRL-C to exit: " + read -r choice + done + + runChoice "$choice" +} + function showMenu() { echo "" echo "Choose among the following options:" @@ -244,60 +325,14 @@ function showMenu() { echo "CREATE EMPTY DRIVE" echo " 6) 600MB drive (recommended)" echo " 7) custom drive size (up to 4000MB)" - - - choice=-1 - - until [ $choice -ge "0" ] && [ $choice -le "7" ]; do - echo -n "Enter your choice (0-7) or CTRL-C to exit: " - read -r choice - done - - - case $choice in - 0) - echo "Installing RaSCSI Service + Web interface" - installRaScsi - installRaScsiWebInterface - createDrive600MB - showRaScsiStatus - ;; - 1) - echo "Installing RaSCSI Service" - installRaScsi - showRaScsiStatus - ;; - 2) - echo "Installing RaSCSI Web interface" - installRaScsiWebInterface - ;; - 3) - echo "Updating RaSCSI Service + Web interface" - updateRaScsi - updateRaScsiWebInterface - showRaScsiStatus - ;; - 4) - echo "Updating RaSCSI Service" - updateRaScsi - showRaScsiStatus - ;; - 5) - echo "Updating RaSCSI Web interface" - updateRaScsiWebInterface - ;; - 6) - echo "Creating a 600MB drive" - createDrive600MB - ;; - 7) - echo "Creating a custom drive" - createDriveCustom - ;; - esac } showRaSCSILogo initialChecks -showMenu +if [ -z "${1}" ]; then # $1 is unset, show menu + showMenu + readChoice +else + runChoice "$1" +fi diff --git a/src/web/file_cmds.py b/src/web/file_cmds.py index 7ca5d19e..9ff3c8f1 100644 --- a/src/web/file_cmds.py +++ b/src/web/file_cmds.py @@ -6,8 +6,8 @@ import time from ractl_cmds import attach_image from settings import * -valid_file_types = ["*.hda", "*.iso", "*.cdr"] -valid_file_types = r"|".join([fnmatch.translate(x) for x in valid_file_types]) +valid_file_suffix = ["*.hda", "*.hdn", "*.hdi", "*.nhd", "*.hdf", "*.hds", "*.iso", "*.cdr", "*.zip"] +valid_file_types = r"|".join([fnmatch.translate(x) for x in valid_file_suffix]) def create_new_image(file_name, type, size): diff --git a/src/web/ractl_cmds.py b/src/web/ractl_cmds.py index fbc9cef5..de288520 100644 --- a/src/web/ractl_cmds.py +++ b/src/web/ractl_cmds.py @@ -1,12 +1,12 @@ import fnmatch -import os import subprocess import re from settings import * -valid_file_types = ["*.hda", "*.iso", "*.cdr", "*.zip"] -valid_file_types = r"|".join([fnmatch.translate(x) for x in valid_file_types]) + +valid_file_suffix = ["*.hda", "*.hdn", "*.hdi", "*.nhd", "*.hdf", "*.hds", "*.iso", "*.cdr", "*.zip"] +valid_file_types = r"|".join([fnmatch.translate(x) for x in valid_file_suffix]) # List of SCSI ID's you'd like to exclude - eg if you are on a Mac, the System is usually 7 EXCLUDE_SCSI_IDS = [7] diff --git a/src/web/requirements.txt b/src/web/requirements.txt index ab184b10..5983c740 100644 --- a/src/web/requirements.txt +++ b/src/web/requirements.txt @@ -1,5 +1,6 @@ +bjoern==3.1.0 click==7.1.2 -Flask==2.0.0 +Flask==2.0.1 itsdangerous==2.0.0 Jinja2==3.0.0 machfs==1.2.4 @@ -7,6 +8,5 @@ macresources==1.2 MarkupSafe==2.0.0 rsrcfork==1.8.0 waitress==1.4.4 -Werkzeug==2.0.0 zope.event==4.5.0 zope.interface==5.1.2 diff --git a/src/web/start.sh b/src/web/start.sh index ee0b1b37..de50c04a 100755 --- a/src/web/start.sh +++ b/src/web/start.sh @@ -37,6 +37,7 @@ if ! test -e venv; then echo "Activating venv" source venv/bin/activate echo "Installing requirements.txt" + pip install wheel pip install -r requirements.txt git rev-parse HEAD > current fi @@ -55,4 +56,4 @@ else fi echo "Starting web server..." -python3 web.py \ No newline at end of file +python3 web.py diff --git a/src/web/templates/index.html b/src/web/templates/index.html index d7bbccdd..33130f01 100644 --- a/src/web/templates/index.html +++ b/src/web/templates/index.html @@ -153,7 +153,7 @@
-
+ @@ -161,6 +161,12 @@
+
@@ -216,7 +222,6 @@ - @@ -253,4 +258,4 @@ {% block footer %}
{{version}}
Logs
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/web/web.py b/src/web/web.py index 0699443c..01c2c528 100644 --- a/src/web/web.py +++ b/src/web/web.py @@ -1,5 +1,7 @@ +import io +import re + from flask import Flask, render_template, request, flash, url_for, redirect, send_file -from werkzeug.utils import secure_filename from file_cmds import ( create_new_image, @@ -22,6 +24,8 @@ from ractl_cmds import ( daynaport_setup_bridge, list_config_files, detach_all, + valid_file_suffix, + valid_file_types ) from settings import * @@ -129,12 +133,15 @@ def attach(): scsi_id = request.form.get("scsi_id") # Validate image type by suffix - if file_name.lower().endswith(".iso") or file_name.lower().endswith("iso"): - image_type = "cd" - elif file_name.lower().endswith(".hda"): - image_type = "hd" + print("file_name", file_name) + print("valid_file_types: ", valid_file_types) + if re.match(valid_file_types, file_name): + if file_name.lower().endswith("iso"): + image_type = "cd" + else: + image_type = "hd" else: - flash("Unknown file type. Valid files are .iso, .hda, .cdr", "error") + flash(f"Unknown file type. Valid files are: {', '.join(valid_file_suffix)}", "error") return redirect(url_for("index")) process = attach_image(scsi_id, file_name, image_type) @@ -228,25 +235,35 @@ def download_img(): return redirect(url_for("index")) -@app.route("/files/upload", methods=["POST"]) -def upload_file(): - if "file" not in request.files: - flash("No file part", "error") +@app.route("/files/upload/", methods=["POST"]) +def upload_file(filename): + if not filename: + flash("No file provided.", "error") return redirect(url_for("index")) - file = request.files["file"] - if file: - filename = secure_filename(file.filename) - file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename)) - return redirect(url_for("index", filename=filename)) + + file_path = os.path.join(app.config["UPLOAD_FOLDER"], filename) + if os.path.isfile(file_path): + flash(f"{filename} already exists.", "error") + return redirect(url_for("index")) + + binary_new_file = "bx" + with open(file_path, binary_new_file, buffering=io.DEFAULT_BUFFER_SIZE) as f: + chunk_size = io.DEFAULT_BUFFER_SIZE + while True: + chunk = request.stream.read(chunk_size) + if len(chunk) == 0: + break + f.write(chunk) + return redirect(url_for("index", filename=filename)) @app.route("/files/create", methods=["POST"]) def create_file(): file_name = request.form.get("file_name") size = request.form.get("size") - type = request.form.get("type") + file_type = request.form.get("type") - process = create_new_image(file_name, type, size) + process = create_new_image(file_name, file_type, size) if process.returncode == 0: flash("Drive created") return redirect(url_for("index")) @@ -293,6 +310,7 @@ if __name__ == "__main__": os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True) app.config["MAX_CONTENT_LENGTH"] = MAX_FILE_SIZE - from waitress import serve + import bjoern + print("Serving rascsi-web...") + bjoern.run(app, "0.0.0.0", 8080) - serve(app, host="0.0.0.0", port=8080)