guest.py 25 KB

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