guest.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import copy
  4. from flask import Blueprint
  5. from flask import request
  6. import json
  7. from uuid import uuid4
  8. import jimit as ji
  9. from api.base import Base
  10. from models import DiskState
  11. from models import OperateRule
  12. from models.initialize import app, dev_table
  13. from models import Database as db
  14. from models import Config
  15. from models import Disk
  16. from models import Rules
  17. from models import Utils
  18. from models import Guest
  19. from models import OSTemplate
  20. from models import GuestXML
  21. from models import status
  22. __author__ = 'James Iter'
  23. __date__ = '2017/3/22'
  24. __contact__ = 'james.iter.cn@gmail.com'
  25. __copyright__ = '(c) 2017 by James Iter.'
  26. blueprint = Blueprint(
  27. 'api_guest',
  28. __name__,
  29. url_prefix='/api/guest'
  30. )
  31. blueprints = Blueprint(
  32. 'api_guests',
  33. __name__,
  34. url_prefix='/api/guests'
  35. )
  36. guest_base = Base(the_class=Guest, the_blueprint=blueprint, the_blueprints=blueprints)
  37. @Utils.dumps2response
  38. def r_create():
  39. args_rules = [
  40. Rules.CPU.value,
  41. Rules.MEMORY.value,
  42. Rules.OS_TEMPLATE_ID.value,
  43. Rules.QUANTITY.value,
  44. Rules.REMARK.value,
  45. Rules.PASSWORD.value,
  46. Rules.LEASE_TERM.value
  47. ]
  48. try:
  49. ret = dict()
  50. ret['state'] = ji.Common.exchange_state(20000)
  51. ji.Check.previewing(args_rules, request.json)
  52. config = Config()
  53. config.id = 1
  54. config.get()
  55. os_template = OSTemplate()
  56. os_template.id = request.json.get('os_template_id')
  57. if not os_template.exist():
  58. ret['state'] = ji.Common.exchange_state(40450)
  59. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', os_template.id.__str__()])
  60. return ret
  61. os_template.get()
  62. # 重置密码的 boot job id 固定为 1
  63. boot_jobs_id = [1, os_template.boot_job_id]
  64. boot_jobs, boot_jobs_count = OperateRule.get_by_filter(
  65. filter_str='boot_job_id:in:' +
  66. ','.join(['{0}'.format(boot_job_id) for boot_job_id in boot_jobs_id]).__str__())
  67. if db.r.scard(app.config['ip_available_set']) < 1:
  68. ret['state'] = ji.Common.exchange_state(50350)
  69. return ret
  70. available_hosts = Guest.get_available_hosts()
  71. if available_hosts.__len__() == 0:
  72. ret['state'] = ji.Common.exchange_state(50351)
  73. return ret
  74. quantity = request.json.get('quantity')
  75. while quantity:
  76. quantity -= 1
  77. guest = Guest()
  78. guest.uuid = uuid4().__str__()
  79. guest.cpu = request.json.get('cpu')
  80. # 虚拟机内存单位,模板生成方法中已置其为GiB
  81. guest.memory = request.json.get('memory')
  82. guest.os_template_id = request.json.get('os_template_id')
  83. guest.label = ji.Common.generate_random_code(length=8)
  84. guest.remark = request.json.get('remark', '')
  85. guest.password = request.json.get('password')
  86. if guest.password is None or guest.password.__len__() < 1:
  87. guest.password = ji.Common.generate_random_code(length=16)
  88. guest.ip = db.r.spop(app.config['ip_available_set'])
  89. db.r.sadd(app.config['ip_used_set'], guest.ip)
  90. guest.network = config.vm_network
  91. guest.manage_network = config.vm_manage_network
  92. guest.vnc_port = db.r.spop(app.config['vnc_port_available_set'])
  93. db.r.sadd(app.config['vnc_port_used_set'], guest.vnc_port)
  94. guest.vnc_password = ji.Common.generate_random_code(length=16)
  95. disk = Disk()
  96. disk.uuid = guest.uuid
  97. disk.remark = guest.label.__str__() + '_SystemImage'
  98. disk.format = 'qcow2'
  99. disk.sequence = 0
  100. disk.size = 0
  101. disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
  102. disk.guest_uuid = ''
  103. disk.create()
  104. guest_xml = GuestXML(guest=guest, disk=disk, config=config, os_type=os_template.os_type)
  105. guest.xml = guest_xml.get_domain()
  106. # 在可用计算节点中平均分配任务
  107. chosen_host = available_hosts[quantity % available_hosts.__len__()]
  108. guest.on_host = chosen_host['hostname']
  109. guest.create()
  110. # 替换占位符为有效内容
  111. _boot_jobs = copy.deepcopy(boot_jobs)
  112. for k, v in enumerate(_boot_jobs):
  113. _boot_jobs[k]['content'] = v['content'].replace('{IP}', guest.ip).\
  114. replace('{HOSTNAME}', guest.label). \
  115. replace('{PASSWORD}', guest.password). \
  116. replace('{NETMASK}', config.netmask).\
  117. replace('{GATEWAY}', config.gateway).\
  118. replace('{DNS1}', config.dns1).\
  119. replace('{DNS2}', config.dns2)
  120. _boot_jobs[k]['command'] = v['command'].replace('{IP}', guest.ip). \
  121. replace('{HOSTNAME}', guest.label). \
  122. replace('{PASSWORD}', guest.password). \
  123. replace('{NETMASK}', config.netmask). \
  124. replace('{GATEWAY}', config.gateway). \
  125. replace('{DNS1}', config.dns1). \
  126. replace('{DNS2}', config.dns2)
  127. message = {
  128. '_object': 'guest',
  129. 'action': 'create',
  130. 'uuid': guest.uuid,
  131. 'storage_mode': config.storage_mode,
  132. 'dfs_volume': config.dfs_volume,
  133. 'hostname': guest.on_host,
  134. 'name': guest.label,
  135. 'template_path': os_template.path,
  136. 'os_type': os_template.os_type,
  137. 'disk': disk.__dict__,
  138. 'xml': guest_xml.get_domain(),
  139. 'boot_jobs': _boot_jobs,
  140. 'passback_parameters': {'boot_jobs_id': boot_jobs_id}
  141. }
  142. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  143. return ret
  144. except ji.PreviewingError, e:
  145. return json.loads(e.message)
  146. @Utils.dumps2response
  147. def r_reboot(uuids):
  148. args_rules = [
  149. Rules.UUIDS.value
  150. ]
  151. try:
  152. ji.Check.previewing(args_rules, {'uuids': uuids})
  153. guest = Guest()
  154. for uuid in uuids.split(','):
  155. guest.uuid = uuid
  156. guest.get_by('uuid')
  157. for uuid in uuids.split(','):
  158. guest.uuid = uuid
  159. guest.get_by('uuid')
  160. message = {
  161. '_object': 'guest',
  162. 'action': 'reboot',
  163. 'uuid': uuid,
  164. 'hostname': guest.on_host
  165. }
  166. Guest.emit_instruction(message=json.dumps(message))
  167. ret = dict()
  168. ret['state'] = ji.Common.exchange_state(20000)
  169. return ret
  170. except ji.PreviewingError, e:
  171. return json.loads(e.message)
  172. @Utils.dumps2response
  173. def r_force_reboot(uuids):
  174. args_rules = [
  175. Rules.UUIDS.value
  176. ]
  177. try:
  178. ji.Check.previewing(args_rules, {'uuids': uuids})
  179. guest = Guest()
  180. for uuid in uuids.split(','):
  181. guest.uuid = uuid
  182. guest.get_by('uuid')
  183. for uuid in uuids.split(','):
  184. guest.uuid = uuid
  185. guest.get_by('uuid')
  186. message = {
  187. '_object': 'guest',
  188. 'action': 'force_reboot',
  189. 'uuid': uuid,
  190. 'hostname': guest.on_host
  191. }
  192. Guest.emit_instruction(message=json.dumps(message))
  193. ret = dict()
  194. ret['state'] = ji.Common.exchange_state(20000)
  195. return ret
  196. except ji.PreviewingError, e:
  197. return json.loads(e.message)
  198. @Utils.dumps2response
  199. def r_shutdown(uuids):
  200. args_rules = [
  201. Rules.UUIDS.value
  202. ]
  203. try:
  204. ji.Check.previewing(args_rules, {'uuids': uuids})
  205. guest = Guest()
  206. for uuid in uuids.split(','):
  207. guest.uuid = uuid
  208. guest.get_by('uuid')
  209. for uuid in uuids.split(','):
  210. guest.uuid = uuid
  211. guest.get_by('uuid')
  212. message = {
  213. '_object': 'guest',
  214. 'action': 'shutdown',
  215. 'uuid': uuid,
  216. 'hostname': guest.on_host
  217. }
  218. Guest.emit_instruction(message=json.dumps(message))
  219. ret = dict()
  220. ret['state'] = ji.Common.exchange_state(20000)
  221. return ret
  222. except ji.PreviewingError, e:
  223. return json.loads(e.message)
  224. @Utils.dumps2response
  225. def r_force_shutdown(uuids):
  226. args_rules = [
  227. Rules.UUIDS.value
  228. ]
  229. try:
  230. ji.Check.previewing(args_rules, {'uuids': uuids})
  231. guest = Guest()
  232. for uuid in uuids.split(','):
  233. guest.uuid = uuid
  234. guest.get_by('uuid')
  235. for uuid in uuids.split(','):
  236. guest.uuid = uuid
  237. guest.get_by('uuid')
  238. message = {
  239. '_object': 'guest',
  240. 'action': 'force_shutdown',
  241. 'uuid': uuid,
  242. 'hostname': guest.on_host
  243. }
  244. Guest.emit_instruction(message=json.dumps(message))
  245. ret = dict()
  246. ret['state'] = ji.Common.exchange_state(20000)
  247. return ret
  248. except ji.PreviewingError, e:
  249. return json.loads(e.message)
  250. @Utils.dumps2response
  251. def r_boot(uuids):
  252. # TODO: 做好关系依赖判断,比如boot不可以对suspend的实例操作。
  253. args_rules = [
  254. Rules.UUIDS.value
  255. ]
  256. try:
  257. ji.Check.previewing(args_rules, {'uuids': uuids})
  258. guest = Guest()
  259. for uuid in uuids.split(','):
  260. guest.uuid = uuid
  261. guest.get_by('uuid')
  262. config = Config()
  263. config.id = 1
  264. config.get()
  265. for uuid in uuids.split(','):
  266. guest.uuid = uuid
  267. guest.get_by('uuid')
  268. _, boot_jobs_id = guest.get_boot_jobs()
  269. boot_jobs = list()
  270. if boot_jobs_id.__len__() > 0:
  271. boot_jobs, count = OperateRule.get_by_filter(filter_str='boot_job_id:in:' + ','.join(boot_jobs_id))
  272. # 替换占位符为有效内容
  273. for k, v in enumerate(boot_jobs):
  274. boot_jobs[k]['content'] = v['content'].replace('{IP}', guest.ip). \
  275. replace('{HOSTNAME}', guest.label). \
  276. replace('{PASSWORD}', guest.password). \
  277. replace('{NETMASK}', config.netmask). \
  278. replace('{GATEWAY}', config.gateway). \
  279. replace('{DNS1}', config.dns1). \
  280. replace('{DNS2}', config.dns2)
  281. boot_jobs[k]['command'] = v['command'].replace('{IP}', guest.ip). \
  282. replace('{HOSTNAME}', guest.label). \
  283. replace('{PASSWORD}', guest.password). \
  284. replace('{NETMASK}', config.netmask). \
  285. replace('{GATEWAY}', config.gateway). \
  286. replace('{DNS1}', config.dns1). \
  287. replace('{DNS2}', config.dns2)
  288. message = {
  289. '_object': 'guest',
  290. 'action': 'boot',
  291. 'uuid': uuid,
  292. 'boot_jobs': boot_jobs,
  293. 'hostname': guest.on_host,
  294. 'passback_parameters': {'boot_jobs_id': boot_jobs_id}
  295. }
  296. Guest.emit_instruction(message=json.dumps(message))
  297. ret = dict()
  298. ret['state'] = ji.Common.exchange_state(20000)
  299. return ret
  300. except ji.PreviewingError, e:
  301. return json.loads(e.message)
  302. @Utils.dumps2response
  303. def r_suspend(uuids):
  304. args_rules = [
  305. Rules.UUIDS.value
  306. ]
  307. try:
  308. ji.Check.previewing(args_rules, {'uuids': uuids})
  309. guest = Guest()
  310. for uuid in uuids.split(','):
  311. guest.uuid = uuid
  312. guest.get_by('uuid')
  313. for uuid in uuids.split(','):
  314. guest.uuid = uuid
  315. guest.get_by('uuid')
  316. message = {
  317. '_object': 'guest',
  318. 'action': 'suspend',
  319. 'uuid': uuid,
  320. 'hostname': guest.on_host
  321. }
  322. Guest.emit_instruction(message=json.dumps(message))
  323. ret = dict()
  324. ret['state'] = ji.Common.exchange_state(20000)
  325. return ret
  326. except ji.PreviewingError, e:
  327. return json.loads(e.message)
  328. @Utils.dumps2response
  329. def r_resume(uuids):
  330. args_rules = [
  331. Rules.UUIDS.value
  332. ]
  333. try:
  334. ji.Check.previewing(args_rules, {'uuids': uuids})
  335. guest = Guest()
  336. for uuid in uuids.split(','):
  337. guest.uuid = uuid
  338. guest.get_by('uuid')
  339. for uuid in uuids.split(','):
  340. guest.uuid = uuid
  341. guest.get_by('uuid')
  342. message = {
  343. '_object': 'guest',
  344. 'action': 'resume',
  345. 'uuid': uuid,
  346. 'hostname': guest.on_host
  347. }
  348. Guest.emit_instruction(message=json.dumps(message))
  349. ret = dict()
  350. ret['state'] = ji.Common.exchange_state(20000)
  351. return ret
  352. except ji.PreviewingError, e:
  353. return json.loads(e.message)
  354. @Utils.dumps2response
  355. def r_delete(uuids):
  356. args_rules = [
  357. Rules.UUIDS.value
  358. ]
  359. # TODO: 加入是否删除使用的数据磁盘开关,如果为True,则顺便删除使用的磁盘。否则解除该磁盘被使用的状态。
  360. try:
  361. ji.Check.previewing(args_rules, {'uuids': uuids})
  362. guest = Guest()
  363. # 检测所指定的 UUDIs 实例都存在
  364. for uuid in uuids.split(','):
  365. guest.uuid = uuid
  366. guest.get_by('uuid')
  367. config = Config()
  368. config.id = 1
  369. config.get()
  370. # 执行删除操作
  371. for uuid in uuids.split(','):
  372. guest.uuid = uuid
  373. guest.get_by('uuid')
  374. message = {
  375. '_object': 'guest',
  376. 'action': 'delete',
  377. 'uuid': uuid,
  378. 'storage_mode': config.storage_mode,
  379. 'dfs_volume': config.dfs_volume,
  380. 'hostname': guest.on_host
  381. }
  382. Guest.emit_instruction(message=json.dumps(message))
  383. # 删除创建失败的 Guest
  384. if guest.status == status.GuestState.dirty.value:
  385. disk = Disk()
  386. disk.uuid = guest.uuid
  387. disk.get_by('uuid')
  388. if disk.state == status.DiskState.pending.value:
  389. disk.delete()
  390. guest.delete()
  391. ret = dict()
  392. ret['state'] = ji.Common.exchange_state(20000)
  393. return ret
  394. except ji.PreviewingError, e:
  395. return json.loads(e.message)
  396. @Utils.dumps2response
  397. def r_attach_disk(uuid, disk_uuid):
  398. args_rules = [
  399. Rules.UUID.value,
  400. Rules.DISK_UUID.value
  401. ]
  402. try:
  403. ji.Check.previewing(args_rules, {'uuid': uuid, 'disk_uuid': disk_uuid})
  404. guest = Guest()
  405. guest.uuid = uuid
  406. guest.get_by('uuid')
  407. disk = Disk()
  408. disk.uuid = disk_uuid
  409. disk.get_by('uuid')
  410. config = Config()
  411. config.id = 1
  412. config.get()
  413. ret = dict()
  414. ret['state'] = ji.Common.exchange_state(20000)
  415. # 判断欲挂载的磁盘是否空闲
  416. if disk.guest_uuid.__len__() > 0 or disk.state != DiskState.idle.value:
  417. ret['state'] = ji.Common.exchange_state(41258)
  418. return ret
  419. # 判断 Guest 是否处于可用状态
  420. if guest.status in (status.GuestState.no_state.value, status.GuestState.dirty.value):
  421. ret['state'] = ji.Common.exchange_state(41259)
  422. return ret
  423. # 判断 Guest 与 磁盘是否在同一宿主机上
  424. if config.storage_mode in [status.StorageMode.local.value, status.StorageMode.shared_mount.value]:
  425. if guest.on_host != disk.on_host:
  426. ret['state'] = ji.Common.exchange_state(41260)
  427. return ret
  428. # 通过检测未被使用的序列,来确定当前磁盘在目标 Guest 身上的序列
  429. disk.guest_uuid = guest.uuid
  430. disks, count = disk.get_by_filter(filter_str='guest_uuid:in:' + guest.uuid)
  431. already_used_sequence = list()
  432. for _disk in disks:
  433. already_used_sequence.append(_disk['sequence'])
  434. for sequence in range(0, dev_table.__len__()):
  435. if sequence not in already_used_sequence:
  436. disk.sequence = sequence
  437. break
  438. disk.state = DiskState.mounting.value
  439. guest_xml = GuestXML(guest=guest, disk=disk, config=config)
  440. message = {
  441. '_object': 'guest',
  442. 'action': 'attach_disk',
  443. 'uuid': uuid,
  444. 'hostname': guest.on_host,
  445. 'xml': guest_xml.get_disk(),
  446. 'passback_parameters': {'disk_uuid': disk.uuid, 'sequence': disk.sequence}
  447. }
  448. Guest.emit_instruction(message=json.dumps(message))
  449. disk.update()
  450. return ret
  451. except ji.PreviewingError, e:
  452. return json.loads(e.message)
  453. @Utils.dumps2response
  454. def r_detach_disk(disk_uuid):
  455. args_rules = [
  456. Rules.DISK_UUID.value
  457. ]
  458. try:
  459. ji.Check.previewing(args_rules, {'disk_uuid': disk_uuid})
  460. disk = Disk()
  461. disk.uuid = disk_uuid
  462. disk.get_by('uuid')
  463. ret = dict()
  464. ret['state'] = ji.Common.exchange_state(20000)
  465. if disk.state != DiskState.mounted.value or disk.sequence == 0:
  466. # 表示未被任何实例使用,已被分离
  467. # 序列为 0 的表示实例系统盘,系统盘不可以被分离
  468. # TODO: 系统盘单独范围其它状态
  469. return ret
  470. guest = Guest()
  471. guest.uuid = disk.guest_uuid
  472. guest.get_by('uuid')
  473. # 判断 Guest 是否处于可用状态
  474. if guest.status in (status.GuestState.no_state.value, status.GuestState.dirty.value):
  475. ret['state'] = ji.Common.exchange_state(41259)
  476. return ret
  477. config = Config()
  478. config.id = 1
  479. config.get()
  480. guest_xml = GuestXML(guest=guest, disk=disk, config=config)
  481. message = {
  482. '_object': 'guest',
  483. 'action': 'detach_disk',
  484. 'uuid': disk.guest_uuid,
  485. 'hostname': guest.on_host,
  486. 'xml': guest_xml.get_disk(),
  487. 'passback_parameters': {'disk_uuid': disk.uuid}
  488. }
  489. Guest.emit_instruction(message=json.dumps(message))
  490. disk.state = DiskState.unloading.value
  491. disk.update()
  492. return ret
  493. except ji.PreviewingError, e:
  494. return json.loads(e.message)
  495. @Utils.dumps2response
  496. def r_migrate(uuids, destination_host):
  497. args_rules = [
  498. Rules.UUIDS.value,
  499. Rules.DESTINATION_HOST.value
  500. ]
  501. try:
  502. ji.Check.previewing(args_rules, {'uuids': uuids, 'destination_host': destination_host})
  503. guest = Guest()
  504. for uuid in uuids.split(','):
  505. guest.uuid = uuid
  506. guest.get_by('uuid')
  507. config = Config()
  508. config.id = 1
  509. config.get()
  510. for uuid in uuids.split(','):
  511. guest.uuid = uuid
  512. guest.get_by('uuid')
  513. message = {
  514. '_object': 'guest',
  515. 'action': 'migrate',
  516. 'uuid': uuid,
  517. 'hostname': guest.on_host,
  518. 'storage_mode': config.storage_mode,
  519. 'duri': 'qemu+ssh://' + destination_host + '/system'
  520. }
  521. Guest.emit_instruction(message=json.dumps(message))
  522. ret = dict()
  523. ret['state'] = ji.Common.exchange_state(20000)
  524. return ret
  525. except ji.PreviewingError, e:
  526. return json.loads(e.message)
  527. @Utils.dumps2response
  528. def r_get(uuids):
  529. return guest_base.get(ids=uuids, ids_rule=Rules.UUIDS.value, by_field='uuid')
  530. @Utils.dumps2response
  531. def r_get_by_filter():
  532. return guest_base.get_by_filter()
  533. @Utils.dumps2response
  534. def r_content_search():
  535. return guest_base.content_search()
  536. @Utils.dumps2response
  537. def r_distribute_count():
  538. from models import Guest
  539. rows, count = Guest.get_all()
  540. ret = dict()
  541. ret['state'] = ji.Common.exchange_state(20000)
  542. ret['data'] = {
  543. 'os_template_id': dict(),
  544. 'status': dict(),
  545. 'on_host': dict(),
  546. 'cpu_memory': dict(),
  547. 'cpu': 0,
  548. 'memory': 0,
  549. 'guests': rows.__len__()
  550. }
  551. for guest in rows:
  552. if guest['os_template_id'] not in ret['data']['os_template_id']:
  553. ret['data']['os_template_id'][guest['os_template_id']] = 0
  554. if guest['status'] not in ret['data']['status']:
  555. ret['data']['status'][guest['status']] = 0
  556. if guest['on_host'] not in ret['data']['on_host']:
  557. ret['data']['on_host'][guest['on_host']] = 0
  558. cpu_memory = '_'.join([str(guest['cpu']), str(guest['memory'])])
  559. if cpu_memory not in ret['data']['cpu_memory']:
  560. ret['data']['cpu_memory'][cpu_memory] = 0
  561. ret['data']['os_template_id'][guest['os_template_id']] += 1
  562. ret['data']['status'][guest['status']] += 1
  563. ret['data']['on_host'][guest['on_host']] += 1
  564. ret['data']['cpu_memory'][cpu_memory] += 1
  565. ret['data']['cpu'] += guest['cpu']
  566. ret['data']['memory'] += guest['memory']
  567. return ret
  568. @Utils.dumps2response
  569. def r_update(uuid):
  570. args_rules = [
  571. Rules.UUID.value
  572. ]
  573. if 'remark' in request.json:
  574. args_rules.append(
  575. Rules.REMARK.value,
  576. )
  577. if args_rules.__len__() < 2:
  578. ret = dict()
  579. ret['state'] = ji.Common.exchange_state(20000)
  580. return ret
  581. request.json['uuid'] = uuid
  582. try:
  583. ji.Check.previewing(args_rules, request.json)
  584. guest = Guest()
  585. guest.uuid = uuid
  586. guest.get_by('uuid')
  587. guest.remark = request.json.get('remark', guest.label)
  588. guest.update()
  589. guest.get()
  590. ret = dict()
  591. ret['state'] = ji.Common.exchange_state(20000)
  592. ret['data'] = guest.__dict__
  593. return ret
  594. except ji.PreviewingError, e:
  595. return json.loads(e.message)
  596. @Utils.dumps2response
  597. def r_add_boot_jobs(uuids, boot_jobs_id):
  598. args_rules = [
  599. Rules.UUIDS.value,
  600. Rules.BOOT_JOBS_ID.value
  601. ]
  602. try:
  603. ji.Check.previewing(args_rules, {'uuids': uuids, 'boot_jobs_id': boot_jobs_id})
  604. guest = Guest()
  605. for uuid in uuids.split(','):
  606. guest.uuid = uuid
  607. guest.get_by('uuid')
  608. for uuid in uuids.split(','):
  609. guest.uuid = uuid
  610. guest.add_boot_jobs(boot_jobs_id=boot_jobs_id.split(','))
  611. ret = dict()
  612. ret['state'] = ji.Common.exchange_state(20000)
  613. if uuids.split(',').__len__() > 1:
  614. ret['data'] = dict()
  615. for uuid in uuids.split(','):
  616. guest.uuid = uuid
  617. boot_jobs = dict()
  618. boot_jobs['ttl'], boot_jobs['boot_jobs'] = guest.get_boot_jobs()
  619. ret['data'][uuid] = boot_jobs
  620. else:
  621. guest.uuid = uuids
  622. ret['data'] = dict()
  623. ret['data']['ttl'], ret['data']['boot_jobs'] = guest.get_boot_jobs()
  624. return ret
  625. except ji.PreviewingError, e:
  626. return json.loads(e.message)
  627. @Utils.dumps2response
  628. def r_get_boot_jobs(uuids):
  629. args_rules = [
  630. Rules.UUIDS.value
  631. ]
  632. try:
  633. ji.Check.previewing(args_rules, {'uuids': uuids})
  634. guest = Guest()
  635. for uuid in uuids.split(','):
  636. guest.uuid = uuid
  637. guest.get_by('uuid')
  638. ret = dict()
  639. ret['state'] = ji.Common.exchange_state(20000)
  640. if uuids.split(',').__len__() > 1:
  641. ret['data'] = dict()
  642. for uuid in uuids.split(','):
  643. guest.uuid = uuid
  644. boot_jobs = dict()
  645. boot_jobs['ttl'], boot_jobs['boot_jobs'] = guest.get_boot_jobs()
  646. ret['data'][uuid] = boot_jobs
  647. else:
  648. guest.uuid = uuids
  649. ret['data'] = dict()
  650. ret['data']['ttl'], ret['data']['boot_jobs'] = guest.get_boot_jobs()
  651. return ret
  652. except ji.PreviewingError, e:
  653. return json.loads(e.message)
  654. @Utils.dumps2response
  655. def r_delete_boot_jobs(uuids, boot_jobs_id):
  656. args_rules = [
  657. Rules.UUIDS.value,
  658. Rules.BOOT_JOBS_ID.value
  659. ]
  660. try:
  661. ji.Check.previewing(args_rules, {'uuids': uuids, 'boot_jobs_id': boot_jobs_id})
  662. guest = Guest()
  663. # 检测所指定的 UUDIs 实例都存在
  664. for uuid in uuids.split(','):
  665. guest.uuid = uuid
  666. guest.get_by('uuid')
  667. for uuid in uuids.split(','):
  668. guest.uuid = uuid
  669. guest.delete_boot_jobs(boot_jobs_id=boot_jobs_id.split(','))
  670. ret = dict()
  671. ret['state'] = ji.Common.exchange_state(20000)
  672. return ret
  673. except ji.PreviewingError, e:
  674. return json.loads(e.message)
  675. @Utils.dumps2response
  676. def r_get_uuids_of_all_had_boot_job():
  677. guest = Guest()
  678. try:
  679. ret = dict()
  680. ret['state'] = ji.Common.exchange_state(20000)
  681. ret['data'] = guest.get_uuids_of_all_had_boot_job()
  682. return ret
  683. except ji.PreviewingError, e:
  684. return json.loads(e.message)
  685. @Utils.dumps2response
  686. def r_reset_password(uuids, password):
  687. args_rules = [
  688. Rules.UUIDS.value,
  689. Rules.PASSWORD.value
  690. ]
  691. try:
  692. ji.Check.previewing(args_rules, {'uuids': uuids, 'password': password})
  693. guest = Guest()
  694. # 检测所指定的 UUDIs 实例都存在
  695. for uuid in uuids.split(','):
  696. guest.uuid = uuid
  697. guest.get_by('uuid')
  698. # 重置密码的 boot job id 固定为 1
  699. for uuid in uuids.split(','):
  700. guest.uuid = uuid
  701. guest.get_by('uuid')
  702. guest.password = password
  703. guest.update()
  704. guest.add_boot_jobs(boot_jobs_id=['1'])
  705. ret = dict()
  706. ret['state'] = ji.Common.exchange_state(20000)
  707. return ret
  708. except ji.PreviewingError, e:
  709. return json.loads(e.message)