disk.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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.iops = config.iops_base + config.iops_pre_unit * disk.size
  65. if disk.iops > config.iops_cap:
  66. disk.iops = config.iops_cap
  67. disk.iops_max = config.iops_max
  68. disk.iops_max_length = config.iops_max_length
  69. disk.iops_rd = 0
  70. disk.iops_wr = 0
  71. disk.bps = config.bps_base + config.bps_pre_unit * disk.size
  72. if disk.bps > config.bps_cap:
  73. disk.bps = config.bps_cap
  74. disk.bps_max = config.bps_max
  75. disk.bps_max_length = config.bps_max_length
  76. disk.bps_rd = 0
  77. disk.bps_wr = 0
  78. disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
  79. message = {
  80. '_object': 'disk',
  81. 'action': 'create',
  82. 'uuid': disk.uuid,
  83. 'storage_mode': config.storage_mode,
  84. 'dfs_volume': config.dfs_volume,
  85. 'hostname': disk.on_host,
  86. 'image_path': disk.path,
  87. 'size': disk.size
  88. }
  89. if disk.on_host == 'shared_storage':
  90. available_hosts = Guest.get_available_hosts()
  91. if available_hosts.__len__() == 0:
  92. ret['state'] = ji.Common.exchange_state(50351)
  93. return ret
  94. # 在可用计算节点中平均分配任务
  95. chosen_host = available_hosts[quantity % available_hosts.__len__()]
  96. message['hostname'] = chosen_host['hostname']
  97. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  98. disk.create()
  99. return ret
  100. except ji.PreviewingError, e:
  101. return json.loads(e.message)
  102. @Utils.dumps2response
  103. def r_resize(uuid, size):
  104. args_rules = [
  105. Rules.UUID.value,
  106. Rules.DISK_SIZE_STR.value
  107. ]
  108. try:
  109. ji.Check.previewing(args_rules, {'uuid': uuid, 'size': size})
  110. disk = Disk()
  111. disk.uuid = uuid
  112. disk.get_by('uuid')
  113. ret = dict()
  114. ret['state'] = ji.Common.exchange_state(20000)
  115. if disk.size >= size:
  116. ret['state'] = ji.Common.exchange_state(41257)
  117. return ret
  118. config = Config()
  119. config.id = 1
  120. config.get()
  121. message = {
  122. '_object': 'disk',
  123. 'action': 'resize',
  124. 'uuid': disk.uuid,
  125. 'guest_uuid': disk.guest_uuid,
  126. 'storage_mode': config.storage_mode,
  127. 'size': int(size),
  128. 'dfs_volume': config.dfs_volume,
  129. 'hostname': disk.on_host,
  130. 'image_path': disk.path,
  131. 'passback_parameters': {'size': size}
  132. }
  133. if disk.on_host == 'shared_storage':
  134. message['hostname'] = Guest.get_lightest_host()['hostname']
  135. if disk.guest_uuid.__len__() == 36:
  136. message['device_node'] = dev_table[disk.sequence]
  137. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  138. return ret
  139. except ji.PreviewingError, e:
  140. return json.loads(e.message)
  141. @Utils.dumps2response
  142. def r_delete(uuids):
  143. args_rules = [
  144. Rules.UUIDS.value
  145. ]
  146. try:
  147. ji.Check.previewing(args_rules, {'uuids': uuids})
  148. ret = dict()
  149. ret['state'] = ji.Common.exchange_state(20000)
  150. disk = Disk()
  151. # 检测所指定的 UUDIs 磁盘都存在
  152. for uuid in uuids.split(','):
  153. disk.uuid = uuid
  154. disk.get_by('uuid')
  155. if disk.state != DiskState.idle.value:
  156. ret['state'] = ji.Common.exchange_state(41256)
  157. return ret
  158. config = Config()
  159. config.id = 1
  160. config.get()
  161. # 执行删除操作
  162. for uuid in uuids.split(','):
  163. disk.uuid = uuid
  164. disk.get_by('uuid')
  165. message = {
  166. '_object': 'disk',
  167. 'action': 'delete',
  168. 'uuid': disk.uuid,
  169. 'storage_mode': config.storage_mode,
  170. 'dfs_volume': config.dfs_volume,
  171. 'hostname': disk.on_host,
  172. 'image_path': disk.path
  173. }
  174. if disk.on_host == 'shared_storage':
  175. message['hostname'] = Guest.get_lightest_host()['hostname']
  176. Guest.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  177. return ret
  178. except ji.PreviewingError, e:
  179. return json.loads(e.message)
  180. @Utils.dumps2response
  181. def r_get(uuids):
  182. return disk_base.get(ids=uuids, ids_rule=Rules.UUIDS.value, by_field='uuid')
  183. @Utils.dumps2response
  184. def r_get_by_filter():
  185. return disk_base.get_by_filter()
  186. @Utils.dumps2response
  187. def r_content_search():
  188. return disk_base.content_search()
  189. @Utils.dumps2response
  190. def r_update(uuid):
  191. args_rules = [
  192. Rules.UUID.value
  193. ]
  194. if 'remark' in request.json:
  195. args_rules.append(
  196. Rules.REMARK.value
  197. )
  198. if args_rules.__len__() < 2:
  199. ret = dict()
  200. ret['state'] = ji.Common.exchange_state(20000)
  201. return ret
  202. request.json['uuid'] = uuid
  203. try:
  204. ji.Check.previewing(args_rules, request.json)
  205. disk = Disk()
  206. disk.uuid = uuid
  207. disk.get_by('uuid')
  208. disk.remark = request.json.get('remark', disk.remark)
  209. disk.update()
  210. disk.get()
  211. ret = dict()
  212. ret['state'] = ji.Common.exchange_state(20000)
  213. ret['data'] = disk.__dict__
  214. return ret
  215. except ji.PreviewingError, e:
  216. return json.loads(e.message)
  217. @Utils.dumps2response
  218. def r_distribute_count():
  219. from models import Disk
  220. rows, count = Disk.get_all()
  221. ret = dict()
  222. ret['state'] = ji.Common.exchange_state(20000)
  223. ret['data'] = {
  224. 'kind': {'system': 0, 'data_mounted': 0, 'data_idle': 0},
  225. 'total_size': 0,
  226. 'disks': rows.__len__()
  227. }
  228. for disk in rows:
  229. if disk['sequence'] == 0:
  230. ret['data']['kind']['system'] += 1
  231. elif disk['sequence'] < 0:
  232. ret['data']['kind']['data_idle'] += 1
  233. else:
  234. ret['data']['kind']['data_mounted'] += 1
  235. ret['data']['total_size'] += disk['size']
  236. return ret