guest.py 26 KB

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