guest.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import json
  4. import random
  5. from flask import Blueprint, render_template, url_for, request
  6. import requests
  7. from math import ceil
  8. import re
  9. import socket
  10. import time
  11. from models import Database as db
  12. from models.initialize import config
  13. __author__ = 'James Iter'
  14. __date__ = '2017/5/30'
  15. __contact__ = 'james.iter.cn@gmail.com'
  16. __copyright__ = '(c) 2017 by James Iter.'
  17. blueprint = Blueprint(
  18. 'v_guest',
  19. __name__,
  20. url_prefix='/guest'
  21. )
  22. blueprints = Blueprint(
  23. 'v_guests',
  24. __name__,
  25. url_prefix='/guests'
  26. )
  27. def show():
  28. args = list()
  29. page = int(request.args.get('page', 1))
  30. page_size = int(request.args.get('page_size', 10))
  31. keyword = request.args.get('keyword', None)
  32. resource_path = request.path
  33. if page is not None:
  34. args.append('page=' + page.__str__())
  35. if page_size is not None:
  36. args.append('page_size=' + page_size.__str__())
  37. if keyword is not None:
  38. args.append('keyword=' + keyword.__str__())
  39. host_url = request.host_url.rstrip('/')
  40. hosts_url = host_url + url_for('api_hosts.r_get_by_filter')
  41. guests_url = host_url + url_for('api_guests.r_get_by_filter')
  42. if keyword is not None:
  43. guests_url = host_url + url_for('api_guests.r_content_search')
  44. os_templates_url = host_url + url_for('api_os_templates.r_get_by_filter')
  45. if args.__len__() > 0:
  46. guests_url = guests_url + '?' + '&'.join(args)
  47. hosts_ret = requests.get(url=hosts_url, cookies=request.cookies)
  48. hosts_ret = json.loads(hosts_ret.content)
  49. hosts_mapping_by_node_id = dict()
  50. for host in hosts_ret['data']:
  51. hosts_mapping_by_node_id[int(host['node_id'])] = host
  52. guests_ret = requests.get(url=guests_url, cookies=request.cookies)
  53. guests_ret = json.loads(guests_ret.content)
  54. os_templates_ret = requests.get(url=os_templates_url, cookies=request.cookies)
  55. os_templates_ret = json.loads(os_templates_ret.content)
  56. os_templates_mapping_by_id = dict()
  57. for os_template in os_templates_ret['data']:
  58. os_templates_mapping_by_id[os_template['id']] = os_template
  59. guests_uuid = list()
  60. for guest in guests_ret['data']:
  61. guests_uuid.append(guest['uuid'])
  62. guests_boot_jobs_ret = {'data': dict()}
  63. if guests_uuid.__len__() > 0:
  64. # 获取指定 Guest 的启动作业 ID
  65. guests_boot_jobs_url = host_url + url_for('api_guests.r_get_boot_jobs', uuids=','.join(guests_uuid))
  66. guests_boot_jobs_ret = requests.get(url=guests_boot_jobs_url, cookies=request.cookies)
  67. guests_boot_jobs_ret = json.loads(guests_boot_jobs_ret.content)
  68. # 统一单个、多个的返回JSON格式
  69. if guests_uuid.__len__() == 1:
  70. guests_boot_jobs_ret['data'] = {guests_uuid[0]: guests_boot_jobs_ret['data']}
  71. last_page = int(ceil(guests_ret['paging']['total'] / float(page_size)))
  72. page_length = 5
  73. pages = list()
  74. if page < int(ceil(page_length / 2.0)):
  75. for i in range(1, page_length + 1):
  76. pages.append(i)
  77. if i == last_page or last_page == 0:
  78. break
  79. elif last_page - page < page_length / 2:
  80. for i in range(last_page - page_length + 1, last_page + 1):
  81. if i < 1:
  82. continue
  83. pages.append(i)
  84. else:
  85. for i in range(page - page_length / 2, page + int(ceil(page_length / 2.0))):
  86. pages.append(i)
  87. if i == last_page or last_page == 0:
  88. break
  89. return render_template('guests_show.html', guests_ret=guests_ret, resource_path=resource_path,
  90. os_templates_mapping_by_id=os_templates_mapping_by_id,
  91. hosts_mapping_by_node_id=hosts_mapping_by_node_id,
  92. guests_boot_jobs_ret=guests_boot_jobs_ret, page=page,
  93. page_size=page_size, keyword=keyword, pages=pages, last_page=last_page)
  94. def create():
  95. host_url = request.host_url.rstrip('/')
  96. if request.method == 'POST':
  97. ability = request.form.get('ability')
  98. os_template_id = request.form.get('os_template_id')
  99. quantity = request.form.get('quantity')
  100. password = request.form.get('password')
  101. remark = request.form.get('remark')
  102. allocation_by_random = 'allocation_by_random' in request.form
  103. node_id = request.form.get('node_id')
  104. if not isinstance(ability, basestring):
  105. pass
  106. m = re.search('^(\d+)c(\d+)g$', ability.lower())
  107. if m is None:
  108. pass
  109. cpu = m.groups()[0]
  110. memory = m.groups()[1]
  111. payload = {
  112. "cpu": int(cpu),
  113. "memory": int(memory),
  114. "os_template_id": int(os_template_id),
  115. "quantity": int(quantity),
  116. "remark": remark,
  117. "password": password,
  118. "lease_term": 100
  119. }
  120. if not allocation_by_random:
  121. payload['node_id'] = node_id
  122. url = host_url + '/api/guest'
  123. headers = {'content-type': 'application/json'}
  124. r = requests.post(url, data=json.dumps(payload), headers=headers, cookies=request.cookies)
  125. j_r = json.loads(r.content)
  126. if j_r['state']['code'] != '200':
  127. return render_template('failure.html',
  128. go_back_url='/guests',
  129. timeout=10000, title='创建失败',
  130. message_title='创建实例失败',
  131. message=j_r['state']['sub']['zh-cn'])
  132. guests_url = host_url + url_for('api_guests.r_get_by_filter')
  133. guests_ret = requests.get(url=guests_url, cookies=request.cookies)
  134. guests_ret = json.loads(guests_ret.content)
  135. page_size = 10
  136. last_page = int(ceil(guests_ret['paging']['total'] / float(page_size)))
  137. return render_template('success.html',
  138. go_back_url='/guests?page={0}&page_size={1}'.format(last_page, page_size),
  139. timeout=10000, title='提交成功',
  140. message_title='创建实例的请求已被接受',
  141. message='您所提交的资源正在创建中。根据所提交资源的大小,需要等待几到十几分钟。页面将在10秒钟后自动跳转到实例列表页面!')
  142. else:
  143. os_template_url = host_url + url_for('api_os_templates.r_get_by_filter')
  144. hosts_url = host_url + url_for('api_hosts.r_get_by_filter', alive=True)
  145. os_template_ret = requests.get(url=os_template_url, cookies=request.cookies)
  146. os_template_ret = json.loads(os_template_ret.content)
  147. hosts_ret = requests.get(url=hosts_url, cookies=request.cookies)
  148. hosts_ret = json.loads(hosts_ret.content)
  149. return render_template('guest_create.html', os_template_ret=os_template_ret, hosts_ret=hosts_ret)
  150. def port_is_opened(port):
  151. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  152. result = s.connect_ex(('0.0.0.0', port))
  153. if result == 0:
  154. return True
  155. else:
  156. return False
  157. def vnc(uuid):
  158. host_url = request.host_url.rstrip('/')
  159. hosts_url = host_url + url_for('api_hosts.r_get_by_filter')
  160. guest_url = host_url + url_for('api_guests.r_get', uuids=uuid)
  161. guest_ret = requests.get(url=guest_url, cookies=request.cookies)
  162. guest_ret = json.loads(guest_ret.content)
  163. hosts_ret = requests.get(url=hosts_url, cookies=request.cookies)
  164. hosts_ret = json.loads(hosts_ret.content)
  165. hosts_mapping_by_node_id = dict()
  166. for host in hosts_ret['data']:
  167. hosts_mapping_by_node_id[int(host['node_id'])] = host
  168. port = random.randrange(50000, 60000)
  169. while True:
  170. if not port_is_opened(port=port):
  171. break
  172. port = random.randrange(50000, 60000)
  173. payload = {'listen_port': port, 'target_host': hosts_mapping_by_node_id[guest_ret['data']['node_id']]['hostname'],
  174. 'target_port': guest_ret['data']['vnc_port']}
  175. db.r.rpush(config['ipc_queue'], json.dumps(payload, ensure_ascii=False))
  176. time.sleep(1)
  177. return render_template('vnc_lite.html', port=port, password=guest_ret['data']['vnc_password'])
  178. def detail(uuid):
  179. host_url = request.host_url.rstrip('/')
  180. hosts_url = host_url + url_for('api_hosts.r_get_by_filter')
  181. guest_url = host_url + url_for('api_guests.r_get', uuids=uuid)
  182. hosts_ret = requests.get(url=hosts_url, cookies=request.cookies)
  183. hosts_ret = json.loads(hosts_ret.content)
  184. hosts_mapping_by_node_id = dict()
  185. for host in hosts_ret['data']:
  186. hosts_mapping_by_node_id[int(host['node_id'])] = host
  187. guest_ret = requests.get(url=guest_url, cookies=request.cookies)
  188. guest_ret = json.loads(guest_ret.content)
  189. os_template_url = host_url + url_for('api_os_templates.r_get', ids=guest_ret['data']['os_template_id'].__str__())
  190. os_template_ret = requests.get(url=os_template_url, cookies=request.cookies)
  191. os_template_ret = json.loads(os_template_ret.content)
  192. disks_url = host_url + url_for('api_disks.r_get_by_filter', filter='guest_uuid:in:' + guest_ret['data']['uuid'])
  193. disks_ret = requests.get(url=disks_url, cookies=request.cookies)
  194. disks_ret = json.loads(disks_ret.content)
  195. url = host_url + '/api/config'
  196. config_ret = requests.get(url=url, cookies=request.cookies)
  197. config_ret = json.loads(config_ret.content)
  198. return render_template('guest_detail.html', uuid=uuid, guest_ret=guest_ret, os_template_ret=os_template_ret,
  199. hosts_mapping_by_node_id=hosts_mapping_by_node_id,
  200. disks_ret=disks_ret, config_ret=config_ret)
  201. def success():
  202. return render_template('success.html', go_back_url='/guests', timeout=10000, title='提交成功',
  203. message_title='创建实例的请求已被接受',
  204. message='您所提交的资源正在创建中。根据所提交资源的大小,需要等待几到十几分钟。页面将在10秒钟后自动跳转到实例列表页面!')
  205. def show_boot_job(uuid):
  206. host_url = request.host_url.rstrip('/')
  207. guest_url = host_url + url_for('api_guests.r_get', uuids=uuid)
  208. guest_ret = requests.get(url=guest_url, cookies=request.cookies)
  209. guest_ret = json.loads(guest_ret.content)
  210. guest_boot_jobs_url = host_url + url_for('api_guests.r_get_boot_jobs', uuids=uuid)
  211. guest_boot_jobs_ret = requests.get(url=guest_boot_jobs_url, cookies=request.cookies)
  212. guest_boot_jobs_ret = json.loads(guest_boot_jobs_ret.content)
  213. boot_jobs_url = host_url + url_for('api_boot_jobs.r_get_by_filter',
  214. filter='id:in:' + ','.join(guest_boot_jobs_ret['data']['boot_jobs']))
  215. boot_jobs_ret = requests.get(url=boot_jobs_url, cookies=request.cookies)
  216. boot_jobs_ret = json.loads(boot_jobs_ret.content)
  217. boot_jobs_mapping_by_id = dict()
  218. for boot_job in boot_jobs_ret['data']:
  219. boot_jobs_mapping_by_id[boot_job['id']] = boot_job
  220. return render_template('guest_boot_jobs.html', uuid=uuid, guest_ret=guest_ret,
  221. guest_boot_jobs_ret=guest_boot_jobs_ret, boot_jobs_mapping_by_id=boot_jobs_mapping_by_id)
  222. def show_guests_boot_jobs():
  223. page = int(request.args.get('page', 1))
  224. page_size = int(request.args.get('page_size', 10))
  225. host_url = request.host_url.rstrip('/')
  226. # 获取所有有启动作业的 Guests uuid
  227. uuids_of_all_had_boot_job_url = host_url + url_for('api_guests.r_get_uuids_of_all_had_boot_job')
  228. uuids_of_all_had_boot_job_ret = requests.get(url=uuids_of_all_had_boot_job_url, cookies=request.cookies)
  229. uuids_of_all_had_boot_job_ret = json.loads(uuids_of_all_had_boot_job_ret.content)
  230. guests_uuid = uuids_of_all_had_boot_job_ret['data']
  231. guests_boot_jobs_ret = {'data': dict()}
  232. if guests_uuid.__len__() > 0:
  233. # 获取指定 Guest 的启动作业 ID
  234. guests_boot_jobs_url = host_url + url_for('api_guests.r_get_boot_jobs',
  235. uuids=','.join(guests_uuid[page_size * (page - 1): page_size * page]))
  236. guests_boot_jobs_ret = requests.get(url=guests_boot_jobs_url, cookies=request.cookies)
  237. guests_boot_jobs_ret = json.loads(guests_boot_jobs_ret.content)
  238. # 统一单个、多个的返回JSON格式
  239. if guests_uuid.__len__() == 1:
  240. guests_boot_jobs_ret['data'] = {guests_uuid[0]: guests_boot_jobs_ret['data']}
  241. # 取出 Guests 的启动作业 IDs,并去重
  242. guests_boot_jobs_id = list()
  243. for uuid, guest_boot_jobs in guests_boot_jobs_ret['data'].items():
  244. guests_boot_jobs_id.extend(guest_boot_jobs['boot_jobs'])
  245. guests_boot_jobs_id = list(set(guests_boot_jobs_id))
  246. # 获取指定启动作业ID 的启动作业
  247. boot_jobs_url = host_url + url_for('api_boot_jobs.r_get_by_filter',
  248. filter='id:in:' + ','.join(guests_boot_jobs_id))
  249. boot_jobs_ret = requests.get(url=boot_jobs_url, cookies=request.cookies)
  250. boot_jobs_ret = json.loads(boot_jobs_ret.content)
  251. # 启动作业 ID 与启动作业的映射
  252. boot_jobs_mapping_by_id = dict()
  253. for boot_job in boot_jobs_ret['data']:
  254. boot_jobs_mapping_by_id[boot_job['id']] = boot_job
  255. guests_url = host_url + url_for('api_guests.r_get_by_filter',
  256. filter='uuid:in:' + ','.join(guests_uuid[page_size * (page - 1): page_size * page]))
  257. guests_ret = requests.get(url=guests_url, cookies=request.cookies)
  258. guests_ret = json.loads(guests_ret.content)
  259. # Guest uuid 与 Guest 的映射
  260. guests_mapping_by_uuid = dict()
  261. for guest in guests_ret['data']:
  262. guests_mapping_by_uuid[guest['uuid']] = guest
  263. os_templates_url = host_url + url_for('api_os_templates.r_get_by_filter')
  264. os_templates_ret = requests.get(url=os_templates_url, cookies=request.cookies)
  265. os_templates_ret = json.loads(os_templates_ret.content)
  266. # 模板与模板 ID 的映射
  267. os_templates_mapping_by_id = dict()
  268. for os_template in os_templates_ret['data']:
  269. os_templates_mapping_by_id[os_template['id']] = os_template
  270. paging_total = guests_uuid.__len__()
  271. last_page = int(ceil(paging_total / float(page_size)))
  272. if last_page == 0:
  273. last_page = 1
  274. page_length = 5
  275. pages = list()
  276. if page < int(ceil(page_length / 2.0)):
  277. for i in range(1, page_length + 1):
  278. pages.append(i)
  279. if i == last_page:
  280. break
  281. elif last_page - page < page_length / 2:
  282. for i in range(last_page - page_length + 1, last_page + 1):
  283. if i < 1:
  284. continue
  285. pages.append(i)
  286. else:
  287. for i in range(page - page_length / 2, page + int(ceil(page_length / 2.0))):
  288. pages.append(i)
  289. if i == last_page:
  290. break
  291. return render_template('guests_boot_jobs.html', guests_boot_jobs_ret=guests_boot_jobs_ret,
  292. boot_jobs_mapping_by_id=boot_jobs_mapping_by_id,
  293. guests_mapping_by_uuid=guests_mapping_by_uuid,
  294. os_templates_mapping_by_id=os_templates_mapping_by_id, page=page, page_size=page_size,
  295. pages=pages, last_page=last_page, paging_total=paging_total)