Merge "Support docker for ota generator"
diff --git a/tools/otagui/.dockerignore b/tools/otagui/.dockerignore
new file mode 100644
index 0000000..e3f4a47
--- /dev/null
+++ b/tools/otagui/.dockerignore
@@ -0,0 +1,2 @@
+node_modules/
+Dockerfile
\ No newline at end of file
diff --git a/tools/otagui/.env.development b/tools/otagui/.env.development
new file mode 100644
index 0000000..c0d6652
--- /dev/null
+++ b/tools/otagui/.env.development
@@ -0,0 +1 @@
+NODE_ENV=development
diff --git a/tools/otagui/.env.production b/tools/otagui/.env.production
new file mode 100644
index 0000000..cbde1cc
--- /dev/null
+++ b/tools/otagui/.env.production
@@ -0,0 +1 @@
+NODE_ENV=production
diff --git a/tools/otagui/.gitignore b/tools/otagui/.gitignore
index b81e39b..323330f 100644
--- a/tools/otagui/.gitignore
+++ b/tools/otagui/.gitignore
@@ -5,6 +5,8 @@
/output
stderr*
stdout*
+yarn.lock
+otatools.zip
# local env files
diff --git a/tools/otagui/Dockerfile b/tools/otagui/Dockerfile
new file mode 100644
index 0000000..5be13ef
--- /dev/null
+++ b/tools/otagui/Dockerfile
@@ -0,0 +1,20 @@
+# build stage
+FROM node:lts-alpine as build-stage
+WORKDIR /app
+COPY package*.json ./
+RUN npm install
+COPY . .
+RUN npm run build
+
+# production stage
+FROM ubuntu:20.04 as production-stage
+RUN apt-get update && apt-get --no-install-recommends install -y python3.9 unzip xxd cgpt unzip openjdk-16-jre-headless zip less
+
+WORKDIR /app
+VOLUME [ "/app/target", "/app/output"]
+COPY otatools.zip .
+COPY --from=build-stage /app/dist ./dist
+COPY --from=build-stage /app/*.py .
+
+EXPOSE 8000
+CMD ["python3.9", "web_server.py"]
\ No newline at end of file
diff --git a/tools/otagui/README.md b/tools/otagui/README.md
index f4ec987..1fb541a 100644
--- a/tools/otagui/README.md
+++ b/tools/otagui/README.md
@@ -27,3 +27,8 @@
python3 web_server.py &
npm run serve
```
+### Run with Docker
+
+1. Build the image `docker build -t zhangxp1998/test .`
+
+2. Run: `docker run -it -p 8000:8000 -v target:/app/target -v output:/app/output zhangxp1998/test:latest`
diff --git a/tools/otagui/ota_interface.py b/tools/otagui/ota_interface.py
index a0ca065..9cdd901 100644
--- a/tools/otagui/ota_interface.py
+++ b/tools/otagui/ota_interface.py
@@ -89,7 +89,7 @@
A class manage the ota generate process
"""
- def __init__(self, path='ota_database.db'):
+ def __init__(self, path='output/ota_database.db'):
"""
create a table if not exist
"""
@@ -156,9 +156,9 @@
'output', 'stdout.'+str(id)), 'w')
try:
proc = subprocess.Popen(
- command, stderr=ferr, stdout=fout)
- except FileNotFoundError:
- logging.error('ota_from_target_files is not set properly')
+ command, stderr=ferr, stdout=fout, shell=False)
+ except FileNotFoundError as e:
+ logging.error('ota_from_target_files is not set properly %s', e)
self.update_status(id, 'Error', int(time.time()))
return
exit_code = proc.wait()
@@ -182,7 +182,7 @@
command += args['extra'].split(' ')
command.append('-k')
command.append(
- '../../../build/make/target/product/security/testkey')
+ 'build/make/target/product/security/testkey')
if args['isIncremental']:
if not os.path.isfile(args['incremental']):
raise FileNotFoundError
diff --git a/tools/otagui/src/services/ApiService.js b/tools/otagui/src/services/ApiService.js
index 3a328d3..b79abf6 100644
--- a/tools/otagui/src/services/ApiService.js
+++ b/tools/otagui/src/services/ApiService.js
@@ -1,15 +1,22 @@
import axios from 'axios'
+const baseURL = process.env.NODE_ENV === 'production' ? '' : 'http://localhost:8000';
+
+console.log(`Build mode: ${process.env.NODE_ENV}, API base url ${baseURL}`);
+
const apiClient = axios.create({
- baseURL: 'http://localhost:8000',
+ baseURL,
withCredentials: false,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
-})
+});
export default {
+ getDownloadURLForJob(job) {
+ return `${baseURL}/download/${job.output}`;
+ },
getJobs() {
return apiClient.get("/check")
},
diff --git a/tools/otagui/src/views/JobDetails.vue b/tools/otagui/src/views/JobDetails.vue
index 11d4265..ad19675 100644
--- a/tools/otagui/src/views/JobDetails.vue
+++ b/tools/otagui/src/views/JobDetails.vue
@@ -63,7 +63,7 @@
},
computed: {
download() {
- return 'http://localhost:8000/download/' + this.job.output
+ return ApiService.getDownloadURLForJob(this.job);
},
},
created() {
diff --git a/tools/otagui/target_lib.py b/tools/otagui/target_lib.py
index 02d62ab..294ace2 100644
--- a/tools/otagui/target_lib.py
+++ b/tools/otagui/target_lib.py
@@ -71,7 +71,7 @@
"""
A class that manages the builds in database.
"""
- def __init__(self, path='ota_database.db'):
+ def __init__(self, path='target/ota_database.db'):
"""
Create a build table if not existing
"""
diff --git a/tools/otagui/web_server.py b/tools/otagui/web_server.py
index e4ddb61..00595e9 100644
--- a/tools/otagui/web_server.py
+++ b/tools/otagui/web_server.py
@@ -30,11 +30,11 @@
from target_lib import TargetLib
import logging
import json
-import pipes
import cgi
-import subprocess
import os
+import stat
import sys
+import zipfile
LOCAL_ADDRESS = '0.0.0.0'
@@ -142,7 +142,10 @@
file_length -= len(self.rfile.readline())
file_length -= len(self.rfile.readline())
file_length -= len(self.rfile.readline())
- output_file.write(self.rfile.read(file_length))
+ BUFFER_SIZE = 1024*1024
+ for offset in range(0, file_length, BUFFER_SIZE):
+ chunk = self.rfile.read(min(file_length-offset, BUFFER_SIZE))
+ output_file.write(chunk)
target_lib.new_build(self.path[6:], file_name)
self._set_response(code=201)
self.wfile.write(
@@ -158,7 +161,6 @@
def run_server(SeverClass=ThreadedHTTPServer, HandlerClass=RequestHandler, port=8000):
- logging.basicConfig(level=logging.DEBUG)
server_address = (LOCAL_ADDRESS, port)
server_instance = SeverClass(server_address, HandlerClass)
try:
@@ -169,12 +171,27 @@
except KeyboardInterrupt:
pass
server_instance.server_close()
+ logging.basicConfig(level=logging.DEBUG)
logging.info('Server has been turned off.')
if __name__ == '__main__':
from sys import argv
+ logging.basicConfig(level=logging.DEBUG)
print(argv)
+ if os.path.exists("otatools.zip"):
+ logging.info("Found otatools.zip, extracting...")
+ EXTRACT_DIR = "./"
+ os.makedirs(EXTRACT_DIR, exist_ok=True)
+ with zipfile.ZipFile("otatools.zip", "r") as zfp:
+ zfp.extractall(EXTRACT_DIR)
+ # mark all binaries executable by owner
+ bin_dir = os.path.join(EXTRACT_DIR, "bin")
+ for filename in os.listdir(bin_dir):
+ os.chmod(os.path.join(bin_dir, filename), stat.S_IRWXU)
+ os.environ["PATH"] = os.path.join(EXTRACT_DIR, "bin") + ":" + os.environ["PATH"]
+ logging.info("Extracted otatools to {}".format(EXTRACT_DIR))
+ logging.info("PATH: %s", os.environ["PATH"])
if not os.path.isdir('target'):
os.mkdir('target', 755)
if not os.path.isdir('output'):