snapshot.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from flask import Blueprint
  4. from flask import request
  5. import json
  6. import jimit as ji
  7. import os
  8. from api.base import Base
  9. from models import Guest, Config, Disk
  10. from models import Snapshot, SnapshotDiskMapping
  11. from models import OSTemplateImage
  12. from models import Utils
  13. from models import Rules
  14. from models import OSTemplateImageKind
  15. __author__ = 'James Iter'
  16. __date__ = '2018/4/10'
  17. __contact__ = 'james.iter.cn@gmail.com'
  18. __copyright__ = '(c) 2018 by James Iter.'
  19. blueprint = Blueprint(
  20. 'api_snapshot',
  21. __name__,
  22. url_prefix='/api/snapshot'
  23. )
  24. blueprints = Blueprint(
  25. 'api_snapshots',
  26. __name__,
  27. url_prefix='/api/snapshots'
  28. )
  29. snapshot_base = Base(the_class=Snapshot, the_blueprint=blueprint, the_blueprints=blueprints)
  30. @Utils.dumps2response
  31. def r_create():
  32. args_rules = [
  33. Rules.GUEST_UUID.value
  34. ]
  35. if 'label' in request.json:
  36. args_rules.append(
  37. Rules.LABEL.value,
  38. )
  39. try:
  40. ret = dict()
  41. ret['state'] = ji.Common.exchange_state(20000)
  42. ji.Check.previewing(args_rules, request.json)
  43. snapshot = Snapshot()
  44. guest = Guest()
  45. guest.uuid = request.json.get('guest_uuid')
  46. guest.get_by('uuid')
  47. snapshot.label = request.json.get('label', '')
  48. snapshot.status = guest.status
  49. snapshot.guest_uuid = guest.uuid
  50. snapshot.snapshot_id = '_'.join(['tmp', ji.Common.generate_random_code(length=8)])
  51. snapshot.parent_id = '-'
  52. snapshot.progress = 0
  53. snapshot.create()
  54. snapshot.get_by('snapshot_id')
  55. message = {
  56. '_object': 'snapshot',
  57. 'action': 'create',
  58. 'uuid': guest.uuid,
  59. 'node_id': guest.node_id,
  60. 'passback_parameters': {'id': snapshot.id}
  61. }
  62. Utils.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  63. ret['data'] = snapshot.__dict__
  64. return ret
  65. except ji.PreviewingError, e:
  66. return json.loads(e.message)
  67. @Utils.dumps2response
  68. def r_update(snapshot_id):
  69. snapshot = Snapshot()
  70. args_rules = [
  71. Rules.SNAPSHOT_ID.value
  72. ]
  73. if 'label' in request.json:
  74. args_rules.append(
  75. Rules.LABEL.value,
  76. )
  77. if args_rules.__len__() < 2:
  78. ret = dict()
  79. ret['state'] = ji.Common.exchange_state(20000)
  80. return ret
  81. request.json['snapshot_id'] = snapshot_id
  82. try:
  83. ji.Check.previewing(args_rules, request.json)
  84. snapshot.snapshot_id = request.json.get('snapshot_id')
  85. snapshot.get_by('snapshot_id')
  86. snapshot.label = request.json.get('label', snapshot.label)
  87. snapshot.update()
  88. snapshot.get()
  89. ret = dict()
  90. ret['state'] = ji.Common.exchange_state(20000)
  91. ret['data'] = snapshot.__dict__
  92. return ret
  93. except ji.PreviewingError, e:
  94. return json.loads(e.message)
  95. @Utils.dumps2response
  96. def r_get(snapshots_id):
  97. return snapshot_base.get(ids=snapshots_id, ids_rule=Rules.SNAPSHOTS_ID.value, by_field='snapshot_id')
  98. @Utils.dumps2response
  99. def r_get_by_filter():
  100. return snapshot_base.get_by_filter()
  101. @Utils.dumps2response
  102. def r_content_search():
  103. return snapshot_base.content_search()
  104. @Utils.dumps2response
  105. def r_delete(snapshots_id):
  106. args_rules = [
  107. Rules.SNAPSHOTS_ID.value
  108. ]
  109. try:
  110. ji.Check.previewing(args_rules, {'snapshots_id': snapshots_id})
  111. snapshot = Snapshot()
  112. guest = Guest()
  113. # 检测所指定的 快照 都存在
  114. for snapshot_id in snapshots_id.split(','):
  115. snapshot.snapshot_id = snapshot_id
  116. snapshot.get_by('snapshot_id')
  117. guest.uuid = snapshot.guest_uuid
  118. guest.get_by('uuid')
  119. # 执行删除操作
  120. for snapshot_id in snapshots_id.split(','):
  121. snapshot.snapshot_id = snapshot_id
  122. snapshot.get_by('snapshot_id')
  123. guest.uuid = snapshot.guest_uuid
  124. guest.get_by('uuid')
  125. message = {
  126. '_object': 'snapshot',
  127. 'action': 'delete',
  128. 'uuid': snapshot.guest_uuid,
  129. 'snapshot_id': snapshot.snapshot_id,
  130. 'node_id': guest.node_id,
  131. 'passback_parameters': {'id': snapshot.id}
  132. }
  133. Utils.emit_instruction(message=json.dumps(message))
  134. # 删除创建失败的 快照
  135. if snapshot.progress == 255:
  136. SnapshotDiskMapping.delete_by_filter(filter_str=':'.join(['snapshot_id', 'eq', snapshot.snapshot_id]))
  137. snapshot.delete()
  138. else:
  139. snapshot.progress = 254
  140. snapshot.update()
  141. ret = dict()
  142. ret['state'] = ji.Common.exchange_state(20000)
  143. return ret
  144. except ji.PreviewingError, e:
  145. return json.loads(e.message)
  146. @Utils.dumps2response
  147. def r_revert(snapshot_id):
  148. args_rules = [
  149. Rules.SNAPSHOT_ID.value
  150. ]
  151. try:
  152. ret = dict()
  153. ret['state'] = ji.Common.exchange_state(20000)
  154. ji.Check.previewing(args_rules, {'snapshot_id': snapshot_id})
  155. snapshot = Snapshot()
  156. guest = Guest()
  157. snapshot.snapshot_id = snapshot_id
  158. snapshot.get_by('snapshot_id')
  159. snapshot.progress = 253
  160. snapshot.update()
  161. snapshot.get()
  162. guest.uuid = snapshot.guest_uuid
  163. guest.get_by('uuid')
  164. message = {
  165. '_object': 'snapshot',
  166. 'action': 'revert',
  167. 'uuid': guest.uuid,
  168. 'snapshot_id': snapshot.snapshot_id,
  169. 'node_id': guest.node_id,
  170. 'passback_parameters': {'id': snapshot.id}
  171. }
  172. Utils.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  173. ret['data'] = snapshot.__dict__
  174. return ret
  175. except ji.PreviewingError, e:
  176. return json.loads(e.message)
  177. @Utils.dumps2response
  178. def r_get_disks(snapshot_id):
  179. args_rules = [
  180. Rules.SNAPSHOT_ID.value
  181. ]
  182. try:
  183. ret = dict()
  184. ret['state'] = ji.Common.exchange_state(20000)
  185. ret['data'] = list()
  186. ji.Check.previewing(args_rules, {'snapshot_id': snapshot_id})
  187. rows, _ = SnapshotDiskMapping.get_by_filter(filter_str=':'.join(['snapshot_id', 'eq', snapshot_id]))
  188. for row in rows:
  189. ret['data'].append(row['disk_uuid'])
  190. return ret
  191. except ji.PreviewingError, e:
  192. return json.loads(e.message)
  193. @Utils.dumps2response
  194. def r_get_snapshots_by_disks_uuid(disks_uuid):
  195. args_rules = [
  196. Rules.UUIDS.value
  197. ]
  198. try:
  199. ret = dict()
  200. ret['state'] = ji.Common.exchange_state(20000)
  201. ret['data'] = list()
  202. ji.Check.previewing(args_rules, {'uuids': disks_uuid})
  203. rows, _ = SnapshotDiskMapping.get_by_filter(filter_str=':'.join(['disk_uuid', 'in', disks_uuid]))
  204. ret['data'] = rows
  205. return ret
  206. except ji.PreviewingError, e:
  207. return json.loads(e.message)
  208. @Utils.dumps2response
  209. def r_convert_to_os_template_image(snapshot_id, disk_uuid):
  210. args_rules = [
  211. Rules.SNAPSHOT_ID.value,
  212. Rules.DISK_UUID.value,
  213. Rules.LABEL.value
  214. ]
  215. try:
  216. ret = dict()
  217. ret['state'] = ji.Common.exchange_state(20000)
  218. ji.Check.previewing(args_rules, {'snapshot_id': snapshot_id, 'disk_uuid': disk_uuid,
  219. 'label': request.json.get('label')})
  220. rows, _ = SnapshotDiskMapping.get_by_filter(filter_str=':'.join(['snapshot_id', 'eq', snapshot_id]))
  221. disks_uuid = list()
  222. for row in rows:
  223. disks_uuid.append(row['disk_uuid'])
  224. if disk_uuid not in disks_uuid:
  225. ret['state'] = ji.Common.exchange_state(40401)
  226. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 未在快照: ',
  227. snapshot_id, u' 中找到磁盘:', disk_uuid])
  228. return ret
  229. config = Config()
  230. config.id = 1
  231. config.get()
  232. snapshot = Snapshot()
  233. os_template_image = OSTemplateImage()
  234. guest = Guest()
  235. disk = Disk()
  236. snapshot.snapshot_id = snapshot_id
  237. snapshot.get_by('snapshot_id')
  238. snapshot.progress = 252
  239. guest.uuid = snapshot.guest_uuid
  240. guest.get_by('uuid')
  241. disk.uuid = disk_uuid
  242. disk.get_by('uuid')
  243. os_template_image.id = guest.os_template_image_id
  244. os_template_image.get()
  245. image_name = '_'.join([snapshot.snapshot_id, disk.uuid]) + '.' + disk.format
  246. os_template_image.id = 0
  247. os_template_image.label = request.json.get('label')
  248. os_template_image.path = '/'.join([os.path.dirname(os_template_image.path), image_name])
  249. os_template_image.kind = OSTemplateImageKind.custom.value
  250. os_template_image.progress = 0
  251. os_template_image.create_time = ji.Common.tus()
  252. if os_template_image.exist_by('path'):
  253. ret['state'] = ji.Common.exchange_state(40901)
  254. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', os_template_image.path])
  255. return ret
  256. os_template_image.create()
  257. os_template_image.get_by('path')
  258. message = {
  259. '_object': 'snapshot',
  260. 'action': 'convert',
  261. 'uuid': disk.guest_uuid,
  262. 'snapshot_id': snapshot.snapshot_id,
  263. 'storage_mode': config.storage_mode,
  264. 'dfs_volume': config.dfs_volume,
  265. 'node_id': disk.node_id,
  266. 'snapshot_path': disk.path,
  267. 'template_path': os_template_image.path,
  268. 'os_template_image_id': os_template_image.id,
  269. 'passback_parameters': {'id': snapshot.snapshot_id}
  270. }
  271. Utils.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  272. snapshot.update()
  273. return ret
  274. except ji.PreviewingError, e:
  275. return json.loads(e.message)