app.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import uuid
  2. import os
  3. import subprocess
  4. import zipfile
  5. import urllib.request
  6. import gzip
  7. from io import BytesIO
  8. import time
  9. import json
  10. from flask import Flask, render_template, request, flash
  11. from threading import Thread, Lock
  12. queue_lock = Lock()
  13. def run_build(taskfile):
  14. # run a build with parameters from task
  15. task = json.loads(open(taskfile).read())
  16. builddir = '/tmp/build'
  17. subprocess.run(['git', 'submodule',
  18. 'update', '--recursive',
  19. '--force', '--init'])
  20. subprocess.run(['./waf', 'configure',
  21. '--board', task['board'],
  22. '--out', builddir,
  23. '--extra-hwdef', task['extra_hwdef']],
  24. cwd = task['sourcedir'])
  25. subprocess.run(['./waf', 'clean'], cwd = task['sourcedir'])
  26. subprocess.run(['./waf', task['vehicle']], cwd = task['sourcedir'])
  27. # background thread to check for queued build requests
  28. def check_queue():
  29. while(1):
  30. queue_lock.acquire()
  31. listing = os.listdir(os.path.join(appdir, 'buildqueue'))
  32. queue_lock.release()
  33. if listing:
  34. for token in listing:
  35. builddir = os.path.join('/private/tmp/build', token)
  36. buildqueue_dir = os.path.join(appdir, 'buildqueue', token)
  37. # check if build exists
  38. if os.path.isdir(builddir):
  39. print("Build already exists")
  40. else:
  41. # run build and rename build directory
  42. run_build(os.path.join(buildqueue_dir, 'q.json'))
  43. f = open(os.path.join(buildqueue_dir, 'q.json'))
  44. task = json.load(f)
  45. os.rename(os.path.join('/private/tmp/build', task['board']), builddir)
  46. # remove working files
  47. os.remove(os.path.join(buildqueue_dir, 'extra_hwdef.dat'))
  48. os.remove(os.path.join(buildqueue_dir, 'q.json'))
  49. os.rmdir(os.path.join(buildqueue_dir))
  50. print("Build successful")
  51. # define source and app directories
  52. sourcedir = os.path.abspath('../ardupilot/')
  53. appdir = os.path.abspath(os.curdir)
  54. if not os.path.isdir('buildqueue'):
  55. os.mkdir('buildqueue')
  56. thread = Thread(target=check_queue, args=())
  57. thread.daemon = True
  58. thread.start()
  59. # Directory of this file
  60. this_path = os.path.dirname(os.path.realpath(__file__))
  61. # Where the user requested tile are stored
  62. output_path = os.path.join(this_path, '..', 'userRequestFirmware')
  63. # Where the data database is
  64. tile_path = os.path.join(this_path, '..', 'data', 'tiles')
  65. # The output folder for all gzipped build requests
  66. app = Flask(__name__, static_url_path='/builds', static_folder=output_path,)
  67. #def compressFiles(fileList, uuidkey):
  68. # create a zip file comprised of dat.gz tiles
  69. #zipthis = os.path.join(output_path, uuidkey + '.zip')
  70. # create output dirs if needed
  71. #try:
  72. # os.makedirs(output_path)
  73. #except OSError:
  74. # pass
  75. #try:
  76. # os.makedirs(tile_path)
  77. #except OSError:
  78. # pass
  79. #try:
  80. # with zipfile.ZipFile(zipthis, 'w') as terrain_zip:
  81. # for fn in fileList:
  82. # if not os.path.exists(fn):
  83. # #download if required
  84. # print("Downloading " + os.path.basename(fn))
  85. # g = urllib.request.urlopen('https://terrain.ardupilot.org/data/tiles/' +
  86. # os.path.basename(fn))
  87. # print("Downloaded " + os.path.basename(fn))
  88. # with open(fn, 'b+w') as f:
  89. # f.write(g.read())
  90. # need to decompress file and pass to zip
  91. # with gzip.open(fn, 'r') as f_in:
  92. # myio = BytesIO(f_in.read())
  93. # print("Decomp " + os.path.basename(fn))
  94. # and add file to zip
  95. # terrain_zip.writestr(os.path.basename(fn)[:-3], myio.read(),
  96. # compress_type=zipfile.ZIP_DEFLATED)
  97. #except Exception as ex:
  98. # print("Unexpected error: {0}".format(ex))
  99. # return False
  100. #return True
  101. @app.route('/')
  102. def index():
  103. return render_template('index.html')
  104. @app.route('/generate', methods=['GET', 'POST'])
  105. def generate():
  106. #if request.method == 'POST':
  107. features = []
  108. task = {}
  109. # fetch features from user input
  110. for i in range(1,8):
  111. value = request.form["option" + str(i)]
  112. features.append(value)
  113. undefine = "undef " + value.split()[1]
  114. features.insert(0,undefine)
  115. extra_hwdef = '\n'.join(features)
  116. #print("features: ", features)
  117. queue_lock.acquire()
  118. # create extra_hwdef.dat file and obtain md5sum
  119. file = open('buildqueue/extra_hwdef.dat',"w")
  120. file.write(extra_hwdef)
  121. file.close()
  122. md5sum = subprocess.check_output(['md5sum', 'buildqueue/extra_hwdef.dat'],
  123. encoding = 'utf-8')
  124. md5sum = md5sum[:len(md5sum)-29]
  125. os.remove('buildqueue/extra_hwdef.dat')
  126. # obtain git-hash of source
  127. git_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD'],
  128. cwd = sourcedir,
  129. encoding = 'utf-8')
  130. git_hash = git_hash[:len(git_hash)-1]
  131. # create directories using concatenated token of git-hash and md5sum of hwdef
  132. token = git_hash + "-" + md5sum
  133. buildqueue_dir = os.path.join(appdir, 'buildqueue', token)
  134. if not os.path.isdir(buildqueue_dir):
  135. os.mkdir(buildqueue_dir)
  136. file = open(os.path.join(buildqueue_dir, 'extra_hwdef.dat'),"w")
  137. file.write(extra_hwdef)
  138. file.close()
  139. # fill dictionary of variables and create json file
  140. task['hwdef_md5sum'] = md5sum
  141. task['git_hash'] = git_hash
  142. task['sourcedir'] = sourcedir
  143. task['extra_hwdef'] = os.path.join(buildqueue_dir, 'extra_hwdef.dat')
  144. task['board'] = request.form["board"]
  145. task['vehicle'] = request.form["vehicle"]
  146. jfile = open(os.path.join(buildqueue_dir, 'q.json'), "w")
  147. jfile.write(json.dumps(task))
  148. jfile.close()
  149. queue_lock.release()
  150. #print(task)
  151. return render_template('building.html')
  152. # remove duplicates
  153. #filelist = list(dict.fromkeys(filelist))
  154. #print(filelist)
  155. #compress
  156. #success = compressFiles(filelist, uuidkey)
  157. # as a cleanup, remove any generated terrain older than 24H
  158. #for f in os.listdir(output_path):
  159. # if os.stat(os.path.join(output_path, f)).st_mtime < time.time() - 24 * 60 * 60:
  160. # print("Removing old file: " + str(os.path.join(output_path, f)))
  161. # os.remove(os.path.join(output_path, f))
  162. #if success:
  163. # print("Generated " + "/terrain/" + uuidkey + ".zip")
  164. # return render_template('generate.html', urlkey="/terrain/" + uuidkey + ".zip",
  165. # uuidkey=uuidkey, outsideLat=outsideLat)
  166. #else:
  167. # print("Failed " + "/terrain/" + uuidkey + ".zip")
  168. # return render_template('generate.html', error="Cannot generate terrain",
  169. # uuidkey=uuidkey)
  170. #else:
  171. # print("Bad get")
  172. # return render_template('generate.html', error="Need to use POST, not GET")
  173. @app.route('/home', methods=['POST'])
  174. def home():
  175. return render_template('index.html')
  176. if __name__ == "__main__":
  177. app.run()