From 95608c3e289121d39aa41a924e026eb291fe581c Mon Sep 17 00:00:00 2001 From: Maksim Podvarkov Date: Thu, 30 Jan 2020 16:49:38 +0500 Subject: [PATCH 1/4] balena --- .dockerignore | 2 + .gitignore | 1 + Dockerfile.template | 30 ++++ balena_startup.sh | 10 ++ system/server.ini.sample | 8 +- system/server.py | 31 +++-- www/favicon.ico | Bin 0 -> 1150 bytes www/index.html | 286 ++++++++++++++++++++------------------- www/monitor.html | 6 +- 9 files changed, 220 insertions(+), 154 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile.template create mode 100755 balena_startup.sh create mode 100644 www/favicon.ico diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4983dd0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +LICENSE.md +README.md diff --git a/.gitignore b/.gitignore index b27596c..ac08c67 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,4 @@ system/server.ini .remote-sync.json system/osid.desktop system/run_app.sh +system/balena.id diff --git a/Dockerfile.template b/Dockerfile.template new file mode 100644 index 0000000..85fae4b --- /dev/null +++ b/Dockerfile.template @@ -0,0 +1,30 @@ +# base-image for python on any machine using a template variable, +# see more about dockerfile templates here: https://www.balena.io/docs/learn/develop/dockerfile/ +FROM balenalib/%%BALENA_MACHINE_NAME%%-python:3-stretch-run + +# use `install_packages` if you need to install dependencies, +# for instance if you need git, just uncomment the line below. +# RUN install_packages git + +# Set our working directory +WORKDIR /usr/src/app + +# Copy requirements.txt first for better cache on later pushes +COPY requirements.txt requirements.txt + +# pip install python deps from requirements.txt on the resin.io build server +RUN pip install -r requirements.txt + +# Install dd & partprobe +RUN apt-get update && apt-get install -y dcfldd parted + +# This will copy all files in our root to the working directory in the container +COPY . ./ + +RUN chmod +x balena_startup.sh && ./balena_startup.sh + +# Enable udevd so that plugged dynamic hardware devices show up in our container. +ENV UDEV=1 + +# main.py will run when container starts up on the device +CMD ["python", "system/server.py"] diff --git a/balena_startup.sh b/balena_startup.sh new file mode 100755 index 0000000..ac77ba3 --- /dev/null +++ b/balena_startup.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +mkdir -p logs +printf "[DuplicatorSettings] +ImagePath = /data +Host = 0.0.0.0 +SocketPort = 80 +Logs = /usr/src/app/logs +SkeletonLocation = /usr/src/app/www/skeleton.min.css +" > system/server.ini +cat system/balena.id >> system/server.ini diff --git a/system/server.ini.sample b/system/server.ini.sample index 1ec68cb..d7b1e51 100644 --- a/system/server.ini.sample +++ b/system/server.ini.sample @@ -1,6 +1,6 @@ [DuplicatorSettings] -ImagePath = /etc/osid/imgroot -Host = localhost +ImagePath = /data +Host = 0.0.0.0 SocketPort = 80 -Logs = /var/osid -SkeletonLocation = /path_to_folder/osid-python3/www/skeleton.min.css +Logs = /usr/src/app/logs +SkeletonLocation = /usr/src/app/www/skeleton.min.css diff --git a/system/server.py b/system/server.py index a3f0f3a..9cbba5b 100644 --- a/system/server.py +++ b/system/server.py @@ -12,7 +12,6 @@ class SDCardDupe(object): @cherrypy.expose def index(self): - # get host configs from server.ini config_parse = configparser.ConfigParser() config_parse.sections() @@ -23,11 +22,17 @@ def index(self): www_path = "/".join(os.path.dirname(os.path.realpath(__file__)).split("/")[:-1]) + "/www/" html_string = open(www_path + 'index.html', 'r').read() hostname_port = config_parse['DuplicatorSettings']['Host']+":"+config_parse['DuplicatorSettings']['SocketPort'] - html_string = html_string.replace("replacewithhostnamehere",hostname_port) + html_string = html_string.replace("replacewithhostnamehere",'/') css_string = '' html_string = html_string.replace("",css_string) + html_string = html_string.replace("$IMG_ROOT$", config_parse['DuplicatorSettings']['ImagePath']) + if 'BalenaAppId' in config_parse['DuplicatorSettings']: + balena_app_id = config_parse['DuplicatorSettings']['BalenaAppId'] + else: + balena_app_id = "false" + html_string = html_string.replace("$BALENA_APP_ID$", balena_app_id) return html_string @@ -43,7 +48,7 @@ def monitor(self): www_path = "/".join(os.path.dirname(os.path.realpath(__file__)).split("/")[:-1]) + "/www/" html_string = open(www_path + 'monitor.html', 'r').read() hostname_port = config_parse['DuplicatorSettings']['Host']+":"+config_parse['DuplicatorSettings']['SocketPort'] - html_string = html_string.replace("replacewithhostnamehere",hostname_port) + html_string = html_string.replace("replacewithhostnamehere",'/') css_string = '' html_string = html_string.replace("",css_string) @@ -74,7 +79,7 @@ def posted(self,img_file,devices): # assumptions made, there will be no collisions, dont have to pop element # but to reduce the cost of loop, will pop element by creating new list if dev_path in mounted_item: - umount_disk_cmd = "sudo umount %s"%mounted_item + umount_disk_cmd = "umount %s"%mounted_item subprocess.call(umount_disk_cmd.split(" ")) else: reduced_list.append(mounted_item) @@ -97,11 +102,11 @@ def posted(self,img_file,devices): out.close() # Run dd command and output status into the progress.info file - dd_cmd = "sudo dcfldd bs=4M if=" + img_file + dd_cmd = "dcfldd bs=4M if=" + img_file dd_cmd += " of=" + " of=".join(devices) - dd_cmd += " sizeprobe=if statusinterval=1 2>&1 | sudo tee " + dd_cmd += " sizeprobe=if statusinterval=1 2>&1 | tee " dd_cmd += config_parse['DuplicatorSettings']['Logs'] + "/progress.info" - dd_cmd += " && echo \"osid_completed_task\" | sudo tee -a " + dd_cmd += " && echo \"osid_completed_task\" | tee -a " dd_cmd += config_parse['DuplicatorSettings']['Logs'] + "/progress.info" # Planned to run this in localhost only. @@ -114,7 +119,7 @@ def posted(self,img_file,devices): subprocess.Popen(['sudo', 'bash', dd_cmd_file], close_fds=True) hostname_port = config_parse['DuplicatorSettings']['Host']+":"+config_parse['DuplicatorSettings']['SocketPort'] - monitor_url = "http://" + hostname_port + "/monitor"; + monitor_url = "/monitor"; html_string = "" @@ -140,7 +145,7 @@ def getStatus(self): out.close() # pull data from progress.info file and feed back to call - cat_cmd = "sudo cat "+ progress_file + cat_cmd = "cat "+ progress_file cat_output = str(subprocess.check_output(cat_cmd, shell=True).decode("utf-8")) if "records in" in cat_output and "records out" in cat_output and "osid_completed_task" in cat_output: percentage = "100%" @@ -163,7 +168,7 @@ def getDevices(self): list_devices = [] # Refresh partition to discover all available medias - refresh_disk_cmd = "sudo /sbin/partprobe" + refresh_disk_cmd = "/sbin/partprobe" subprocess.check_output(refresh_disk_cmd, shell=True) # command to get a list of devices on OS @@ -235,10 +240,14 @@ def getImages(self): 'log.access_file' : config_parse['DuplicatorSettings']['Logs']+"/access.log", 'log.screen': False, 'tools.sessions.on': True + }, + '/favicon.ico':{ + 'tools.staticfile.on': True, + 'tools.staticfile.filename': "/".join(os.path.dirname(os.path.realpath(__file__)).split("/")[:-1]) + "/www/favicon.ico" } } # create a daemon for cherrpy so it will create a thread when started - cherrypy.process.plugins.Daemonizer(cherrypy.engine).subscribe() + #cherrypy.process.plugins.Daemonizer(cherrypy.engine).subscribe() cherrypy.quickstart(SDCardDupe(), '/', conf) diff --git a/www/favicon.ico b/www/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d3cd2d9596f37eda8ca151516d412e6800046394 GIT binary patch literal 1150 zcmZ{jX-HI26o5}!L>rVzV%j1twn5prj3PE~xo??yI?rX)#u>+4a!bdxvarS?sMPi- zXfYz%egqY!RAf;7h$1VS90}uSmR(L{~EXR zZ?S+i4LYTwo*XGhwb&rosxBD=|7mVk138kz>J_@b?d1B=#j3DExQvy;Roo)_a2NL# zy?oaIG;6iG;=?&o_~hrLI<{3{*WM63wLoR_W_%^@91W=7b7Xw zuEqv(WJ)SzNGzK8{u1#xZkF6wEFQ)^mY=xS@(WAEqr_EHo;wErF-vB?nFBQ*# zi&a+C@lVL_#X36Q=)FWdMtR!&doSNjeY9W=e;*x^UXjPP2KX(^2ToSxCVr?~xP(5- zZ`?<9Zxe3#`!{r-Wq|tcB>urrmZZ6;#sII&DUc>7gygaETW-3y2L7eLZmNs!;R3P4 zxPyC7@1Yr;toW9utO>Ep@d4gYM(#h?RVCaWE*4v{NIXF2-}LufDx9S{t{b%sXULo@ zOQH{K!pLMI=#n{Xt8k>NOudF4xfz?dPjv77SSTODGAr4{`tDS=I!tE?6KDV>HyKh> z%~A0O)ko2t`Di+wi5WHxGp!oNp3K0N_wq2VRqfIAq$tIm@*l4&W;hHpf|7SjCl{#K11E;}72=|o9!%P+oM?w>L3U-V2D_X9IWZeTO()ZO7rvvo zS00RbQ-B-J>0e^b+P_4SZrB!54%+u-n_@x@W_0MJI}%MZH`R(wl;i383+a7v?OK;m z%Gtyci!H8A>so(4y>H{Gw5KTztSKwWG;=&} - rPi-Dupe - - - - - + + + + + + + + + +
+
+ Open Source Image Duplicator - Python v1.1.1 +
+ +
+
+ + + +
+ + +
diff --git a/www/monitor.html b/www/monitor.html index 6b5c15f..7f3e560 100644 --- a/www/monitor.html +++ b/www/monitor.html @@ -3,7 +3,7 @@ - rPi-Dupe + RPI-Duplicator @@ -24,7 +24,7 @@ var elem = document.getElementById("progress_bar"); var width = 0; - var id = setInterval(frame, 100); + var id = setInterval(frame, 5000); function frame() { if (width >= 100) { @@ -33,7 +33,7 @@ var xmlhttp = new XMLHttpRequest(); // URL replacewithhostnamehere will be changed based on configuration file by CherryPy Server - var url = "http://" + "replacewithhostnamehere" + "/getStatus"; + var url = "/getStatus"; // Call the api and get the status until complete. xmlhttp.onreadystatechange = function() { From 5c8d3e1b345e63231f618eb6ff32059cbde29b76 Mon Sep 17 00:00:00 2001 From: Maksim Podvarkov Date: Fri, 31 Jan 2020 13:45:08 +0500 Subject: [PATCH 2/4] balena --- .dockerignore | 3 +++ .gitignore | 2 +- README.md | 4 ++++ system/balena.id | 1 + system/server.ini.sample | 8 ++++---- 5 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 system/balena.id diff --git a/.dockerignore b/.dockerignore index 4983dd0..538e765 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,5 @@ LICENSE.md README.md +/system/ +!/system/server.py +!/system/balena.id diff --git a/.gitignore b/.gitignore index ac08c67..c60603d 100644 --- a/.gitignore +++ b/.gitignore @@ -105,4 +105,4 @@ system/server.ini .remote-sync.json system/osid.desktop system/run_app.sh -system/balena.id +#system/balena.id diff --git a/README.md b/README.md index e895f78..2519657 100755 --- a/README.md +++ b/README.md @@ -108,6 +108,10 @@ Then proceed to modify those files to match the system paths for the items in th * Just make sure the path for the run_app.sh script is defined properly. * if you use OSID on headless Raspberry, this file is useless. +### Balena cloud deployment +change `balenaAppId` variable in system/balena.id to your `` +Deploy app to balena cloud + ### Usage #### Accepted image file diff --git a/system/balena.id b/system/balena.id new file mode 100644 index 0000000..db5c3b3 --- /dev/null +++ b/system/balena.id @@ -0,0 +1 @@ +balenaAppId="" diff --git a/system/server.ini.sample b/system/server.ini.sample index d7b1e51..1ec68cb 100644 --- a/system/server.ini.sample +++ b/system/server.ini.sample @@ -1,6 +1,6 @@ [DuplicatorSettings] -ImagePath = /data -Host = 0.0.0.0 +ImagePath = /etc/osid/imgroot +Host = localhost SocketPort = 80 -Logs = /usr/src/app/logs -SkeletonLocation = /usr/src/app/www/skeleton.min.css +Logs = /var/osid +SkeletonLocation = /path_to_folder/osid-python3/www/skeleton.min.css From c71c49e96c2383388f61ce0c07f880233c2ead3d Mon Sep 17 00:00:00 2001 From: Maksim Podvarkov Date: Mon, 3 Feb 2020 11:29:51 +0500 Subject: [PATCH 3/4] Fix return to start link --- www/monitor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/monitor.html b/www/monitor.html index 7f3e560..9e5d89f 100644 --- a/www/monitor.html +++ b/www/monitor.html @@ -48,7 +48,7 @@ if (width == 100) { completed_html = "Duplication Complete: " + array.img_name + "
" - completed_html += "Return to Start" + completed_html += "Return to Start" document.getElementById("StatusMessage").innerHTML = completed_html } else { document.getElementById("StatusMessage").innerHTML = "Time Remaining: " + array.time_remaining From 54a3564d67e3716fa04960677ae0630baa9f99b8 Mon Sep 17 00:00:00 2001 From: Maksim Podvarkov Date: Mon, 3 Feb 2020 11:53:11 +0500 Subject: [PATCH 4/4] monitor.html: Use setTimeout instead of setInterval in polling function. Change variable names Use 5000 ms delay --- www/monitor.html | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/www/monitor.html b/www/monitor.html index 9e5d89f..e9f8439 100644 --- a/www/monitor.html +++ b/www/monitor.html @@ -20,15 +20,15 @@ @@ -90,7 +92,7 @@

Progress