From c887edfc8c9956aa9dcac3764abe6cef16ffb596 Mon Sep 17 00:00:00 2001 From: Daniel Markstedt Date: Sun, 19 Dec 2021 15:50:03 -0800 Subject: [PATCH] Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition --- easyinstall.sh | 12 --------- src/oled_monitor/monitor_rascsi.service | 3 ++- src/oled_monitor/rascsi_oled_monitor.py | 20 +++++++-------- src/oled_monitor/socket_cmds.py | 4 ++- src/oled_monitor/start.sh | 2 -- src/web/pi_cmds.py | 14 ----------- src/web/ractl_cmds.py | 8 ------ src/web/socket_cmds.py | 4 ++- src/web/templates/index.html | 9 ++----- src/web/web.py | 33 ------------------------- 10 files changed, 20 insertions(+), 89 deletions(-) diff --git a/easyinstall.sh b/easyinstall.sh index 3c586474..f12ad150 100755 --- a/easyinstall.sh +++ b/easyinstall.sh @@ -113,18 +113,6 @@ function installRaScsiWebInterface() { sudo usermod -a -G $USER www-data - if [[ `sudo grep -c "rascsi" /etc/sudoers` -eq 0 ]]; then - sudo bash -c 'echo " -# Allow the web server to restart the rascsi service -www-data ALL=NOPASSWD: /bin/systemctl restart rascsi.service -www-data ALL=NOPASSWD: /bin/systemctl stop rascsi.service -# Allow the web server to reboot the raspberry pi -www-data ALL=NOPASSWD: /sbin/shutdown, /sbin/reboot -" >> /etc/sudoers' - else - echo "The sudoers file is already modified for rascsi-web." - fi - sudo systemctl reload nginx || true } diff --git a/src/oled_monitor/monitor_rascsi.service b/src/oled_monitor/monitor_rascsi.service index 1648a2d6..220b8e8b 100644 --- a/src/oled_monitor/monitor_rascsi.service +++ b/src/oled_monitor/monitor_rascsi.service @@ -5,9 +5,10 @@ After=network.target rascsi.service [Service] Type=simple Restart=always +RestartSec=2s ExecStart=/home/pi/RASCSI/src/oled_monitor/start.sh -ExecStop=/bin/echo "Shutting down the OLED Monitor gracefully..." ExecStop=/bin/pkill --signal 2 -f "python3 rascsi_oled_monitor.py" +# Sleep 2s as a crude way for the python interrupt handler to take effect and show the shutdown splash ExecStop=/bin/sleep 2 SyslogIdentifier=RASCSIMON diff --git a/src/oled_monitor/rascsi_oled_monitor.py b/src/oled_monitor/rascsi_oled_monitor.py index ce7cf12e..00d67258 100755 --- a/src/oled_monitor/rascsi_oled_monitor.py +++ b/src/oled_monitor/rascsi_oled_monitor.py @@ -119,6 +119,11 @@ LINE_SPACING = 8 # Some other nice fonts to try: http://www.dafont.com/bitmap.php FONT = ImageFont.truetype('type_writer.ttf', FONT_SIZE) +# Load a bitmap image for start and stop splash screens and convert to monocrome +# Make sure the splash bitmap image is in the same dir as this script +SPLASH_START = Image.open(f"splash_start_{HEIGHT}.bmp").convert("1") +SPLASH_STOP = Image.open(f"splash_stop_{HEIGHT}.bmp").convert("1") + IP_ADDR, HOSTNAME = get_ip_and_host() @@ -163,23 +168,18 @@ def formatted_output(): def start_splash(): """ Displays a splash screen for the startup sequence - Make sure the splash bitmap image is in the same dir as this script """ - splash = Image.open(f"splash_start_{HEIGHT}.bmp").convert("1") - DRAW.bitmap((0, 0), splash) - OLED.image(splash) + DRAW.bitmap((0, 0), SPLASH_START, fill=0) + OLED.image(SPLASH_START) OLED.show() - sleep(6) + sleep(4) def stop_splash(): """ Displays a splash screen for the shutdown sequence - Make sure the splash bitmap image is in the same dir as this script """ - DRAW.rectangle((0, 0, WIDTH, HEIGHT), outline=0, fill=0) - splash = Image.open(f"splash_stop_{HEIGHT}.bmp").convert("1") - DRAW.bitmap((0, 0), splash) - OLED.image(splash) + DRAW.bitmap((0, 0), SPLASH_STOP, fill=0) + OLED.image(SPLASH_STOP) OLED.show() # Show a startup splash bitmap image before starting the main loop diff --git a/src/oled_monitor/socket_cmds.py b/src/oled_monitor/socket_cmds.py index f3cdb9e5..b953e301 100644 --- a/src/oled_monitor/socket_cmds.py +++ b/src/oled_monitor/socket_cmds.py @@ -5,6 +5,7 @@ and receiving results from the RaSCSI backend import socket from struct import pack, unpack +from time import sleep def send_pb_command(payload): """ @@ -16,7 +17,7 @@ def send_pb_command(payload): port = 6868 counter = 0 - tries = 100 + tries = 20 error_msg = "" while counter < tries: @@ -29,6 +30,7 @@ def send_pb_command(payload): print("The RaSCSI service is not responding - attempt %s/%s", str(counter), str(tries)) error_msg = str(error) + sleep(0.2) exit(error_msg) diff --git a/src/oled_monitor/start.sh b/src/oled_monitor/start.sh index 712ad825..2b4dac19 100755 --- a/src/oled_monitor/start.sh +++ b/src/oled_monitor/start.sh @@ -60,9 +60,7 @@ fi # Compiler flags needed for gcc v10 and up if [[ `gcc --version | awk '/gcc/' | awk -F ' ' '{print $3}' | awk -F '.' '{print $1}'` -ge 10 ]]; then - echo -n "gcc 10 or later detected. Will compile with the following flags: " COMPILER_FLAGS="-fcommon" - echo $COMPILER_FLAGS fi # Test for two known broken venv states diff --git a/src/web/pi_cmds.py b/src/web/pi_cmds.py index 7ffb82b2..5e44e8a5 100644 --- a/src/web/pi_cmds.py +++ b/src/web/pi_cmds.py @@ -8,20 +8,6 @@ import logging from settings import AUTH_GROUP -def systemd_service(service, action): - """ - Takes (str) service and (str) action - Action can be any that systemctl supports, ex. start/stop/restart/show - Returns (dict) with (bool) status, (str) msg, (str) err - """ - proc = asyncio.run(run_async(f"sudo /bin/systemctl {action} {service}")) - return { - "status": proc["returncode"] == 0, - "msg": proc["stdout"], - "err": proc["stderr"], - } - - def running_env(): """ Returns (str) git and (str) env diff --git a/src/web/ractl_cmds.py b/src/web/ractl_cmds.py index 26ce811d..b3782c74 100644 --- a/src/web/ractl_cmds.py +++ b/src/web/ractl_cmds.py @@ -3,7 +3,6 @@ Module for commands sent to the RaSCSI backend service. """ from settings import REMOVABLE_DEVICE_TYPES -from pi_cmds import systemd_service from socket_cmds import send_pb_command import rascsi_interface_pb2 as proto @@ -363,13 +362,6 @@ def shutdown_pi(mode): Takes (str) mode as an argument. Returns (bool) status and (str) msg. """ - # This section proactively stops the monitor_rascsi systemd service, if running - # Otherwise, the monitor_rascsi script's interrupt handler won't take effect - monitor_service = "monitor_rascsi.service" - monitor_status = systemd_service(monitor_service, "show") - if "ActiveState=active" in monitor_status["msg"]: - systemd_service(monitor_service, "stop") - command = proto.PbCommand() command.operation = proto.PbOperation.SHUT_DOWN command.params["mode"] = str(mode) diff --git a/src/web/socket_cmds.py b/src/web/socket_cmds.py index 91704d3a..ba540e76 100644 --- a/src/web/socket_cmds.py +++ b/src/web/socket_cmds.py @@ -4,6 +4,7 @@ Module for sending and receiving data over a socket connection with the RaSCSI b import logging from flask import abort +from time import sleep def send_pb_command(payload): """ @@ -15,7 +16,7 @@ def send_pb_command(payload): port = 6868 counter = 0 - tries = 100 + tries = 20 error_msg = "" import socket @@ -29,6 +30,7 @@ def send_pb_command(payload): logging.warning("The RaSCSI service is not responding - attempt %s/%s", str(counter), str(tries)) error_msg = str(error) + sleep(0.2) logging.error(error_msg) diff --git a/src/web/templates/index.html b/src/web/templates/index.html index 157b2479..48c87bcc 100644 --- a/src/web/templates/index.html +++ b/src/web/templates/index.html @@ -619,8 +619,8 @@ Raspberry Pi Operations @@ -635,11 +635,6 @@ -
-
- -
-
diff --git a/src/web/web.py b/src/web/web.py index c004af12..e8550414 100644 --- a/src/web/web.py +++ b/src/web/web.py @@ -38,7 +38,6 @@ from file_cmds import ( ) from pi_cmds import ( running_env, - systemd_service, running_proc, is_bridge_setup, disk_space, @@ -661,38 +660,6 @@ def unreserve_id(): flash(process["msg"], "error") return redirect(url_for("index")) -@APP.route("/rascsi/restart", methods=["POST"]) -@login_required -def rascsi_restart(): - """ - Restarts the RaSCSI backend service - """ - service = "rascsi.service" - monitor_service = "monitor_rascsi.service" - rascsi_status = systemd_service(service, "show") - if rascsi_status["status"] and "ActiveState=active" not in rascsi_status["msg"]: - flash( - f"Failed to restart {service} because it is inactive. " - "You are probably running RaSCSI as a regular process.", "error" - ) - return redirect(url_for("index")) - - monitor_status = systemd_service(monitor_service, "show") - restart_proc = systemd_service(service, "restart") - if restart_proc["status"]: - flash(f"Restarted {service}") - restart_monitor = systemd_service(monitor_service, "restart") - if restart_monitor["status"] and "ActiveState=active" in monitor_status["msg"]: - flash(f"Restarted {monitor_service}") - elif not restart_monitor["status"] and "ActiveState=active" in monitor_status["msg"]: - flash(f"Failed to restart {monitor_service}:", "error") - return redirect(url_for("index")) - - restart_monitor = systemd_service("monitor_rascsi.service", "restart") - flash(f"Failed to restart {service}:", "error") - flash(restart_proc["err"], "error") - return redirect(url_for("index")) - @APP.route("/pi/reboot", methods=["POST"]) @login_required