guest.py 25 KB

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