guest.py 23 KB

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