guest.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  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 models import DiskState
  10. from models import OSInitWrite
  11. from models.initialize import app, dev_table
  12. from models import Database as db
  13. from models import Config
  14. from models import GuestDisk
  15. from models import Rules
  16. from models import Utils
  17. from models import Guest
  18. from models import OSTemplate
  19. from models import GuestXML
  20. from models import status
  21. __author__ = 'James Iter'
  22. __date__ = '2017/3/22'
  23. __contact__ = 'james.iter.cn@gmail.com'
  24. __copyright__ = '(c) 2017 by James Iter.'
  25. blueprint = Blueprint(
  26. 'guest',
  27. __name__,
  28. url_prefix='/api/guest'
  29. )
  30. blueprints = Blueprint(
  31. 'guests',
  32. __name__,
  33. url_prefix='/api/guests'
  34. )
  35. @Utils.dumps2response
  36. def r_create():
  37. args_rules = [
  38. Rules.CPU.value,
  39. Rules.MEMORY.value,
  40. Rules.OS_TEMPLATE_ID.value,
  41. Rules.QUANTITY.value,
  42. Rules.NAME.value,
  43. Rules.PASSWORD.value,
  44. Rules.LEASE_TERM.value
  45. ]
  46. try:
  47. ret = dict()
  48. ret['state'] = ji.Common.exchange_state(20000)
  49. ji.Check.previewing(args_rules, request.json)
  50. config = Config()
  51. config.id = 1
  52. config.get()
  53. os_template = OSTemplate()
  54. os_template.id = request.json.get('os_template_id')
  55. if not os_template.exist():
  56. ret['state'] = ji.Common.exchange_state(40450)
  57. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', os_template.id.__str__()])
  58. return ret
  59. os_template.get()
  60. os_init_writes, os_init_writes_count = OSInitWrite.get_by_filter(
  61. filter_str='os_init_id:in:' + os_template.os_init_id.__str__())
  62. if db.r.scard(app.config['ip_available_set']) < 1:
  63. ret['state'] = ji.Common.exchange_state(50350)
  64. return ret
  65. quantity = request.json.get('quantity')
  66. while quantity:
  67. quantity -= 1
  68. guest = Guest()
  69. guest.uuid = uuid4().__str__()
  70. guest.cpu = request.json.get('cpu')
  71. # 虚拟机内存单位,模板生成方法中已置其为GiB
  72. guest.memory = request.json.get('memory')
  73. guest.os_template_id = request.json.get('os_template_id')
  74. guest.name = request.json.get('name')
  75. if quantity > 0:
  76. '-'.join([guest.name, quantity.__str__()])
  77. guest.password = request.json.get('password')
  78. if guest.password is None or guest.password.__len__() < 1:
  79. guest.password = ji.Common.generate_random_code(length=16)
  80. while guest.name.__len__() < 1 or guest.exist_by('name'):
  81. guest.name = ji.Common.generate_random_code(length=8)
  82. guest.ip = db.r.spop(app.config['ip_available_set'])
  83. db.r.sadd(app.config['ip_used_set'], guest.ip)
  84. guest.network = config.vm_network
  85. guest.manage_network = config.vm_manage_network
  86. guest.vnc_port = db.r.spop(app.config['vnc_port_available_set'])
  87. db.r.sadd(app.config['vnc_port_used_set'], guest.vnc_port)
  88. guest.vnc_password = ji.Common.generate_random_code(length=16)
  89. guest_disk = {'uuid': uuid4().__str__(), 'size': -1, 'format': 'qcow2', 'sequence': 0}
  90. guest_xml = GuestXML(guest=guest, disk=guest_disk, config=config)
  91. guest.xml = guest_xml.get_domain()
  92. guest.create()
  93. # 替换占位符为有效内容
  94. _os_init_writes = copy.deepcopy(os_init_writes)
  95. for k, v in enumerate(_os_init_writes):
  96. _os_init_writes[k]['content'] = v['content'].replace('{IP}', guest.ip).\
  97. replace('{HOSTNAME}', guest.name).\
  98. replace('{NETMASK}', config.netmask).\
  99. replace('{GATEWAY}', config.gateway).\
  100. replace('{DNS1}', config.dns1).\
  101. replace('{DNS2}', config.dns2)
  102. create_vm_msg = {
  103. 'action': 'create_vm',
  104. 'uuid': guest.uuid,
  105. 'name': guest.name,
  106. 'glusterfs_volume': config.glusterfs_volume,
  107. 'template_path': 'template_pool/' + os_template.name,
  108. 'guest_disk': guest_disk,
  109. 'writes': _os_init_writes,
  110. 'password': guest.password,
  111. 'xml': guest_xml.get_domain()
  112. }
  113. db.r.rpush(app.config['downstream_queue'], json.dumps(create_vm_msg, ensure_ascii=False))
  114. return ret
  115. except ji.PreviewingError, e:
  116. return json.loads(e.message)
  117. @Utils.dumps2response
  118. def r_reboot(uuids):
  119. args_rules = [
  120. Rules.UUIDS.value
  121. ]
  122. try:
  123. ji.Check.previewing(args_rules, {'uuids': uuids})
  124. guest = Guest()
  125. for uuid in uuids.split(','):
  126. guest.uuid = uuid
  127. guest.get_by('uuid')
  128. for uuid in uuids.split(','):
  129. message = {'action': 'reboot', 'uuid': uuid}
  130. Guest.emit_instruction(message=json.dumps(message))
  131. ret = dict()
  132. ret['state'] = ji.Common.exchange_state(20000)
  133. return ret
  134. except ji.PreviewingError, e:
  135. return json.loads(e.message)
  136. @Utils.dumps2response
  137. def r_force_reboot(uuids):
  138. args_rules = [
  139. Rules.UUIDS.value
  140. ]
  141. try:
  142. ji.Check.previewing(args_rules, {'uuids': uuids})
  143. guest = Guest()
  144. for uuid in uuids.split(','):
  145. guest.uuid = uuid
  146. guest.get_by('uuid')
  147. for uuid in uuids.split(','):
  148. message = {'action': 'force_reboot', 'uuid': uuid}
  149. Guest.emit_instruction(message=json.dumps(message))
  150. ret = dict()
  151. ret['state'] = ji.Common.exchange_state(20000)
  152. return ret
  153. except ji.PreviewingError, e:
  154. return json.loads(e.message)
  155. @Utils.dumps2response
  156. def r_shutdown(uuids):
  157. args_rules = [
  158. Rules.UUIDS.value
  159. ]
  160. try:
  161. ji.Check.previewing(args_rules, {'uuids': uuids})
  162. guest = Guest()
  163. for uuid in uuids.split(','):
  164. guest.uuid = uuid
  165. guest.get_by('uuid')
  166. for uuid in uuids.split(','):
  167. message = {'action': 'shutdown', 'uuid': uuid}
  168. Guest.emit_instruction(message=json.dumps(message))
  169. ret = dict()
  170. ret['state'] = ji.Common.exchange_state(20000)
  171. return ret
  172. except ji.PreviewingError, e:
  173. return json.loads(e.message)
  174. @Utils.dumps2response
  175. def r_force_shutdown(uuids):
  176. args_rules = [
  177. Rules.UUIDS.value
  178. ]
  179. try:
  180. ji.Check.previewing(args_rules, {'uuids': uuids})
  181. guest = Guest()
  182. for uuid in uuids.split(','):
  183. guest.uuid = uuid
  184. guest.get_by('uuid')
  185. for uuid in uuids.split(','):
  186. message = {'action': 'force_shutdown', 'uuid': uuid}
  187. Guest.emit_instruction(message=json.dumps(message))
  188. ret = dict()
  189. ret['state'] = ji.Common.exchange_state(20000)
  190. return ret
  191. except ji.PreviewingError, e:
  192. return json.loads(e.message)
  193. @Utils.dumps2response
  194. def r_boot(uuids):
  195. # TODO: 做好关系依赖判断,比如boot不可以对suspend的实例操作。
  196. args_rules = [
  197. Rules.UUIDS.value
  198. ]
  199. try:
  200. ji.Check.previewing(args_rules, {'uuids': uuids})
  201. guest = Guest()
  202. for uuid in uuids.split(','):
  203. guest.uuid = uuid
  204. guest.get_by('uuid')
  205. for uuid in uuids.split(','):
  206. message = {'action': 'boot', 'uuid': uuid}
  207. Guest.emit_instruction(message=json.dumps(message))
  208. ret = dict()
  209. ret['state'] = ji.Common.exchange_state(20000)
  210. return ret
  211. except ji.PreviewingError, e:
  212. return json.loads(e.message)
  213. @Utils.dumps2response
  214. def r_suspend(uuids):
  215. args_rules = [
  216. Rules.UUIDS.value
  217. ]
  218. try:
  219. ji.Check.previewing(args_rules, {'uuids': uuids})
  220. guest = Guest()
  221. for uuid in uuids.split(','):
  222. guest.uuid = uuid
  223. guest.get_by('uuid')
  224. for uuid in uuids.split(','):
  225. message = {'action': 'suspend', 'uuid': uuid}
  226. Guest.emit_instruction(message=json.dumps(message))
  227. ret = dict()
  228. ret['state'] = ji.Common.exchange_state(20000)
  229. return ret
  230. except ji.PreviewingError, e:
  231. return json.loads(e.message)
  232. @Utils.dumps2response
  233. def r_resume(uuids):
  234. args_rules = [
  235. Rules.UUIDS.value
  236. ]
  237. try:
  238. ji.Check.previewing(args_rules, {'uuids': uuids})
  239. guest = Guest()
  240. for uuid in uuids.split(','):
  241. guest.uuid = uuid
  242. guest.get_by('uuid')
  243. for uuid in uuids.split(','):
  244. message = {'action': 'resume', 'uuid': uuid}
  245. Guest.emit_instruction(message=json.dumps(message))
  246. ret = dict()
  247. ret['state'] = ji.Common.exchange_state(20000)
  248. return ret
  249. except ji.PreviewingError, e:
  250. return json.loads(e.message)
  251. @Utils.dumps2response
  252. def r_delete(uuids):
  253. args_rules = [
  254. Rules.UUIDS.value
  255. ]
  256. # TODO: 加入是否删除使用的数据磁盘开关,如果为True,则顺便删除使用的磁盘。否则解除该磁盘被使用的状态。
  257. try:
  258. ji.Check.previewing(args_rules, {'uuids': uuids})
  259. guest = Guest()
  260. # 检测所指定的 UUDIs 实例都存在
  261. for uuid in uuids.split(','):
  262. guest.uuid = uuid
  263. guest.get_by('uuid')
  264. # 执行删除操作
  265. for uuid in uuids.split(','):
  266. message = {'action': 'delete', 'uuid': uuid}
  267. Guest.emit_instruction(message=json.dumps(message))
  268. ret = dict()
  269. ret['state'] = ji.Common.exchange_state(20000)
  270. return ret
  271. except ji.PreviewingError, e:
  272. return json.loads(e.message)
  273. @Utils.dumps2response
  274. def r_attach_disk(uuid, disk_uuid):
  275. args_rules = [
  276. Rules.UUID.value,
  277. Rules.DISK_UUID.value
  278. ]
  279. try:
  280. ji.Check.previewing(args_rules, {'uuid': uuid, 'disk_uuid': disk_uuid})
  281. guest = Guest()
  282. guest.uuid = uuid
  283. guest.get_by('uuid')
  284. guest_disk = GuestDisk()
  285. guest_disk.uuid = disk_uuid
  286. guest_disk.get_by('uuid')
  287. ret = dict()
  288. ret['state'] = ji.Common.exchange_state(20000)
  289. # 判断欲挂载的磁盘是否空闲
  290. if guest_disk.guest_uuid.__len__() > 0:
  291. ret['state'] = ji.Common.exchange_state(41258)
  292. return ret
  293. # 判断 Guest 是否处于可用状态
  294. if guest.status in (status.GuestState.no_state.value, status.GuestState.dirty.value):
  295. ret['state'] = ji.Common.exchange_state(41259)
  296. return ret
  297. # 取出该 guest 已挂载的磁盘,来做出决定,确定该磁盘的序列
  298. guest_disk.guest_uuid = guest.uuid
  299. disks, count = guest_disk.get_by_filter(filter_str='guest_uuid:in:' + guest.uuid)
  300. guest_disk.sequence = count + 1
  301. config = Config()
  302. config.id = 1
  303. config.get()
  304. xml = """
  305. <disk type='network' device='disk'>
  306. <driver name='qemu' type='qcow2' cache='none'/>
  307. <source protocol='gluster' name='{0}/DiskPool/{1}.{2}'>
  308. <host name='127.0.0.1' port='24007'/>
  309. </source>
  310. <target dev='{3}' bus='virtio'/>
  311. </disk>
  312. """.format(config.glusterfs_volume, guest_disk.uuid, guest_disk.format,
  313. dev_table[guest_disk.sequence])
  314. message = {'action': 'attach_disk', 'uuid': uuid, 'xml': xml,
  315. 'passback_parameters': {'disk_uuid': guest_disk.uuid, 'sequence': guest_disk.sequence}}
  316. Guest.emit_instruction(message=json.dumps(message))
  317. return ret
  318. except ji.PreviewingError, e:
  319. return json.loads(e.message)
  320. @Utils.dumps2response
  321. def r_detach_disk(disk_uuid):
  322. args_rules = [
  323. Rules.DISK_UUID.value
  324. ]
  325. try:
  326. ji.Check.previewing(args_rules, {'disk_uuid': disk_uuid})
  327. guest_disk = GuestDisk()
  328. guest_disk.uuid = disk_uuid
  329. guest_disk.get_by('uuid')
  330. ret = dict()
  331. ret['state'] = ji.Common.exchange_state(20000)
  332. if guest_disk.state != DiskState.mounted.value or guest_disk.sequence == 0:
  333. # 表示未被任何实例使用,已被分离
  334. # 序列为 0 的表示实例系统盘,系统盘不可以被分离
  335. # TODO: 系统盘单独范围其它状态
  336. return ret
  337. guest = Guest()
  338. guest.uuid = guest_disk.guest_uuid
  339. guest.get_by('uuid')
  340. # 判断 Guest 是否处于可用状态
  341. if guest.status in (status.GuestState.no_state.value, status.GuestState.dirty.value):
  342. ret['state'] = ji.Common.exchange_state(41259)
  343. return ret
  344. config = Config()
  345. config.id = 1
  346. config.get()
  347. xml = """
  348. <disk type='network' device='disk'>
  349. <driver name='qemu' type='qcow2' cache='none'/>
  350. <source protocol='gluster' name='{0}/DiskPool/{1}.{2}'>
  351. <host name='127.0.0.1' port='24007'/>
  352. </source>
  353. <target dev='{3}' bus='virtio'/>
  354. </disk>
  355. """.format(config.glusterfs_volume, guest_disk.uuid, guest_disk.format,
  356. dev_table[guest_disk.sequence])
  357. message = {'action': 'detach_disk', 'uuid': guest_disk.guest_uuid, 'xml': xml,
  358. 'passback_parameters': {'disk_uuid': guest_disk.uuid}}
  359. Guest.emit_instruction(message=json.dumps(message))
  360. return ret
  361. except ji.PreviewingError, e:
  362. return json.loads(e.message)
  363. @Utils.dumps2response
  364. def r_migrate(uuids, destination_host):
  365. args_rules = [
  366. Rules.UUIDS.value,
  367. Rules.DESTINATION_HOST.value
  368. ]
  369. try:
  370. ji.Check.previewing(args_rules, {'uuids': uuids, 'destination_host': destination_host})
  371. guest = Guest()
  372. for uuid in uuids.split(','):
  373. guest.uuid = uuid
  374. guest.get_by('uuid')
  375. for uuid in uuids.split(','):
  376. message = {'action': 'migrate', 'uuid': uuid, 'duri': 'qemu+ssh://' + destination_host + '/system'}
  377. Guest.emit_instruction(message=json.dumps(message))
  378. ret = dict()
  379. ret['state'] = ji.Common.exchange_state(20000)
  380. return ret
  381. except ji.PreviewingError, e:
  382. return json.loads(e.message)
  383. @Utils.dumps2response
  384. def r_get(uuid):
  385. guest = Guest()
  386. args_rules = [
  387. Rules.UUID.value
  388. ]
  389. guest.uuid = uuid
  390. try:
  391. ji.Check.previewing(args_rules, guest.__dict__)
  392. guest.get_by('uuid')
  393. ret = dict()
  394. ret['state'] = ji.Common.exchange_state(20000)
  395. ret['data'] = guest.__dict__
  396. return ret
  397. except ji.PreviewingError, e:
  398. return json.loads(e.message)
  399. @Utils.dumps2response
  400. def r_get_by_filter():
  401. page = str(request.args.get('page', 1))
  402. page_size = str(request.args.get('page_size', 50))
  403. args_rules = [
  404. Rules.PAGE.value,
  405. Rules.PAGE_SIZE.value
  406. ]
  407. try:
  408. ji.Check.previewing(args_rules, {'page': page, 'page_size': page_size})
  409. except ji.PreviewingError, e:
  410. return json.loads(e.message)
  411. page = int(page)
  412. page_size = int(page_size)
  413. # 把page和page_size换算成offset和limit
  414. offset = (page - 1) * page_size
  415. # offset, limit将覆盖page及page_size的影响
  416. offset = str(request.args.get('offset', offset))
  417. limit = str(request.args.get('limit', page_size))
  418. order_by = request.args.get('order_by', 'id')
  419. order = request.args.get('order', 'asc')
  420. filter_str = request.args.get('filter', '')
  421. args_rules = [
  422. Rules.OFFSET.value,
  423. Rules.LIMIT.value,
  424. Rules.ORDER_BY.value,
  425. Rules.ORDER.value
  426. ]
  427. try:
  428. ji.Check.previewing(args_rules, {'offset': offset, 'limit': limit, 'order_by': order_by, 'order': order})
  429. offset = int(offset)
  430. limit = int(limit)
  431. ret = dict()
  432. ret['state'] = ji.Common.exchange_state(20000)
  433. ret['data'] = list()
  434. ret['paging'] = {'total': 0, 'offset': offset, 'limit': limit, 'page': page, 'page_size': page_size,
  435. 'next': '', 'prev': '', 'first': '', 'last': ''}
  436. ret['data'], ret['paging']['total'] = Guest.get_by_filter(offset=offset, limit=limit, order_by=order_by,
  437. order=order, filter_str=filter_str)
  438. host_url = request.host_url.rstrip('/')
  439. other_str = '&filter=' + filter_str + '&order=' + order + '&order_by=' + order_by
  440. last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
  441. if page <= 1:
  442. ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
  443. other_str
  444. else:
  445. ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
  446. page_size.__str__() + other_str
  447. if page >= last_pagination:
  448. ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + \
  449. '&page_size=' + page_size.__str__() + other_str
  450. else:
  451. ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
  452. page_size.__str__() + other_str
  453. ret['paging']['first'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + \
  454. page_size.__str__() + other_str
  455. ret['paging']['last'] = \
  456. host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
  457. page_size.__str__() + other_str
  458. return ret
  459. except ji.PreviewingError, e:
  460. return json.loads(e.message)
  461. @Utils.dumps2response
  462. def r_content_search():
  463. page = str(request.args.get('page', 1))
  464. page_size = str(request.args.get('page_size', 50))
  465. args_rules = [
  466. Rules.PAGE.value,
  467. Rules.PAGE_SIZE.value
  468. ]
  469. try:
  470. ji.Check.previewing(args_rules, {'page': page, 'page_size': page_size})
  471. except ji.PreviewingError, e:
  472. return json.loads(e.message)
  473. page = int(page)
  474. page_size = int(page_size)
  475. # 把page和page_size换算成offset和limit
  476. offset = (page - 1) * page_size
  477. # offset, limit将覆盖page及page_size的影响
  478. offset = str(request.args.get('offset', offset))
  479. limit = str(request.args.get('limit', page_size))
  480. order_by = request.args.get('order_by', 'id')
  481. order = request.args.get('order', 'asc')
  482. keyword = request.args.get('keyword', '')
  483. args_rules = [
  484. Rules.OFFSET.value,
  485. Rules.LIMIT.value,
  486. Rules.ORDER_BY.value,
  487. Rules.ORDER.value,
  488. Rules.KEYWORD.value
  489. ]
  490. try:
  491. ji.Check.previewing(args_rules, {'offset': offset, 'limit': limit, 'order_by': order_by, 'order': order,
  492. 'keyword': keyword})
  493. offset = int(offset)
  494. limit = int(limit)
  495. ret = dict()
  496. ret['state'] = ji.Common.exchange_state(20000)
  497. ret['data'] = list()
  498. ret['paging'] = {'total': 0, 'offset': offset, 'limit': limit, 'page': page, 'page_size': page_size}
  499. ret['data'], ret['paging']['total'] = Guest.content_search(offset=offset, limit=limit, order_by=order_by,
  500. order=order, keyword=keyword)
  501. host_url = request.host_url.rstrip('/')
  502. other_str = '&keyword=' + keyword + '&order=' + order + '&order_by=' + order_by
  503. last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
  504. if page <= 1:
  505. ret['paging']['prev'] = host_url + blueprints.url_prefix + '/_search?page=1&page_size=' + \
  506. page_size.__str__() + other_str
  507. else:
  508. ret['paging']['prev'] = host_url + blueprints.url_prefix + '/_search?page=' + str(page-1) + \
  509. '&page_size=' + page_size.__str__() + other_str
  510. if page >= last_pagination:
  511. ret['paging']['next'] = host_url + blueprints.url_prefix + '/_search?page=' + last_pagination.__str__() + \
  512. '&page_size=' + page_size.__str__() + other_str
  513. else:
  514. ret['paging']['next'] = host_url + blueprints.url_prefix + '/_search?page=' + str(page+1) + \
  515. '&page_size=' + page_size.__str__() + other_str
  516. ret['paging']['first'] = host_url + blueprints.url_prefix + '/_search?page=1&page_size=' + \
  517. page_size.__str__() + other_str
  518. ret['paging']['last'] = \
  519. host_url + blueprints.url_prefix + '/_search?page=' + last_pagination.__str__() + '&page_size=' + \
  520. page_size.__str__() + other_str
  521. return ret
  522. except ji.PreviewingError, e:
  523. return json.loads(e.message)
  524. @Utils.dumps2response
  525. def r_update(uuid):
  526. args_rules = [
  527. Rules.UUID.value
  528. ]
  529. if 'remark' in request.json:
  530. args_rules.append(
  531. Rules.REMARK.value,
  532. )
  533. if args_rules.__len__() < 2:
  534. ret = dict()
  535. ret['state'] = ji.Common.exchange_state(20000)
  536. return ret
  537. request.json['uuid'] = uuid
  538. try:
  539. ji.Check.previewing(args_rules, request.json)
  540. guest = Guest()
  541. guest.uuid = uuid
  542. guest.get_by('uuid')
  543. guest.remark = request.json.get('remark', guest.name)
  544. guest.update()
  545. guest.get()
  546. ret = dict()
  547. ret['state'] = ji.Common.exchange_state(20000)
  548. ret['data'] = guest.__dict__
  549. return ret
  550. except ji.PreviewingError, e:
  551. return json.loads(e.message)