disk.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from flask import Blueprint, request
  4. import json
  5. from uuid import uuid4
  6. import jimit as ji
  7. from models import Guest, DiskState
  8. from models.initialize import dev_table
  9. from models import Config
  10. from models import Disk
  11. from models import Rules
  12. from models import Utils
  13. from models.status import StorageMode
  14. from base import Base
  15. __author__ = 'James Iter'
  16. __date__ = '2017/4/24'
  17. __contact__ = 'james.iter.cn@gmail.com'
  18. __copyright__ = '(c) 2017 by James Iter.'
  19. blueprint = Blueprint(
  20. 'api_disk',
  21. __name__,
  22. url_prefix='/api/disk'
  23. )
  24. blueprints = Blueprint(
  25. 'api_disks',
  26. __name__,
  27. url_prefix='/api/disks'
  28. )
  29. disk_base = Base(the_class=Disk, the_blueprint=blueprint, the_blueprints=blueprints)
  30. @Utils.dumps2response
  31. def r_create():
  32. args_rules = [
  33. Rules.DISK_SIZE.value,
  34. Rules.REMARK.value,
  35. Rules.DISK_ON_HOST.value,
  36. Rules.QUANTITY.value
  37. ]
  38. config = Config()
  39. config.id = 1
  40. config.get()
  41. if config.storage_mode in [StorageMode.shared_mount.value, StorageMode.ceph.value,
  42. StorageMode.glusterfs.value]:
  43. request.json['on_host'] = 'shared_storage'
  44. try:
  45. ji.Check.previewing(args_rules, request.json)
  46. ret = dict()
  47. ret['state'] = ji.Common.exchange_state(20000)
  48. size = request.json['size']
  49. quantity = request.json['quantity']
  50. on_host = request.json['on_host']
  51. if size < 1:
  52. ret['state'] = ji.Common.exchange_state(41255)
  53. return ret
  54. while quantity:
  55. quantity -= 1
  56. disk = Disk()
  57. disk.guest_uuid = ''
  58. disk.size = size
  59. disk.uuid = uuid4().__str__()
  60. disk.remark = request.json.get('remark', '')
  61. disk.on_host = on_host
  62. disk.sequence = -1
  63. disk.format = 'qcow2'
  64. disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
  65. message = {
  66. '_object': 'disk',
  67. 'action': 'create',
  68. 'uuid': disk.uuid,
  69. 'storage_mode': config.storage_mode,
  70. 'dfs_volume': config.dfs_volume,
  71. 'hostname': disk.on_host,
  72. 'image_path': disk.path,
  73. 'size': disk.size
  74. }
  75. if disk.on_host == 'shared_storage':
  76. available_hosts = Guest.get_available_hosts()
  77. if available_hosts.__len__() == 0:
  78. ret['state'] = ji.Common.exchange_state(50351)
  79. return ret
  80. # 在可用计算节点中平均分配任务
  81. chosen_host = available_hosts[quantity % available_hosts.__len__()]
  82. message['hostname'] = chosen_host['hostname']
  83. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  84. disk.create()
  85. return ret
  86. except ji.PreviewingError, e:
  87. return json.loads(e.message)
  88. @Utils.dumps2response
  89. def r_resize(uuid, size):
  90. args_rules = [
  91. Rules.UUID.value,
  92. Rules.DISK_SIZE_STR.value
  93. ]
  94. try:
  95. ji.Check.previewing(args_rules, {'uuid': uuid, 'size': size})
  96. disk = Disk()
  97. disk.uuid = uuid
  98. disk.get_by('uuid')
  99. ret = dict()
  100. ret['state'] = ji.Common.exchange_state(20000)
  101. if disk.size >= size:
  102. ret['state'] = ji.Common.exchange_state(41257)
  103. return ret
  104. config = Config()
  105. config.id = 1
  106. config.get()
  107. message = {
  108. '_object': 'disk',
  109. 'action': 'resize',
  110. 'uuid': disk.uuid,
  111. 'guest_uuid': disk.guest_uuid,
  112. 'storage_mode': config.storage_mode,
  113. 'size': int(size),
  114. 'dfs_volume': config.dfs_volume,
  115. 'hostname': disk.on_host,
  116. 'image_path': disk.path,
  117. 'passback_parameters': {'size': size}
  118. }
  119. if disk.on_host == 'shared_storage':
  120. message['hostname'] = Guest.get_lightest_host()['hostname']
  121. if disk.guest_uuid.__len__() == 36:
  122. message['device_node'] = dev_table[disk.sequence]
  123. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  124. return ret
  125. except ji.PreviewingError, e:
  126. return json.loads(e.message)
  127. @Utils.dumps2response
  128. def r_delete(uuids):
  129. args_rules = [
  130. Rules.UUIDS.value
  131. ]
  132. try:
  133. ji.Check.previewing(args_rules, {'uuids': uuids})
  134. ret = dict()
  135. ret['state'] = ji.Common.exchange_state(20000)
  136. disk = Disk()
  137. # 检测所指定的 UUDIs 磁盘都存在
  138. for uuid in uuids.split(','):
  139. disk.uuid = uuid
  140. disk.get_by('uuid')
  141. if disk.state != DiskState.idle.value:
  142. ret['state'] = ji.Common.exchange_state(41256)
  143. return ret
  144. config = Config()
  145. config.id = 1
  146. config.get()
  147. # 执行删除操作
  148. for uuid in uuids.split(','):
  149. disk.uuid = uuid
  150. disk.get_by('uuid')
  151. message = {
  152. '_object': 'disk',
  153. 'action': 'delete',
  154. 'uuid': disk.uuid,
  155. 'storage_mode': config.storage_mode,
  156. 'dfs_volume': config.dfs_volume,
  157. 'hostname': disk.on_host,
  158. 'image_path': disk.path
  159. }
  160. if disk.on_host == 'shared_storage':
  161. message['hostname'] = Guest.get_lightest_host()['hostname']
  162. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  163. return ret
  164. except ji.PreviewingError, e:
  165. return json.loads(e.message)
  166. @Utils.dumps2response
  167. def r_get(uuids):
  168. return disk_base.get(ids=uuids, ids_rule=Rules.UUIDS.value, by_field='uuid')
  169. @Utils.dumps2response
  170. def r_get_by_filter():
  171. return disk_base.get_by_filter()
  172. @Utils.dumps2response
  173. def r_content_search():
  174. return disk_base.content_search()
  175. @Utils.dumps2response
  176. def r_update(uuid):
  177. args_rules = [
  178. Rules.UUID.value
  179. ]
  180. if 'remark' in request.json:
  181. args_rules.append(
  182. Rules.REMARK.value
  183. )
  184. if args_rules.__len__() < 2:
  185. ret = dict()
  186. ret['state'] = ji.Common.exchange_state(20000)
  187. return ret
  188. request.json['uuid'] = uuid
  189. try:
  190. ji.Check.previewing(args_rules, request.json)
  191. disk = Disk()
  192. disk.uuid = uuid
  193. disk.get_by('uuid')
  194. disk.remark = request.json.get('remark', disk.remark)
  195. disk.update()
  196. disk.get()
  197. ret = dict()
  198. ret['state'] = ji.Common.exchange_state(20000)
  199. ret['data'] = disk.__dict__
  200. return ret
  201. except ji.PreviewingError, e:
  202. return json.loads(e.message)
  203. @Utils.dumps2response
  204. def r_distribute_count():
  205. from models import Disk
  206. rows, count = Disk.get_all()
  207. ret = dict()
  208. ret['state'] = ji.Common.exchange_state(20000)
  209. ret['data'] = {
  210. 'kind': {'system': 0, 'data_mounted': 0, 'data_idle': 0},
  211. 'total_size': 0,
  212. 'disks': rows.__len__()
  213. }
  214. for disk in rows:
  215. if disk['sequence'] == 0:
  216. ret['data']['kind']['system'] += 1
  217. elif disk['sequence'] < 0:
  218. ret['data']['kind']['data_idle'] += 1
  219. else:
  220. ret['data']['kind']['data_mounted'] += 1
  221. ret['data']['total_size'] += disk['size']
  222. return ret