instance.py 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. from flask import jsonify, request
  2. import json
  3. import requests
  4. import os
  5. import time
  6. from lxconsole import db
  7. from lxconsole.models import Server
  8. from datetime import datetime
  9. from flask_login import login_required
  10. from lxconsole.api.access_controls import privilege_check
  11. def get_client_crt():
  12. return 'certs/client.crt'
  13. def get_client_key():
  14. return 'certs/client.key'
  15. @login_required
  16. def api_instance_endpoint(endpoint):
  17. if not privilege_check(endpoint, request.args.get('id')):
  18. return jsonify({'data': [], 'metadata':[], 'error': 'not authorized', 'error_code': 403})
  19. if endpoint == 'add_instance_disk_device':
  20. id = request.args.get('id')
  21. project = request.args.get('project')
  22. instance = request.args.get('instance')
  23. server = Server.query.filter_by(id=id).first()
  24. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  25. client_cert = get_client_crt()
  26. client_key = get_client_key()
  27. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  28. instance = json.dumps(results.json())
  29. instance = json.loads(instance)
  30. # Before applying PATCH, check to make sure device does not already exists so that we do not overwrite an existing device
  31. if request.form.get('name') in instance['metadata']['devices'].keys():
  32. return jsonify({"type": "error","error": "Unable to add new device. Device name already exists","error_code": 409,"metadata": {"error": "Unable to add new device. Device name already exists"}})
  33. description = instance['metadata']['description']
  34. data = {}
  35. device = {}
  36. device.update({'type': 'disk'})
  37. device.update({'pool': request.form.get('pool')}) if request.form.get('pool') else False
  38. device.update({'source': request.form.get('source')}) if request.form.get('source') else False
  39. device.update({'path': request.form.get('path')}) if request.form.get('path') else False
  40. device.update({'limits_read': request.form.get('limits_read')}) if request.form.get('limits_read') else False
  41. device.update({'limits_write': request.form.get('limits_write')}) if request.form.get('limits_write') else False
  42. device.update({'limits_max': request.form.get('limits_max')}) if request.form.get('limits_max') else False
  43. device.update({'required': request.form.get('required')}) if request.form.get('required') else False
  44. device.update({'read_only': request.form.get('read_only')}) if request.form.get('read_only') else False
  45. device.update({'size': request.form.get('size')}) if request.form.get('size') else False
  46. device.update({'size_state': request.form.get('size_state')}) if request.form.get('size_state') else False
  47. device.update({'recursive': request.form.get('recursive')}) if request.form.get('recursive') else False
  48. device.update({'propagation': request.form.get('propagation')}) if request.form.get('propagation') else False
  49. device.update({'shift': request.form.get('shift')}) if request.form.get('shift') else False
  50. device.update({'raw_mount_options': request.form.get('raw_mount_options')}) if request.form.get('raw_mount_options') else False
  51. device.update({'ceph_user_name': request.form.get('ceph_user_name')}) if request.form.get('ceph_user_name') else False
  52. device.update({'ceph_cluster_name': request.form.get('ceph_cluster_name')}) if request.form.get('ceph_cluster_name') else False
  53. device.update({'boot_priority': request.form.get('boot_priority')}) if request.form.get('boot_priority') else False
  54. devices = {}
  55. devices.update({request.form.get('name'): device})
  56. data.update({'description': description})
  57. data.update({'devices': devices})
  58. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  59. return jsonify(results.json())
  60. if endpoint == 'add_instance_gpu_device':
  61. id = request.args.get('id')
  62. project = request.args.get('project')
  63. instance = request.args.get('instance')
  64. server = Server.query.filter_by(id=id).first()
  65. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  66. client_cert = get_client_crt()
  67. client_key = get_client_key()
  68. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  69. instance = json.dumps(results.json())
  70. instance = json.loads(instance)
  71. # Before applying PATCH, check to make sure device does not already exists so that we do not overwrite an existing device
  72. if request.form.get('name') in instance['metadata']['devices'].keys():
  73. return jsonify({"type": "error","error": "Unable to add new device. Device name already exists","error_code": 409,"metadata": {"error": "Unable to add new device. Device name already exists"}})
  74. description = instance['metadata']['description']
  75. data = {}
  76. device = {}
  77. device.update({'type': 'gpu'})
  78. device.update({'gputype': request.form.get('gputype')}) if request.form.get('gputype') else False
  79. device.update({'vendorid': request.form.get('vendorid')}) if request.form.get('vendorid') else False
  80. device.update({'productid': request.form.get('productid')}) if request.form.get('productid') else False
  81. device.update({'id': request.form.get('id')}) if request.form.get('id') else False
  82. device.update({'pci': request.form.get('pci')}) if request.form.get('pci') else False
  83. device.update({'uid': request.form.get('uid')}) if request.form.get('uid') else False
  84. device.update({'gid': request.form.get('gid')}) if request.form.get('gid') else False
  85. device.update({'mode': request.form.get('mode')}) if request.form.get('mode') else False
  86. device.update({'mig.ci': request.form.get('mig.ci')}) if request.form.get('mig.ci') else False
  87. device.update({'mig.gi': request.form.get('mig.gi')}) if request.form.get('mig.gi') else False
  88. devices = {}
  89. devices.update({request.form.get('name'): device})
  90. data.update({'description': description})
  91. data.update({'devices': devices})
  92. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  93. return jsonify(results.json())
  94. if endpoint == 'add_instance_network_device':
  95. id = request.args.get('id')
  96. project = request.args.get('project')
  97. instance = request.args.get('instance')
  98. server = Server.query.filter_by(id=id).first()
  99. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  100. client_cert = get_client_crt()
  101. client_key = get_client_key()
  102. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  103. instance = json.dumps(results.json())
  104. instance = json.loads(instance)
  105. # Before applying PATCH, check to make sure device does not already exists so that we do not overwrite an existing device
  106. if request.form.get('name') in instance['metadata']['devices'].keys():
  107. return jsonify({"type": "error","error": "Unable to add new device. Device name already exists","error_code": 409,"metadata": {"error": "Unable to add new device. Device name already exists"}})
  108. description = instance['metadata']['description']
  109. data = {}
  110. device = {}
  111. device.update({'type': 'nic'})
  112. device.update({'nictype': request.form.get('nictype')}) if request.form.get('nictype') else False
  113. device.update({'parent': request.form.get('parent')}) if request.form.get('parent') else False
  114. device.update({'network': request.form.get('network')}) if request.form.get('network') else False
  115. device.update({'interface_name': request.form.get('interface_name')}) if request.form.get('interface_name') else False
  116. device.update({'mtu': request.form.get('mtu')}) if request.form.get('mtu') else False
  117. device.update({'mode': request.form.get('mode')}) if request.form.get('mode') else False
  118. device.update({'hwaddr': request.form.get('hwaddr')}) if request.form.get('hwaddr') else False
  119. device.update({'host_name': request.form.get('host_name')}) if request.form.get('host_name') else False
  120. device.update({'limits_ingress': request.form.get('limits_ingress')}) if request.form.get('limits_ingress') else False
  121. device.update({'limits_egress': request.form.get('limits_egress')}) if request.form.get('limits_egress') else False
  122. device.update({'limits_max': request.form.get('limits_max')}) if request.form.get('limits_max') else False
  123. device.update({'ipv4_address': request.form.get('ipv4_address')}) if request.form.get('ipv4_address') else False
  124. device.update({'ipv4_gateway': request.form.get('ipv4_gateway')}) if request.form.get('ipv4_gateway') else False
  125. device.update({'ipv4_host_table': request.form.get('ipv4_host_table')}) if request.form.get('ipv4_host_table') else False
  126. device.update({'ipv4_host_address': request.form.get('ipv4_host_address')}) if request.form.get('ipv4_host_address') else False
  127. device.update({'ipv4_routes': request.form.get('ipv4_routes')}) if request.form.get('ipv4_routes') else False
  128. device.update({'ipv4_routes_external': request.form.get('ipv4_routes_external')}) if request.form.get('ipv4_routes_external') else False
  129. device.update({'ipv6_address': request.form.get('ipv6_address')}) if request.form.get('ipv6_address') else False
  130. device.update({'ipv6_gateway': request.form.get('ipv6_gateway')}) if request.form.get('ipv6_gateway') else False
  131. device.update({'ipv6_host_table': request.form.get('ipv6_host_table')}) if request.form.get('ipv6_host_table') else False
  132. device.update({'ipv6_host_address': request.form.get('ipv6_host_address')}) if request.form.get('ipv6_host_address') else False
  133. device.update({'ipv6_routes': request.form.get('ipv6_routes')}) if request.form.get('ipv6_routes') else False
  134. device.update({'ipv6_routes_external': request.form.get('ipv6_routes_external')}) if request.form.get('ipv6_routes_external') else False
  135. device.update({'security_mac_filtering': request.form.get('security_mac_filtering')}) if request.form.get('security_mac_filtering') else False
  136. device.update({'security_ipv4_filtering': request.form.get('security_ipv4_filtering')}) if request.form.get('security_ipv4_filtering') else False
  137. device.update({'security_ipv6_filtering': request.form.get('security_ipv6_filtering')}) if request.form.get('security_ipv6_filtering') else False
  138. device.update({'maas_subnet_ipv4': request.form.get('maas_subnet_ipv4')}) if request.form.get('maas_subnet_ipv4') else False
  139. device.update({'maas_subnet_ipv6': request.form.get('maas_subnet_ipv6')}) if request.form.get('maas_subnet_ipv6') else False
  140. device.update({'boot_priority': request.form.get('boot_priority')}) if request.form.get('boot_priority') else False
  141. device.update({'vlan': request.form.get('vlan')}) if request.form.get('vlan') else False
  142. device.update({'vlan_tagged': request.form.get('vlan_tagged')}) if request.form.get('vlan_tagged') else False
  143. device.update({'security_port_isolation': request.form.get('security_port_isolation')}) if request.form.get('security_port_isolation') else False
  144. device.update({'gvrp': request.form.get('gvrp')}) if request.form.get('gvrp') else False
  145. device.update({'security_acls': request.form.get('security_acls')}) if request.form.get('security_acls') else False
  146. device.update({'security_acls_default_ingress_action': request.form.get('security_acls_default_ingress_action')}) if request.form.get('security_acls_default_ingress_action') else False
  147. device.update({'security_acls_default_egress_action': request.form.get('security_acls_default_egress_action')}) if request.form.get('security_acls_default_egress_action') else False
  148. device.update({'security_acls_default_ingress_logged': request.form.get('security_acls_default_ingress_logged')}) if request.form.get('security_acls_default_ingress_logged') else False
  149. device.update({'security_acls_default_egress_logged': request.form.get('security_acls_default_egress_logged')}) if request.form.get('security_acls_default_egress_logged') else False
  150. devices = {}
  151. devices.update({request.form.get('name'): device})
  152. data.update({'description': description})
  153. data.update({'devices': devices})
  154. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  155. return jsonify(results.json())
  156. if endpoint == 'add_instance_proxy_device':
  157. id = request.args.get('id')
  158. project = request.args.get('project')
  159. instance = request.args.get('instance')
  160. server = Server.query.filter_by(id=id).first()
  161. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  162. client_cert = get_client_crt()
  163. client_key = get_client_key()
  164. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  165. instance = json.dumps(results.json())
  166. instance = json.loads(instance)
  167. # Before applying PATCH, check to make sure device does not already exists so that we do not overwrite an existing device
  168. if request.form.get('name') in instance['metadata']['devices'].keys():
  169. return jsonify({"type": "error","error": "Unable to add new device. Device name already exists","error_code": 409,"metadata": {"error": "Unable to add new device. Device name already exists"}})
  170. description = instance['metadata']['description']
  171. data = {}
  172. device = {}
  173. device.update({'type': 'proxy'})
  174. device.update({'listen': request.form.get('listen')}) if request.form.get('listen') else False
  175. device.update({'connect': request.form.get('connect')}) if request.form.get('connect') else False
  176. device.update({'bind': request.form.get('bind')}) if request.form.get('bind') else False
  177. device.update({'uid': request.form.get('uid')}) if request.form.get('uid') else False
  178. device.update({'gid': request.form.get('gid')}) if request.form.get('gid') else False
  179. device.update({'mode': request.form.get('mode')}) if request.form.get('mode') else False
  180. device.update({'nat': request.form.get('nat')}) if request.form.get('nat') else False
  181. device.update({'proxy_protocol': request.form.get('proxy_protocol')}) if request.form.get('proxy_protocol') else False
  182. device.update({'security_uid': request.form.get('security_uid')}) if request.form.get('security_uid') else False
  183. device.update({'security_gid': request.form.get('security_gid')}) if request.form.get('security_gid') else False
  184. devices = {}
  185. devices.update({request.form.get('name'): device})
  186. data.update({'description': description})
  187. data.update({'devices': devices})
  188. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  189. return jsonify(results.json())
  190. if endpoint == 'add_instance_unix_device':
  191. id = request.args.get('id')
  192. project = request.args.get('project')
  193. instance = request.args.get('instance')
  194. server = Server.query.filter_by(id=id).first()
  195. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  196. client_cert = get_client_crt()
  197. client_key = get_client_key()
  198. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  199. instance = json.dumps(results.json())
  200. instance = json.loads(instance)
  201. # Before applying PATCH, check to make sure device does not already exists so that we do not overwrite an existing device
  202. if request.form.get('name') in instance['metadata']['devices'].keys():
  203. return jsonify({"type": "error","error": "Unable to add new device. Device name already exists","error_code": 409,"metadata": {"error": "Unable to add new device. Device name already exists"}})
  204. description = instance['metadata']['description']
  205. data = {}
  206. device = {}
  207. device.update({'type': request.form.get('type')}) if request.form.get('type') else False
  208. device.update({'source': request.form.get('source')}) if request.form.get('source') else False
  209. device.update({'path': request.form.get('path')}) if request.form.get('path') else False
  210. device.update({'major': request.form.get('major')}) if request.form.get('major') else False
  211. device.update({'minor': request.form.get('minor')}) if request.form.get('minor') else False
  212. device.update({'uid': request.form.get('uid')}) if request.form.get('uid') else False
  213. device.update({'gid': request.form.get('gid')}) if request.form.get('gid') else False
  214. device.update({'mode': request.form.get('mode')}) if request.form.get('mode') else False
  215. device.update({'required': request.form.get('required')}) if request.form.get('required') else False
  216. devices = {}
  217. devices.update({request.form.get('name'): device})
  218. data.update({'description': description})
  219. data.update({'devices': devices})
  220. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  221. return jsonify(results.json())
  222. if endpoint == 'add_instance_usb_device':
  223. id = request.args.get('id')
  224. project = request.args.get('project')
  225. instance = request.args.get('instance')
  226. server = Server.query.filter_by(id=id).first()
  227. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  228. client_cert = get_client_crt()
  229. client_key = get_client_key()
  230. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  231. instance = json.dumps(results.json())
  232. instance = json.loads(instance)
  233. # Before applying PATCH, check to make sure device does not already exists so that we do not overwrite an existing device
  234. if request.form.get('name') in instance['metadata']['devices'].keys():
  235. return jsonify({"type": "error","error": "Unable to add new device. Device name already exists","error_code": 409,"metadata": {"error": "Unable to add new device. Device name already exists"}})
  236. description = instance['metadata']['description']
  237. data = {}
  238. device = {}
  239. device.update({'type': 'usb'})
  240. device.update({'vendorid': request.form.get('vendorid')}) if request.form.get('vendorid') else False
  241. device.update({'productid': request.form.get('productid')}) if request.form.get('productid') else False
  242. device.update({'uid': request.form.get('uid')}) if request.form.get('uid') else False
  243. device.update({'gid': request.form.get('gid')}) if request.form.get('gid') else False
  244. device.update({'mode': request.form.get('mode')}) if request.form.get('mode') else False
  245. devices = {}
  246. devices.update({request.form.get('name'): device})
  247. data.update({'description': description})
  248. data.update({'devices': devices})
  249. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  250. return jsonify(results.json())
  251. if endpoint == 'attach_instance_profile':
  252. id = request.args.get('id')
  253. project = request.args.get('project')
  254. instance = request.args.get('instance')
  255. server = Server.query.filter_by(id=id).first()
  256. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  257. client_cert = get_client_crt()
  258. client_key = get_client_key()
  259. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  260. instance = json.dumps(results.json())
  261. instance = json.loads(instance)
  262. description = instance['metadata']['description']
  263. data = {}
  264. profiles = instance['metadata']['profiles']
  265. if request.form.get('name') not in profiles:
  266. profiles.append(request.form.get('name'))
  267. data.update({'description': description})
  268. data.update({'profiles': profiles})
  269. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  270. return jsonify(results.json())
  271. if endpoint == 'change_instance_state':
  272. id = request.args.get('id')
  273. project = request.args.get('project')
  274. instance = request.form.get('instance')
  275. action = request.form.get('action')
  276. force = request.form.get('force')
  277. server = Server.query.filter_by(id=id).first()
  278. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/state?project=' + project
  279. client_cert = get_client_crt()
  280. client_key = get_client_key()
  281. if force == 'true':
  282. data = { 'action': action, 'force': True }
  283. else:
  284. data = { 'action': action, 'force': False }
  285. results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  286. return jsonify(results.json())
  287. if endpoint == 'copy_instance':
  288. id = request.args.get('id')
  289. project = request.args.get('project')
  290. instance = request.args.get('instance')
  291. server = Server.query.filter_by(id=id).first()
  292. location = request.args.get('location')
  293. #Target location is needed for clustered servers and not allowed on non-clustered servers
  294. if location == 'none':
  295. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances?project=' + project
  296. else:
  297. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances?target='+location+'&project=' + project
  298. client_cert = get_client_crt()
  299. client_key = get_client_key()
  300. data = {}
  301. data.update({'name': request.form.get('name')})
  302. source = {}
  303. source.update({'type': 'copy'})
  304. source.update({'source': instance })
  305. source.update({'project': project})
  306. data.update({'source': source})
  307. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  308. return jsonify(results.json())
  309. if endpoint == 'create_instance_backup':
  310. id = request.args.get('id')
  311. project = request.args.get('project')
  312. instance = request.args.get('instance')
  313. server = Server.query.filter_by(id=id).first()
  314. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/backups?project=' + project
  315. client_cert = get_client_crt()
  316. client_key = get_client_key()
  317. # Determine file name
  318. name = request.form.get('name')
  319. if not name:
  320. now = datetime.now()
  321. dt_string = now.strftime("%Y%m%d%H%M%S")
  322. name = instance + '-' + dt_string
  323. # Determine file extenstion
  324. compression_algorithm = request.form.get('compression_algorithm')
  325. if compression_algorithm == 'bzip2':
  326. extenstion = '.tar.bz2'
  327. elif compression_algorithm == 'gzip':
  328. extenstion = '.tar.gz'
  329. elif compression_algorithm == 'lzma':
  330. extenstion = '.tar.lzma'
  331. elif compression_algorithm == 'xz':
  332. extenstion = '.tar.xz'
  333. elif compression_algorithm == 'zstd':
  334. extenstion = '.tar.zst'
  335. else:
  336. extenstion = '.tar'
  337. # Append file extension to name
  338. name = name + extenstion
  339. data = {}
  340. data.update({'name': name})
  341. data.update({'instance_only': True }) if request.form.get('instance_only') == 'true' else data.update({'instance_only': False })
  342. data.update({'optimized_storage': True }) if request.form.get('optimized_storage') == 'true' else data.update({'optimized_storage': False })
  343. data.update({'compression_algorithm': request.form.get('compression_algorithm')}) if request.form.get('compression_algorithm') else False
  344. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  345. return jsonify(results.json())
  346. if endpoint == 'create_instance_snapshot':
  347. id = request.args.get('id')
  348. project = request.args.get('project')
  349. instance = request.args.get('instance')
  350. server = Server.query.filter_by(id=id).first()
  351. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/snapshots?project=' + project
  352. client_cert = get_client_crt()
  353. client_key = get_client_key()
  354. data = {}
  355. data.update({'name': request.form.get('name')})
  356. if request.form.get('stateful') == 'true':
  357. data.update({'stateful': True})
  358. else:
  359. data.update({'stateful': False})
  360. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  361. return jsonify(results.json())
  362. if endpoint == 'create_instance_snapshot_instance':
  363. id = request.args.get('id')
  364. project = request.args.get('project')
  365. instance = request.args.get('instance')
  366. server = Server.query.filter_by(id=id).first()
  367. location = request.args.get('location')
  368. #Target location is needed for clustered servers and not allowed on non-clustered servers
  369. if location == 'none':
  370. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances?project=' + project
  371. else:
  372. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances?target='+location+'&project=' + project
  373. client_cert = get_client_crt()
  374. client_key = get_client_key()
  375. data = {}
  376. data.update({'name': request.form.get('name')})
  377. source = {}
  378. source.update({'type': 'copy'})
  379. source.update({'instance_only': True})
  380. source.update({'source': instance + '/' + request.form.get('snapshot')})
  381. source.update({'project': project})
  382. data.update({'source': source})
  383. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  384. return jsonify(results.json())
  385. if endpoint == 'delete_instance_backup':
  386. id = request.args.get('id')
  387. project = request.args.get('project')
  388. instance = request.args.get('instance')
  389. backup = request.args.get('backup')
  390. server = Server.query.filter_by(id=id).first()
  391. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/backups/' + backup + '?project=' + project
  392. client_cert = get_client_crt()
  393. client_key = get_client_key()
  394. if os.path.isfile('backups/' + str(server.id) + '/' + project + '/' + instance + '/' + backup):
  395. os.unlink('backups/' + str(server.id) + '/' + project + '/' + instance + '/' + backup)
  396. results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  397. return jsonify(results.json())
  398. if endpoint == 'delete_instance_device':
  399. id = request.args.get('id')
  400. project = request.args.get('project')
  401. instance = request.args.get('instance')
  402. device = request.args.get('device')
  403. server = Server.query.filter_by(id=id).first()
  404. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  405. client_cert = get_client_crt()
  406. client_key = get_client_key()
  407. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  408. instance = json.dumps(results.json())
  409. instance = json.loads(instance)
  410. data = instance['metadata']
  411. data['devices'].pop(device)
  412. results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  413. return jsonify(results.json())
  414. if endpoint == 'delete_instance':
  415. id = request.args.get('id')
  416. project = request.args.get('project')
  417. instance = request.form.get('instance')
  418. server = Server.query.filter_by(id=id).first()
  419. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  420. client_cert = get_client_crt()
  421. client_key = get_client_key()
  422. results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  423. return jsonify(results.json())
  424. if endpoint == 'delete_instance_log':
  425. id = request.args.get('id')
  426. project = request.args.get('project')
  427. log = request.args.get('log')
  428. server = Server.query.filter_by(id=id).first()
  429. url = 'https://' + server.addr + ':' + str(server.port) + log + '?project=' + project
  430. client_cert = get_client_crt()
  431. client_key = get_client_key()
  432. results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  433. return jsonify(results.json())
  434. if endpoint == 'delete_instance_snapshot':
  435. id = request.args.get('id')
  436. project = request.args.get('project')
  437. instance = request.args.get('instance')
  438. snapshot = request.args.get('snapshot')
  439. server = Server.query.filter_by(id=id).first()
  440. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/snapshots/' + snapshot + '?project=' + project
  441. client_cert = get_client_crt()
  442. client_key = get_client_key()
  443. results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  444. return jsonify(results.json())
  445. if endpoint == 'detach_instance_profile':
  446. id = request.args.get('id')
  447. project = request.args.get('project')
  448. instance = request.args.get('instance')
  449. profile = request.args.get('profile')
  450. server = Server.query.filter_by(id=id).first()
  451. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  452. client_cert = get_client_crt()
  453. client_key = get_client_key()
  454. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  455. instance = json.dumps(results.json())
  456. instance = json.loads(instance)
  457. instance = instance['metadata']
  458. description = instance['description']
  459. instance_profiles = instance['profiles']
  460. instance_profiles.remove(profile)
  461. data = {}
  462. data.update({ 'description': description })
  463. data.update({ 'profiles': instance_profiles})
  464. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  465. return jsonify(results.json())
  466. if endpoint == 'display_instance_log':
  467. id = request.args.get('id')
  468. project = request.args.get('project')
  469. server = Server.query.filter_by(id=id).first()
  470. log = request.args.get('log')
  471. url = 'https://' + server.addr + ':' + str(server.port) + log + '?project=' + project
  472. client_cert = get_client_crt()
  473. client_key = get_client_key()
  474. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  475. return results.text
  476. if endpoint == 'establish_instance_console_websocket':
  477. id = request.args.get('id')
  478. project = request.args.get('project')
  479. instance = request.args.get('instance')
  480. server = Server.query.filter_by(id=id).first()
  481. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/console?project=' + project
  482. client_cert = get_client_crt()
  483. client_key = get_client_key()
  484. data = {}
  485. data.update({'type': 'console'})
  486. data.update({'width': int(request.form.get('width'))})
  487. data.update({'height': int(request.form.get('height'))})
  488. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  489. results = json.dumps(results.json())
  490. results = json.loads(results)
  491. operation = results['operation'] if results['operation'] else ''
  492. secret = str(results['metadata']['metadata']['fds']['0']) if str(results['metadata']['metadata']['fds']['0']) else ''
  493. control = str(results['metadata']['metadata']['fds']['control']) if str(results['metadata']['metadata']['fds']['control']) else ''
  494. return jsonify({'operation': operation, 'secret': secret, 'control': control})
  495. if endpoint == 'establish_instance_exec_websocket':
  496. id = request.args.get('id')
  497. project = request.args.get('project')
  498. instance = request.args.get('instance')
  499. server = Server.query.filter_by(id=id).first()
  500. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/exec?project=' + project
  501. client_cert = get_client_crt()
  502. client_key = get_client_key()
  503. data = {}
  504. if request.form.get('shell') == "sh":
  505. data.update({'command': ["/bin/sh"]})
  506. else:
  507. data.update({'command': ["/bin/bash"]})
  508. data.update({'wait-for-websocket':True})
  509. data.update({'interactive': True})
  510. data.update({'width': int(request.form.get('width'))})
  511. data.update({'height': int(request.form.get('height'))})
  512. environment = {}
  513. environment.update({'HOME': '/root'})
  514. environment.update({'TERM': 'xterm'})
  515. environment.update({'USER': 'root'})
  516. data.update({'environment': environment})
  517. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  518. results = json.dumps(results.json())
  519. results = json.loads(results)
  520. operation = results['operation'] if results['operation'] else ''
  521. secret = str(results['metadata']['metadata']['fds']['0']) if str(results['metadata']['metadata']['fds']['0']) else ''
  522. control = str(results['metadata']['metadata']['fds']['control']) if str(results['metadata']['metadata']['fds']['control']) else ''
  523. return jsonify({'operation': operation, 'secret': secret, 'control': control})
  524. if endpoint == 'export_instance_backup':
  525. id = request.args.get('id')
  526. project = request.args.get('project')
  527. server = Server.query.filter_by(id=id).first()
  528. instance = request.args.get('instance')
  529. backup = request.args.get('backup')
  530. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '/backups/' + backup + '/export?project=' + project
  531. client_cert = get_client_crt()
  532. client_key = get_client_key()
  533. os.system('mkdir -p backups/' + str(server.id) + '/' + project + '/' + instance)
  534. filename = 'backups/' + str(server.id) + '/' + project + '/' + instance + '/' + backup
  535. with requests.get(url, stream=True, verify=server.ssl_verify, cert=(client_cert, client_key)) as r:
  536. r.raise_for_status()
  537. with open(filename, 'wb') as f:
  538. for chunk in r.iter_content(chunk_size=8192):
  539. f.write(chunk)
  540. return jsonify({"status": "Ok", "status_code": 200, "metadata": "{}"})
  541. if endpoint == 'get_instance':
  542. id = request.args.get('id')
  543. project = request.args.get('project')
  544. server = Server.query.filter_by(id=id).first()
  545. name = request.args.get('name')
  546. recursion = request.args.get('recursion')
  547. if recursion == '1':
  548. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  549. else:
  550. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  551. client_cert = get_client_crt()
  552. client_key = get_client_key()
  553. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  554. return jsonify(results.json())
  555. # Virtual Machine only
  556. if endpoint == 'copy_instance_proc_stat':
  557. id = request.args.get('id')
  558. project = request.args.get('project')
  559. server = Server.query.filter_by(id=id).first()
  560. name = request.args.get('name')
  561. client_cert = get_client_crt()
  562. client_key = get_client_key()
  563. # Unable to read /proc/stat directly on virtual machines use lxd files api...getting an EOF error
  564. # So we will copy /proc/stat to /tmp/stat and then read that file as a work around
  565. data = {}
  566. data.update({'command': ['/bin/sh', '-c', 'cat /proc/stat \u003e /tmp/stat' ]})
  567. #data.update({'command': ['cat', '/proc/stat']})
  568. #data.update({'command': ['cp', '/proc/stat', '/tmp/stat']})
  569. data.update({'wait-for-websocket': False})
  570. data.update({'interactive': False})
  571. data.update({'width': 80 })
  572. data.update({'height': 24 })
  573. data.update({'user': 0 })
  574. data.update({'group': 0 })
  575. data.update({'cwd': "/" })
  576. data.update({'record-output': False })
  577. data.update({'environment': {} })
  578. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/exec?project=' + project
  579. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  580. #Using record-output no longer appears to work, but it looks like lxd has code to use a new method of recording logs with exec-output as an option in the near future
  581. #Set record-output: true in command
  582. #exec_rtn = json.dumps(results.json())
  583. #exec_rtn = json.loads(exec_rtn)
  584. #Use operation to check for return value and get log output information
  585. #operation = exec_rtn['operation']
  586. #Check the logs/exec-ouput with get request to see if log exists /1.0/instances/{name}/logs/exec-output
  587. #url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/logs/exec-output?project=' + project
  588. #results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  589. #results return a list of urls of exec-output files. Should be able to match operation to a file in the list
  590. #example url: url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/test/logs/exec-output/exec_fea46679-fdaa-48f4-9079-502a090c4fb5.stdout'
  591. #results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  592. #The returned value should be text: return results.text
  593. #Check stdout log with get request "/1.0/instances/foo/logs/exec-output/exec_d0a89537-0617-4ed6-a79b-c2e88a970965.stdout",
  594. #return results.text
  595. #Check stderr log with get request "/1.0/instances/foo/logs/exec-output/exec_d0a89537-0617-4ed6-a79b-c2e88a970965.stderr",
  596. #Else delete to delete log at /1.0/instances/{name}/logs/exec-output/{filename}
  597. return jsonify(results.json())
  598. # Virtual Machine only
  599. if endpoint == 'get_instance_proc_stat':
  600. id = request.args.get('id')
  601. project = request.args.get('project')
  602. server = Server.query.filter_by(id=id).first()
  603. name = request.args.get('name')
  604. client_cert = get_client_crt()
  605. client_key = get_client_key()
  606. #Get /proc/stat information but from /tmp/stat
  607. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/files?project=' + project + '&path=/tmp/stat'
  608. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  609. if 'cpu' in results.text:
  610. results = results.text.split('\n')
  611. for result in results:
  612. stats = result.split()
  613. if 'cpu' in stats:
  614. user_time = int(stats[1])
  615. system_time= int(stats[3])
  616. idle_time = int(stats[4])
  617. return jsonify({'user_time':user_time, 'system_time':system_time, 'idle_time':idle_time})
  618. return jsonify({'user_time':0, 'system_time':0, 'idle_time':0})
  619. if endpoint == 'get_instance_cpu_usage':
  620. id = request.args.get('id')
  621. project = request.args.get('project')
  622. server = Server.query.filter_by(id=id).first()
  623. name = request.args.get('name')
  624. client_cert = get_client_crt()
  625. client_key = get_client_key()
  626. #Get instance state to retrieve instance cpu usage
  627. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/state?project=' + project
  628. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  629. results = json.dumps(results.json())
  630. results = json.loads(results)
  631. #Get cpu usage
  632. if 'cpu' in results['metadata']:
  633. if 'usage' in results['metadata']['cpu']:
  634. #Usage is reported in nanoseconds
  635. instance_cpu_time = int(results['metadata']['cpu']['usage'])
  636. else:
  637. instance_cpu_time = 0
  638. else:
  639. instance_cpu_time = 0
  640. #Get /proc/stat information
  641. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/files?project=' + project + '&path=/proc/stat'
  642. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  643. if 'cpu' in results.text:
  644. results = results.text.split('\n')
  645. for result in results:
  646. stats = result.split()
  647. if stats[0] == 'cpu':
  648. #0 = 'cpu'
  649. #1 = <user time>
  650. #2 = <nice time>
  651. #3 = <system time>
  652. #4 = <idle time>
  653. user_time = int(stats[1])
  654. system_time= int(stats[3])
  655. idle_time = int(stats[4])
  656. host_cpu_time = user_time + system_time + idle_time
  657. return jsonify({'instance_cpu_time':instance_cpu_time,'host_cpu_time': host_cpu_time})
  658. return jsonify({'instance_cpu_time':0,'host_cpu_time': 0})
  659. if endpoint == 'get_instance_disk_devices':
  660. id = request.args.get('id')
  661. project = request.args.get('project')
  662. server = Server.query.filter_by(id=id).first()
  663. name = request.args.get('name')
  664. recursion = request.args.get('recursion')
  665. if recursion == '1':
  666. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  667. else:
  668. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  669. client_cert = get_client_crt()
  670. client_key = get_client_key()
  671. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  672. instance = json.dumps(results.json())
  673. instance = json.loads(instance)
  674. expanded_devices = instance['metadata']['expanded_devices']
  675. devices = []
  676. instance_state_url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/state?project=' + project
  677. instance_state = requests.get(instance_state_url, verify=server.ssl_verify, cert=(client_cert, client_key))
  678. instance_state = json.dumps(instance_state.json())
  679. instance_state = json.loads(instance_state)
  680. if expanded_devices:
  681. for expanded_device in expanded_devices:
  682. if expanded_devices[expanded_device]['type'] == 'disk':
  683. device = {}
  684. device.update({ 'device': expanded_device })
  685. device.update({ 'type': expanded_devices[expanded_device]['type'] })
  686. if 'path' in expanded_devices[expanded_device]:
  687. device.update({ 'path': expanded_devices[expanded_device]['path'] })
  688. if 'pool' in expanded_devices[expanded_device]:
  689. device.update({ 'pool': expanded_devices[expanded_device]['pool'] })
  690. if expanded_device in instance_state['metadata']['disk']:
  691. if 'usage' in instance_state['metadata']['disk'][expanded_device]:
  692. device.update({ 'usage': instance_state['metadata']['disk'][expanded_device]['usage'] })
  693. devices.append(device)
  694. return jsonify({ 'data': devices })
  695. if endpoint == 'get_instance_gpu_devices':
  696. id = request.args.get('id')
  697. project = request.args.get('project')
  698. server = Server.query.filter_by(id=id).first()
  699. name = request.args.get('name')
  700. recursion = request.args.get('recursion')
  701. if recursion == '1':
  702. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  703. else:
  704. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  705. client_cert = get_client_crt()
  706. client_key = get_client_key()
  707. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  708. instance = json.dumps(results.json())
  709. instance = json.loads(instance)
  710. expanded_devices = instance['metadata']['expanded_devices']
  711. devices = []
  712. if expanded_devices:
  713. for expanded_device in expanded_devices:
  714. if expanded_devices[expanded_device]['type'] == 'gpu':
  715. device = {}
  716. device.update({ 'device': expanded_device })
  717. device.update({ 'type': expanded_devices[expanded_device]['type'] })
  718. if 'gputype' in expanded_devices[expanded_device]:
  719. device.update({ 'gputype': expanded_devices[expanded_device]['gputype'] })
  720. if 'vendorid' in expanded_devices[expanded_device]:
  721. device.update({ 'vendorid': expanded_devices[expanded_device]['vendorid'] })
  722. if 'productid' in expanded_devices[expanded_device]:
  723. device.update({ 'productid': expanded_devices[expanded_device]['productid'] })
  724. if 'id' in expanded_devices[expanded_device]:
  725. device.update({ 'id': expanded_devices[expanded_device]['id'] })
  726. if 'pci' in expanded_devices[expanded_device]:
  727. device.update({ 'pci': expanded_devices[expanded_device]['pci'] })
  728. if 'uid' in expanded_devices[expanded_device]:
  729. device.update({ 'uid': expanded_devices[expanded_device]['uid'] })
  730. if 'gid' in expanded_devices[expanded_device]:
  731. device.update({ 'gid': expanded_devices[expanded_device]['gid'] })
  732. if 'mode' in expanded_devices[expanded_device]:
  733. device.update({ 'mode': expanded_devices[expanded_device]['mode'] })
  734. if 'mig.ci' in expanded_devices[expanded_device]:
  735. device.update({ 'mig.ci': expanded_devices[expanded_device]['mig.ci'] })
  736. if 'mig.gi' in expanded_devices[expanded_device]:
  737. device.update({ 'mig.gi': expanded_devices[expanded_device]['mig.gi'] })
  738. devices.append(device)
  739. return jsonify({ 'data': devices })
  740. if endpoint == 'get_instance_interfaces':
  741. id = request.args.get('id')
  742. project = request.args.get('project')
  743. server = Server.query.filter_by(id=id).first()
  744. name = request.args.get('name')
  745. recursion = request.args.get('recursion')
  746. if recursion == '1':
  747. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/state?recursion=1&project=' + project
  748. else:
  749. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/state?project=' + project
  750. client_cert = get_client_crt()
  751. client_key = get_client_key()
  752. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  753. instance = json.dumps(results.json())
  754. instance = json.loads(instance)
  755. networks = instance['metadata']['network']
  756. interfaces = []
  757. if networks:
  758. for network in networks:
  759. if network:
  760. interface = {}
  761. interface.update({ 'name': network })
  762. interface.update({ 'hwaddr': networks[network]['hwaddr'] })
  763. interface.update({ 'state': networks[network]['state'] })
  764. addresses = networks[network]['addresses']
  765. interface.update({ 'ipv4_addresses': [] })
  766. interface.update({ 'ipv6_addresses': [] })
  767. for address in addresses:
  768. #if address['family'] == 'inet' and address['scope'] == 'global':
  769. if address['family'] == 'inet':
  770. interface['ipv4_addresses'] += [ address['address'] ]
  771. if address['family'] == 'inet6':
  772. interface['ipv6_addresses'] += [ address['address'] ]
  773. interfaces.append(interface)
  774. return jsonify({ 'data': interfaces })
  775. if endpoint == 'get_instance_network_devices':
  776. id = request.args.get('id')
  777. project = request.args.get('project')
  778. server = Server.query.filter_by(id=id).first()
  779. name = request.args.get('name')
  780. recursion = request.args.get('recursion')
  781. if recursion == '1':
  782. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  783. else:
  784. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  785. client_cert = get_client_crt()
  786. client_key = get_client_key()
  787. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  788. instance = json.dumps(results.json())
  789. instance = json.loads(instance)
  790. expanded_devices = instance['metadata']['expanded_devices']
  791. devices = []
  792. if expanded_devices:
  793. for expanded_device in expanded_devices:
  794. if expanded_devices[expanded_device]['type'] == 'nic':
  795. device = {}
  796. device.update({ 'device': expanded_device })
  797. device.update({ 'type': expanded_devices[expanded_device]['type'] })
  798. if 'name' in expanded_devices[expanded_device]:
  799. device.update({ 'name': expanded_devices[expanded_device]['name'] })
  800. if 'network' in expanded_devices[expanded_device]:
  801. device.update({ 'network': expanded_devices[expanded_device]['network'] })
  802. if 'nictype' in expanded_devices[expanded_device]:
  803. device.update({ 'nictype': expanded_devices[expanded_device]['nictype'] })
  804. if 'parent' in expanded_devices[expanded_device]:
  805. device.update({ 'parent': expanded_devices[expanded_device]['parent'] })
  806. devices.append(device)
  807. return jsonify({ 'data': devices })
  808. if endpoint == 'get_instance_proxy_devices':
  809. id = request.args.get('id')
  810. project = request.args.get('project')
  811. server = Server.query.filter_by(id=id).first()
  812. name = request.args.get('name')
  813. recursion = request.args.get('recursion')
  814. if recursion == '1':
  815. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  816. else:
  817. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  818. client_cert = get_client_crt()
  819. client_key = get_client_key()
  820. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  821. instance = json.dumps(results.json())
  822. instance = json.loads(instance)
  823. expanded_devices = instance['metadata']['expanded_devices']
  824. devices = []
  825. if expanded_devices:
  826. for expanded_device in expanded_devices:
  827. if expanded_devices[expanded_device]['type'] == 'proxy':
  828. device = {}
  829. device.update({ 'device': expanded_device })
  830. device.update({ 'type': expanded_devices[expanded_device]['type'] })
  831. if 'connect' in expanded_devices[expanded_device]:
  832. device.update({ 'connect': expanded_devices[expanded_device]['connect'] })
  833. if 'listen' in expanded_devices[expanded_device]:
  834. device.update({ 'listen': expanded_devices[expanded_device]['listen'] })
  835. devices.append(device)
  836. return jsonify({ 'data': devices })
  837. if endpoint == 'get_instance_state':
  838. id = request.args.get('id')
  839. project = request.args.get('project')
  840. server = Server.query.filter_by(id=id).first()
  841. name = request.args.get('name')
  842. recursion = request.args.get('recursion')
  843. if recursion == '1':
  844. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/state?recursion=1&project=' + project
  845. else:
  846. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/state?project=' + project
  847. client_cert = get_client_crt()
  848. client_key = get_client_key()
  849. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  850. return jsonify(results.json())
  851. # Container only
  852. if endpoint == 'get_instance_unix_devices':
  853. id = request.args.get('id')
  854. project = request.args.get('project')
  855. server = Server.query.filter_by(id=id).first()
  856. name = request.args.get('name')
  857. recursion = request.args.get('recursion')
  858. if recursion == '1':
  859. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  860. else:
  861. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  862. client_cert = get_client_crt()
  863. client_key = get_client_key()
  864. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  865. instance = json.dumps(results.json())
  866. instance = json.loads(instance)
  867. expanded_devices = instance['metadata']['expanded_devices']
  868. devices = []
  869. if expanded_devices:
  870. for expanded_device in expanded_devices:
  871. if expanded_devices[expanded_device]['type'] == 'unix-block' or expanded_devices[expanded_device]['type'] == 'unix-char':
  872. device = {}
  873. device.update({ 'device': expanded_device })
  874. device.update({ 'type': expanded_devices[expanded_device]['type'] })
  875. if 'source' in expanded_devices[expanded_device]:
  876. device.update({ 'source': expanded_devices[expanded_device]['source'] })
  877. if 'path' in expanded_devices[expanded_device]:
  878. device.update({ 'path': expanded_devices[expanded_device]['path'] })
  879. if 'major' in expanded_devices[expanded_device]:
  880. device.update({ 'major': expanded_devices[expanded_device]['major'] })
  881. if 'minor' in expanded_devices[expanded_device]:
  882. device.update({ 'minor': expanded_devices[expanded_device]['minor'] })
  883. if 'uid' in expanded_devices[expanded_device]:
  884. device.update({ 'uid': expanded_devices[expanded_device]['uid'] })
  885. if 'gid' in expanded_devices[expanded_device]:
  886. device.update({ 'gid': expanded_devices[expanded_device]['gid'] })
  887. if 'mode' in expanded_devices[expanded_device]:
  888. device.update({ 'mode': expanded_devices[expanded_device]['mode'] })
  889. if 'required' in expanded_devices[expanded_device]:
  890. device.update({ 'required': expanded_devices[expanded_device]['required'] })
  891. devices.append(device)
  892. return jsonify({ 'data': devices })
  893. if endpoint == 'get_instance_usb_devices':
  894. id = request.args.get('id')
  895. project = request.args.get('project')
  896. server = Server.query.filter_by(id=id).first()
  897. name = request.args.get('name')
  898. recursion = request.args.get('recursion')
  899. if recursion == '1':
  900. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?recursion=1&project=' + project
  901. else:
  902. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '?project=' + project
  903. client_cert = get_client_crt()
  904. client_key = get_client_key()
  905. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  906. instance = json.dumps(results.json())
  907. instance = json.loads(instance)
  908. expanded_devices = instance['metadata']['expanded_devices']
  909. devices = []
  910. if expanded_devices:
  911. for expanded_device in expanded_devices:
  912. if expanded_devices[expanded_device]['type'] == 'usb':
  913. device = {}
  914. device.update({ 'device': expanded_device })
  915. device.update({ 'type': expanded_devices[expanded_device]['type'] })
  916. if 'vendorid' in expanded_devices[expanded_device]:
  917. device.update({ 'vendorid': expanded_devices[expanded_device]['vendorid'] })
  918. if 'productid' in expanded_devices[expanded_device]:
  919. device.update({ 'productid': expanded_devices[expanded_device]['productid'] })
  920. if 'uid' in expanded_devices[expanded_device]:
  921. device.update({ 'uid': expanded_devices[expanded_device]['uid'] })
  922. if 'gid' in expanded_devices[expanded_device]:
  923. device.update({ 'gid': expanded_devices[expanded_device]['gid'] })
  924. if 'mode' in expanded_devices[expanded_device]:
  925. device.update({ 'mode': expanded_devices[expanded_device]['mode'] })
  926. if 'required' in expanded_devices[expanded_device]:
  927. device.update({ 'required': expanded_devices[expanded_device]['required'] })
  928. devices.append(device)
  929. return jsonify({ 'data': devices })
  930. if endpoint == 'get_instance_websocket_host':
  931. id = request.args.get('id')
  932. server = Server.query.filter_by(id=id).first()
  933. return jsonify({ 'addr': server.addr, 'port': server.port, 'proxy': server.proxy })
  934. if endpoint == 'list_instance_backups':
  935. id = request.args.get('id')
  936. project = request.args.get('project')
  937. server = Server.query.filter_by(id=id).first()
  938. name = request.args.get('name')
  939. recursion = request.args.get('recursion')
  940. if recursion == '1':
  941. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/backups?recursion=1&project=' + project
  942. else:
  943. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/backups?project=' + project
  944. client_cert = get_client_crt()
  945. client_key = get_client_key()
  946. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  947. backups = json.dumps(results.json())
  948. backups = json.loads(backups)
  949. devices = []
  950. if backups:
  951. for backup in backups['metadata']:
  952. # Check if backup file exists
  953. if os.path.isfile('backups/' + str(server.id) + '/' + project + '/' + name + '/' + backup['name']):
  954. backup.update({'backup_file_exists': True})
  955. backup.update({'backup_file_size': os.path.getsize('backups/' + str(server.id) + '/' + project + '/' + name + '/' + backup['name'])})
  956. else:
  957. backup.update({'backup_file_exists': False})
  958. return jsonify(backups)
  959. if endpoint == 'list_instance_logs':
  960. id = request.args.get('id')
  961. project = request.args.get('project')
  962. server = Server.query.filter_by(id=id).first()
  963. name = request.args.get('name')
  964. recursion = request.args.get('recursion')
  965. if recursion == '1':
  966. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/logs?recursion=1&project=' + project
  967. else:
  968. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/logs?project=' + project
  969. client_cert = get_client_crt()
  970. client_key = get_client_key()
  971. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  972. # Newly created VMs will not have logs until it starts, causing a 404 error
  973. results = json.dumps(results.json())
  974. results = json.loads(results)
  975. if results['metadata'] is None:
  976. return jsonify({"metadata":[]})
  977. return jsonify(results)
  978. if endpoint == 'list_instance_snapshots':
  979. id = request.args.get('id')
  980. project = request.args.get('project')
  981. server = Server.query.filter_by(id=id).first()
  982. name = request.args.get('name')
  983. recursion = request.args.get('recursion')
  984. if recursion == '1':
  985. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/snapshots?recursion=1&project=' + project
  986. else:
  987. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + name + '/snapshots?project=' + project
  988. client_cert = get_client_crt()
  989. client_key = get_client_key()
  990. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  991. return jsonify(results.json())
  992. if endpoint == 'migrate_instance':
  993. id = request.args.get('id')
  994. project = request.args.get('project')
  995. instance = request.args.get('instance')
  996. server = Server.query.filter_by(id=id).first()
  997. location = request.args.get('location')
  998. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?target='+location+'&project=' + project
  999. client_cert = get_client_crt()
  1000. client_key = get_client_key()
  1001. data = {}
  1002. data.update({'name': instance })
  1003. data.update({'migration': True})
  1004. data.update({'live': False})
  1005. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  1006. return jsonify(results.json())
  1007. if endpoint == 'publish_instance':
  1008. id = request.args.get('id')
  1009. project = request.args.get('project')
  1010. instance = request.args.get('instance')
  1011. server = Server.query.filter_by(id=id).first()
  1012. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/images?project=' + project
  1013. client_cert = get_client_crt()
  1014. client_key = get_client_key()
  1015. data = {}
  1016. properties = {}
  1017. properties.update({ 'description':request.form.get('description') })
  1018. properties.update({ 'os': request.form.get('os') })
  1019. properties.update({ 'release': request.form.get('release') })
  1020. data.update({ 'properties': properties })
  1021. source = {}
  1022. source.update({ 'type': 'instance' })
  1023. source.update({ 'name': instance })
  1024. data.update({ 'source': source })
  1025. if request.form.get('public') == 'true':
  1026. data.update({'public': True})
  1027. else:
  1028. data.update({'public': False})
  1029. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  1030. return jsonify(results.json())
  1031. if endpoint == 'publish_instance_snapshot':
  1032. id = request.args.get('id')
  1033. project = request.args.get('project')
  1034. instance = request.args.get('instance')
  1035. snapshot = request.args.get('snapshot')
  1036. server = Server.query.filter_by(id=id).first()
  1037. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/images?project=' + project
  1038. client_cert = get_client_crt()
  1039. client_key = get_client_key()
  1040. data = {}
  1041. properties = {}
  1042. properties.update({ 'description':request.form.get('description') })
  1043. properties.update({ 'os': request.form.get('os') })
  1044. properties.update({ 'release': request.form.get('release') })
  1045. data.update({ 'properties': properties })
  1046. source = {}
  1047. source.update({ 'type': 'snapshot' })
  1048. source.update({ 'name': instance + '/' + snapshot })
  1049. data.update({ 'source': source })
  1050. if request.form.get('public') == 'true':
  1051. data.update({'public': True})
  1052. else:
  1053. data.update({'public': False})
  1054. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  1055. return jsonify(results.json())
  1056. if endpoint == 'rename_instance':
  1057. id = request.args.get('id')
  1058. project = request.args.get('project')
  1059. instance = request.args.get('instance')
  1060. server = Server.query.filter_by(id=id).first()
  1061. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  1062. client_cert = get_client_crt()
  1063. client_key = get_client_key()
  1064. data = {}
  1065. data.update({'name': request.form.get('name')})
  1066. results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  1067. return jsonify(results.json())
  1068. if endpoint == 'restore_instance_snapshot':
  1069. id = request.args.get('id')
  1070. project = request.args.get('project')
  1071. instance = request.args.get('instance')
  1072. server = Server.query.filter_by(id=id).first()
  1073. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  1074. client_cert = get_client_crt()
  1075. client_key = get_client_key()
  1076. data = {}
  1077. data.update({'restore': request.form.get('name')})
  1078. results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  1079. return jsonify(results.json())
  1080. if endpoint == 'update_instance':
  1081. id = request.args.get('id')
  1082. project = request.args.get('project')
  1083. instance = request.args.get('instance')
  1084. server = Server.query.filter_by(id=id).first()
  1085. url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/instances/' + instance + '?project=' + project
  1086. client_cert = get_client_crt()
  1087. client_key = get_client_key()
  1088. # If the update was from JSON tab, update it with a PUT request
  1089. if request.form.get('json'):
  1090. data = request.form.get('json')
  1091. results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
  1092. return jsonify(results.json())
  1093. # Get the current config
  1094. results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
  1095. instance = json.dumps(results.json())
  1096. instance = json.loads(instance)
  1097. existing_config = instance['metadata']['config']
  1098. # Create a new dict to hold the differences between existing config and form config
  1099. updated_config = {}
  1100. # Loop through and compare differences between existing config and form config
  1101. for key, val in request.form.items():
  1102. # If key is description, continue as it is not part of config
  1103. if key == 'description':
  1104. continue
  1105. # If the key does not exist in existing config, create and set it to empty string so we can compare it to form config
  1106. if not key in existing_config:
  1107. existing_config.update( { key: '' } )
  1108. # If the post key is different than existing key capture this difference in new dict
  1109. if request.form.get(key) != existing_config[key]:
  1110. updated_config.update({key: request.form.get(key)})
  1111. # Send a PATCH request to update only the differences in config
  1112. data = {}
  1113. data.update({'description': request.form.get('description')})
  1114. data.update({'config' : updated_config })
  1115. results = requests.patch(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
  1116. return jsonify(results.json())