guest.py 22 KB

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