Merge "Support docker for ota generator"
This commit is contained in:
2
tools/otagui/.dockerignore
Normal file
2
tools/otagui/.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
Dockerfile
|
||||||
1
tools/otagui/.env.development
Normal file
1
tools/otagui/.env.development
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NODE_ENV=development
|
||||||
1
tools/otagui/.env.production
Normal file
1
tools/otagui/.env.production
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NODE_ENV=production
|
||||||
2
tools/otagui/.gitignore
vendored
2
tools/otagui/.gitignore
vendored
@@ -5,6 +5,8 @@ node_modules
|
|||||||
/output
|
/output
|
||||||
stderr*
|
stderr*
|
||||||
stdout*
|
stdout*
|
||||||
|
yarn.lock
|
||||||
|
otatools.zip
|
||||||
|
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
|
|||||||
20
tools/otagui/Dockerfile
Normal file
20
tools/otagui/Dockerfile
Normal file
@@ -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"]
|
||||||
@@ -27,3 +27,8 @@ Finally, run the python http-server and vue.js server:
|
|||||||
python3 web_server.py &
|
python3 web_server.py &
|
||||||
npm run serve
|
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`
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class ProcessesManagement:
|
|||||||
A class manage the ota generate process
|
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
|
create a table if not exist
|
||||||
"""
|
"""
|
||||||
@@ -156,9 +156,9 @@ class ProcessesManagement:
|
|||||||
'output', 'stdout.'+str(id)), 'w')
|
'output', 'stdout.'+str(id)), 'w')
|
||||||
try:
|
try:
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
command, stderr=ferr, stdout=fout)
|
command, stderr=ferr, stdout=fout, shell=False)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError as e:
|
||||||
logging.error('ota_from_target_files is not set properly')
|
logging.error('ota_from_target_files is not set properly %s', e)
|
||||||
self.update_status(id, 'Error', int(time.time()))
|
self.update_status(id, 'Error', int(time.time()))
|
||||||
return
|
return
|
||||||
exit_code = proc.wait()
|
exit_code = proc.wait()
|
||||||
@@ -182,7 +182,7 @@ class ProcessesManagement:
|
|||||||
command += args['extra'].split(' ')
|
command += args['extra'].split(' ')
|
||||||
command.append('-k')
|
command.append('-k')
|
||||||
command.append(
|
command.append(
|
||||||
'../../../build/make/target/product/security/testkey')
|
'build/make/target/product/security/testkey')
|
||||||
if args['isIncremental']:
|
if args['isIncremental']:
|
||||||
if not os.path.isfile(args['incremental']):
|
if not os.path.isfile(args['incremental']):
|
||||||
raise FileNotFoundError
|
raise FileNotFoundError
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
import axios from 'axios'
|
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({
|
const apiClient = axios.create({
|
||||||
baseURL: 'http://localhost:8000',
|
baseURL,
|
||||||
withCredentials: false,
|
withCredentials: false,
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
getDownloadURLForJob(job) {
|
||||||
|
return `${baseURL}/download/${job.output}`;
|
||||||
|
},
|
||||||
getJobs() {
|
getJobs() {
|
||||||
return apiClient.get("/check")
|
return apiClient.get("/check")
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
download() {
|
download() {
|
||||||
return 'http://localhost:8000/download/' + this.job.output
|
return ApiService.getDownloadURLForJob(this.job);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class TargetLib:
|
|||||||
"""
|
"""
|
||||||
A class that manages the builds in database.
|
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
|
Create a build table if not existing
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ from ota_interface import ProcessesManagement
|
|||||||
from target_lib import TargetLib
|
from target_lib import TargetLib
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import pipes
|
|
||||||
import cgi
|
import cgi
|
||||||
import subprocess
|
|
||||||
import os
|
import os
|
||||||
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
import zipfile
|
||||||
|
|
||||||
LOCAL_ADDRESS = '0.0.0.0'
|
LOCAL_ADDRESS = '0.0.0.0'
|
||||||
|
|
||||||
@@ -142,7 +142,10 @@ class RequestHandler(CORSSimpleHTTPHandler):
|
|||||||
file_length -= len(self.rfile.readline())
|
file_length -= len(self.rfile.readline())
|
||||||
file_length -= len(self.rfile.readline())
|
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)
|
target_lib.new_build(self.path[6:], file_name)
|
||||||
self._set_response(code=201)
|
self._set_response(code=201)
|
||||||
self.wfile.write(
|
self.wfile.write(
|
||||||
@@ -158,7 +161,6 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
|||||||
|
|
||||||
|
|
||||||
def run_server(SeverClass=ThreadedHTTPServer, HandlerClass=RequestHandler, port=8000):
|
def run_server(SeverClass=ThreadedHTTPServer, HandlerClass=RequestHandler, port=8000):
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
server_address = (LOCAL_ADDRESS, port)
|
server_address = (LOCAL_ADDRESS, port)
|
||||||
server_instance = SeverClass(server_address, HandlerClass)
|
server_instance = SeverClass(server_address, HandlerClass)
|
||||||
try:
|
try:
|
||||||
@@ -169,12 +171,27 @@ def run_server(SeverClass=ThreadedHTTPServer, HandlerClass=RequestHandler, port=
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
server_instance.server_close()
|
server_instance.server_close()
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
logging.info('Server has been turned off.')
|
logging.info('Server has been turned off.')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from sys import argv
|
from sys import argv
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
print(argv)
|
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'):
|
if not os.path.isdir('target'):
|
||||||
os.mkdir('target', 755)
|
os.mkdir('target', 755)
|
||||||
if not os.path.isdir('output'):
|
if not os.path.isdir('output'):
|
||||||
|
|||||||
Reference in New Issue
Block a user