app.py 5.9 KB

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