guest.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  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. lightest_host = None
  121. for k, v in db.r.hgetall(app.config['hosts_info']).items():
  122. v = json.loads(v)
  123. if lightest_host is None:
  124. lightest_host = v
  125. if float(lightest_host['system_load'][0]) / lightest_host['cpu'] > float(v['system_load'][0]) / v['cpu']:
  126. lightest_host = v
  127. create_vm_msg = {
  128. 'action': 'create',
  129. 'uuid': guest.uuid,
  130. 'hostname': lightest_host['hostname'],
  131. 'name': guest.label,
  132. 'glusterfs_volume': config.glusterfs_volume,
  133. 'template_path': os_template.path,
  134. 'disk': disk.__dict__,
  135. 'xml': guest_xml.get_domain(),
  136. 'boot_jobs': _boot_jobs,
  137. 'passback_parameters': {'boot_jobs_id': boot_jobs_id}
  138. }
  139. Guest.emit_instruction(message=json.dumps(create_vm_msg, ensure_ascii=False))
  140. return ret
  141. except ji.PreviewingError, e:
  142. return json.loads(e.message)
  143. @Utils.dumps2response
  144. def r_reboot(uuids):
  145. args_rules = [
  146. Rules.UUIDS.value
  147. ]
  148. try:
  149. ji.Check.previewing(args_rules, {'uuids': uuids})
  150. guest = Guest()
  151. for uuid in uuids.split(','):
  152. guest.uuid = uuid
  153. guest.get_by('uuid')
  154. for uuid in uuids.split(','):
  155. message = {'action': 'reboot', 'uuid': uuid}
  156. Guest.emit_instruction(message=json.dumps(message))
  157. ret = dict()
  158. ret['state'] = ji.Common.exchange_state(20000)
  159. return ret
  160. except ji.PreviewingError, e:
  161. return json.loads(e.message)
  162. @Utils.dumps2response
  163. def r_force_reboot(uuids):
  164. args_rules = [
  165. Rules.UUIDS.value
  166. ]
  167. try:
  168. ji.Check.previewing(args_rules, {'uuids': uuids})
  169. guest = Guest()
  170. for uuid in uuids.split(','):
  171. guest.uuid = uuid
  172. guest.get_by('uuid')
  173. for uuid in uuids.split(','):
  174. message = {'action': 'force_reboot', 'uuid': uuid}
  175. Guest.emit_instruction(message=json.dumps(message))
  176. ret = dict()
  177. ret['state'] = ji.Common.exchange_state(20000)
  178. return ret
  179. except ji.PreviewingError, e:
  180. return json.loads(e.message)
  181. @Utils.dumps2response
  182. def r_shutdown(uuids):
  183. args_rules = [
  184. Rules.UUIDS.value
  185. ]
  186. try:
  187. ji.Check.previewing(args_rules, {'uuids': uuids})
  188. guest = Guest()
  189. for uuid in uuids.split(','):
  190. guest.uuid = uuid
  191. guest.get_by('uuid')
  192. for uuid in uuids.split(','):
  193. message = {'action': 'shutdown', 'uuid': uuid}
  194. Guest.emit_instruction(message=json.dumps(message))
  195. ret = dict()
  196. ret['state'] = ji.Common.exchange_state(20000)
  197. return ret
  198. except ji.PreviewingError, e:
  199. return json.loads(e.message)
  200. @Utils.dumps2response
  201. def r_force_shutdown(uuids):
  202. args_rules = [
  203. Rules.UUIDS.value
  204. ]
  205. try:
  206. ji.Check.previewing(args_rules, {'uuids': uuids})
  207. guest = Guest()
  208. for uuid in uuids.split(','):
  209. guest.uuid = uuid
  210. guest.get_by('uuid')
  211. for uuid in uuids.split(','):
  212. message = {'action': 'force_shutdown', 'uuid': uuid}
  213. Guest.emit_instruction(message=json.dumps(message))
  214. ret = dict()
  215. ret['state'] = ji.Common.exchange_state(20000)
  216. return ret
  217. except ji.PreviewingError, e:
  218. return json.loads(e.message)
  219. @Utils.dumps2response
  220. def r_boot(uuids):
  221. # TODO: 做好关系依赖判断,比如boot不可以对suspend的实例操作。
  222. args_rules = [
  223. Rules.UUIDS.value
  224. ]
  225. try:
  226. ji.Check.previewing(args_rules, {'uuids': uuids})
  227. guest = Guest()
  228. for uuid in uuids.split(','):
  229. guest.uuid = uuid
  230. guest.get_by('uuid')
  231. config = Config()
  232. config.id = 1
  233. config.get()
  234. for uuid in uuids.split(','):
  235. _, boot_jobs_id = guest.get_boot_jobs()
  236. boot_jobs = list()
  237. if boot_jobs_id.__len__() > 0:
  238. boot_jobs, count = OperateRule.get_by_filter(filter_str='boot_job_id:in:' + ','.join(boot_jobs_id))
  239. # 替换占位符为有效内容
  240. for k, v in enumerate(boot_jobs):
  241. boot_jobs[k]['content'] = v['content'].replace('{IP}', guest.ip). \
  242. replace('{HOSTNAME}', guest.label). \
  243. replace('{PASSWORD}', guest.password). \
  244. replace('{NETMASK}', config.netmask). \
  245. replace('{GATEWAY}', config.gateway). \
  246. replace('{DNS1}', config.dns1). \
  247. replace('{DNS2}', config.dns2)
  248. boot_jobs[k]['command'] = v['command'].replace('{IP}', guest.ip). \
  249. replace('{HOSTNAME}', guest.label). \
  250. replace('{PASSWORD}', guest.password). \
  251. replace('{NETMASK}', config.netmask). \
  252. replace('{GATEWAY}', config.gateway). \
  253. replace('{DNS1}', config.dns1). \
  254. replace('{DNS2}', config.dns2)
  255. message = {'action': 'boot', 'uuid': uuid, 'boot_jobs': boot_jobs,
  256. 'passback_parameters': {'boot_jobs_id': boot_jobs_id}}
  257. Guest.emit_instruction(message=json.dumps(message))
  258. ret = dict()
  259. ret['state'] = ji.Common.exchange_state(20000)
  260. return ret
  261. except ji.PreviewingError, e:
  262. return json.loads(e.message)
  263. @Utils.dumps2response
  264. def r_suspend(uuids):
  265. args_rules = [
  266. Rules.UUIDS.value
  267. ]
  268. try:
  269. ji.Check.previewing(args_rules, {'uuids': uuids})
  270. guest = Guest()
  271. for uuid in uuids.split(','):
  272. guest.uuid = uuid
  273. guest.get_by('uuid')
  274. for uuid in uuids.split(','):
  275. message = {'action': 'suspend', 'uuid': uuid}
  276. Guest.emit_instruction(message=json.dumps(message))
  277. ret = dict()
  278. ret['state'] = ji.Common.exchange_state(20000)
  279. return ret
  280. except ji.PreviewingError, e:
  281. return json.loads(e.message)
  282. @Utils.dumps2response
  283. def r_resume(uuids):
  284. args_rules = [
  285. Rules.UUIDS.value
  286. ]
  287. try:
  288. ji.Check.previewing(args_rules, {'uuids': uuids})
  289. guest = Guest()
  290. for uuid in uuids.split(','):
  291. guest.uuid = uuid
  292. guest.get_by('uuid')
  293. for uuid in uuids.split(','):
  294. message = {'action': 'resume', 'uuid': uuid}
  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_delete(uuids):
  303. args_rules = [
  304. Rules.UUIDS.value
  305. ]
  306. # TODO: 加入是否删除使用的数据磁盘开关,如果为True,则顺便删除使用的磁盘。否则解除该磁盘被使用的状态。
  307. try:
  308. ji.Check.previewing(args_rules, {'uuids': uuids})
  309. guest = Guest()
  310. # 检测所指定的 UUDIs 实例都存在
  311. for uuid in uuids.split(','):
  312. guest.uuid = uuid
  313. guest.get_by('uuid')
  314. # 执行删除操作
  315. for uuid in uuids.split(','):
  316. message = {'action': 'delete_guest', 'uuid': uuid}
  317. Guest.emit_instruction(message=json.dumps(message))
  318. ret = dict()
  319. ret['state'] = ji.Common.exchange_state(20000)
  320. return ret
  321. except ji.PreviewingError, e:
  322. return json.loads(e.message)
  323. @Utils.dumps2response
  324. def r_attach_disk(uuid, disk_uuid):
  325. args_rules = [
  326. Rules.UUID.value,
  327. Rules.DISK_UUID.value
  328. ]
  329. try:
  330. ji.Check.previewing(args_rules, {'uuid': uuid, 'disk_uuid': disk_uuid})
  331. guest = Guest()
  332. guest.uuid = uuid
  333. guest.get_by('uuid')
  334. disk = Disk()
  335. disk.uuid = disk_uuid
  336. disk.get_by('uuid')
  337. ret = dict()
  338. ret['state'] = ji.Common.exchange_state(20000)
  339. # 判断欲挂载的磁盘是否空闲
  340. if disk.guest_uuid.__len__() > 0 or disk.state != DiskState.idle.value:
  341. ret['state'] = ji.Common.exchange_state(41258)
  342. return ret
  343. # 判断 Guest 是否处于可用状态
  344. if guest.status in (status.GuestState.no_state.value, status.GuestState.dirty.value):
  345. ret['state'] = ji.Common.exchange_state(41259)
  346. return ret
  347. # 通过检测未被使用的序列,来确定当前磁盘在目标 Guest 身上的序列
  348. disk.guest_uuid = guest.uuid
  349. disks, count = disk.get_by_filter(filter_str='guest_uuid:in:' + guest.uuid)
  350. already_used_sequence = list()
  351. for _disk in disks:
  352. already_used_sequence.append(_disk['sequence'])
  353. for sequence in range(0, dev_table.__len__()):
  354. if sequence not in already_used_sequence:
  355. disk.sequence = sequence
  356. break
  357. disk.state = DiskState.mounting.value
  358. config = Config()
  359. config.id = 1
  360. config.get()
  361. xml = """
  362. <disk type='network' device='disk'>
  363. <driver name='qemu' type='qcow2' cache='none'/>
  364. <source protocol='gluster' name='{0}/Images/{1}.{2}'>
  365. <host name='127.0.0.1' port='24007'/>
  366. </source>
  367. <target dev='{3}' bus='virtio'/>
  368. </disk>
  369. """.format(config.glusterfs_volume, disk.uuid, disk.format,
  370. dev_table[disk.sequence])
  371. message = {'action': 'attach_disk', 'uuid': uuid, 'xml': xml,
  372. 'passback_parameters': {'disk_uuid': disk.uuid, 'sequence': disk.sequence}}
  373. Guest.emit_instruction(message=json.dumps(message))
  374. disk.update()
  375. return ret
  376. except ji.PreviewingError, e:
  377. return json.loads(e.message)
  378. @Utils.dumps2response
  379. def r_detach_disk(disk_uuid):
  380. args_rules = [
  381. Rules.DISK_UUID.value
  382. ]
  383. try:
  384. ji.Check.previewing(args_rules, {'disk_uuid': disk_uuid})
  385. disk = Disk()
  386. disk.uuid = disk_uuid
  387. disk.get_by('uuid')
  388. ret = dict()
  389. ret['state'] = ji.Common.exchange_state(20000)
  390. if disk.state != DiskState.mounted.value or disk.sequence == 0:
  391. # 表示未被任何实例使用,已被分离
  392. # 序列为 0 的表示实例系统盘,系统盘不可以被分离
  393. # TODO: 系统盘单独范围其它状态
  394. return ret
  395. guest = Guest()
  396. guest.uuid = disk.guest_uuid
  397. guest.get_by('uuid')
  398. # 判断 Guest 是否处于可用状态
  399. if guest.status in (status.GuestState.no_state.value, status.GuestState.dirty.value):
  400. ret['state'] = ji.Common.exchange_state(41259)
  401. return ret
  402. config = Config()
  403. config.id = 1
  404. config.get()
  405. xml = """
  406. <disk type='network' device='disk'>
  407. <driver name='qemu' type='qcow2' cache='none'/>
  408. <source protocol='gluster' name='{0}/Images/{1}.{2}'>
  409. <host name='127.0.0.1' port='24007'/>
  410. </source>
  411. <target dev='{3}' bus='virtio'/>
  412. </disk>
  413. """.format(config.glusterfs_volume, disk.uuid, disk.format,
  414. dev_table[disk.sequence])
  415. message = {'action': 'detach_disk', 'uuid': disk.guest_uuid, 'xml': xml,
  416. 'passback_parameters': {'disk_uuid': disk.uuid}}
  417. Guest.emit_instruction(message=json.dumps(message))
  418. disk.state = DiskState.unloading.value
  419. disk.update()
  420. return ret
  421. except ji.PreviewingError, e:
  422. return json.loads(e.message)
  423. @Utils.dumps2response
  424. def r_migrate(uuids, destination_host):
  425. args_rules = [
  426. Rules.UUIDS.value,
  427. Rules.DESTINATION_HOST.value
  428. ]
  429. try:
  430. ji.Check.previewing(args_rules, {'uuids': uuids, 'destination_host': destination_host})
  431. guest = Guest()
  432. for uuid in uuids.split(','):
  433. guest.uuid = uuid
  434. guest.get_by('uuid')
  435. for uuid in uuids.split(','):
  436. message = {'action': 'migrate', 'uuid': uuid, 'duri': 'qemu+ssh://' + destination_host + '/system'}
  437. Guest.emit_instruction(message=json.dumps(message))
  438. ret = dict()
  439. ret['state'] = ji.Common.exchange_state(20000)
  440. return ret
  441. except ji.PreviewingError, e:
  442. return json.loads(e.message)
  443. @Utils.dumps2response
  444. def r_get(uuids):
  445. return guest_base.get(ids=uuids, ids_rule=Rules.UUIDS.value, by_field='uuid')
  446. @Utils.dumps2response
  447. def r_get_by_filter():
  448. return guest_base.get_by_filter()
  449. @Utils.dumps2response
  450. def r_content_search():
  451. return guest_base.content_search()
  452. @Utils.dumps2response
  453. def r_update(uuid):
  454. args_rules = [
  455. Rules.UUID.value
  456. ]
  457. if 'remark' in request.json:
  458. args_rules.append(
  459. Rules.REMARK.value,
  460. )
  461. if args_rules.__len__() < 2:
  462. ret = dict()
  463. ret['state'] = ji.Common.exchange_state(20000)
  464. return ret
  465. request.json['uuid'] = uuid
  466. try:
  467. ji.Check.previewing(args_rules, request.json)
  468. guest = Guest()
  469. guest.uuid = uuid
  470. guest.get_by('uuid')
  471. guest.remark = request.json.get('remark', guest.label)
  472. guest.update()
  473. guest.get()
  474. ret = dict()
  475. ret['state'] = ji.Common.exchange_state(20000)
  476. ret['data'] = guest.__dict__
  477. return ret
  478. except ji.PreviewingError, e:
  479. return json.loads(e.message)
  480. @Utils.dumps2response
  481. def r_add_boot_jobs(uuids, boot_jobs_id):
  482. args_rules = [
  483. Rules.UUIDS.value,
  484. Rules.BOOT_JOBS_ID.value
  485. ]
  486. try:
  487. ji.Check.previewing(args_rules, {'uuids': uuids, 'boot_jobs_id': boot_jobs_id})
  488. guest = Guest()
  489. for uuid in uuids.split(','):
  490. guest.uuid = uuid
  491. guest.get_by('uuid')
  492. for uuid in uuids.split(','):
  493. guest.uuid = uuid
  494. guest.add_boot_jobs(boot_jobs_id=boot_jobs_id.split(','))
  495. ret = dict()
  496. ret['state'] = ji.Common.exchange_state(20000)
  497. if uuids.split(',').__len__() > 1:
  498. ret['data'] = dict()
  499. for uuid in uuids.split(','):
  500. guest.uuid = uuid
  501. boot_jobs = dict()
  502. boot_jobs['ttl'], boot_jobs['boot_jobs'] = guest.get_boot_jobs()
  503. ret['data'][uuid] = boot_jobs
  504. else:
  505. guest.uuid = uuids
  506. ret['data'] = dict()
  507. ret['data']['ttl'], ret['data']['boot_jobs'] = guest.get_boot_jobs()
  508. return ret
  509. except ji.PreviewingError, e:
  510. return json.loads(e.message)
  511. @Utils.dumps2response
  512. def r_get_boot_jobs(uuids):
  513. args_rules = [
  514. Rules.UUIDS.value
  515. ]
  516. try:
  517. ji.Check.previewing(args_rules, {'uuids': uuids})
  518. guest = Guest()
  519. for uuid in uuids.split(','):
  520. guest.uuid = uuid
  521. guest.get_by('uuid')
  522. ret = dict()
  523. ret['state'] = ji.Common.exchange_state(20000)
  524. if uuids.split(',').__len__() > 1:
  525. ret['data'] = dict()
  526. for uuid in uuids.split(','):
  527. guest.uuid = uuid
  528. boot_jobs = dict()
  529. boot_jobs['ttl'], boot_jobs['boot_jobs'] = guest.get_boot_jobs()
  530. ret['data'][uuid] = boot_jobs
  531. else:
  532. guest.uuid = uuids
  533. ret['data'] = dict()
  534. ret['data']['ttl'], ret['data']['boot_jobs'] = guest.get_boot_jobs()
  535. return ret
  536. except ji.PreviewingError, e:
  537. return json.loads(e.message)
  538. @Utils.dumps2response
  539. def r_delete_boot_jobs(uuids, boot_jobs_id):
  540. args_rules = [
  541. Rules.UUIDS.value,
  542. Rules.BOOT_JOBS_ID.value
  543. ]
  544. try:
  545. ji.Check.previewing(args_rules, {'uuids': uuids, 'boot_jobs_id': boot_jobs_id})
  546. guest = Guest()
  547. # 检测所指定的 UUDIs 实例都存在
  548. for uuid in uuids.split(','):
  549. guest.uuid = uuid
  550. guest.get_by('uuid')
  551. for uuid in uuids.split(','):
  552. guest.uuid = uuid
  553. guest.delete_boot_jobs(boot_jobs_id=boot_jobs_id.split(','))
  554. ret = dict()
  555. ret['state'] = ji.Common.exchange_state(20000)
  556. return ret
  557. except ji.PreviewingError, e:
  558. return json.loads(e.message)
  559. @Utils.dumps2response
  560. def r_get_uuids_of_all_had_boot_job():
  561. guest = Guest()
  562. try:
  563. ret = dict()
  564. ret['state'] = ji.Common.exchange_state(20000)
  565. ret['data'] = guest.get_uuids_of_all_had_boot_job()
  566. return ret
  567. except ji.PreviewingError, e:
  568. return json.loads(e.message)
  569. @Utils.dumps2response
  570. def r_reset_password(uuids, password):
  571. args_rules = [
  572. Rules.UUIDS.value,
  573. Rules.PASSWORD.value
  574. ]
  575. try:
  576. ji.Check.previewing(args_rules, {'uuids': uuids, 'password': password})
  577. guest = Guest()
  578. # 检测所指定的 UUDIs 实例都存在
  579. for uuid in uuids.split(','):
  580. guest.uuid = uuid
  581. guest.get_by('uuid')
  582. # 重置密码的 boot job id 固定为 1
  583. for uuid in uuids.split(','):
  584. guest.uuid = uuid
  585. guest.get_by('uuid')
  586. guest.password = password
  587. guest.update()
  588. guest.add_boot_jobs(boot_jobs_id=['1'])
  589. ret = dict()
  590. ret['state'] = ji.Common.exchange_state(20000)
  591. return ret
  592. except ji.PreviewingError, e:
  593. return json.loads(e.message)