ssh_key.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from flask import Blueprint
  4. from flask import request
  5. from werkzeug.datastructures import ImmutableMultiDict
  6. import json
  7. import jimit as ji
  8. from api.base import Base
  9. from models import SSHKey, OSTemplateImage, OSTemplateProfile, GuestState
  10. from models import SSHKeyGuestMapping
  11. from models import Guest
  12. from models import Utils
  13. from models import Rules
  14. __author__ = 'James Iter'
  15. __date__ = '2018/2/26'
  16. __contact__ = 'james.iter.cn@gmail.com'
  17. __copyright__ = '(c) 2018 by James Iter.'
  18. blueprint = Blueprint(
  19. 'api_ssh_key',
  20. __name__,
  21. url_prefix='/api/ssh_key'
  22. )
  23. blueprints = Blueprint(
  24. 'api_ssh_keys',
  25. __name__,
  26. url_prefix='/api/ssh_keys'
  27. )
  28. ssh_key_base = Base(the_class=SSHKey, the_blueprint=blueprint, the_blueprints=blueprints)
  29. guest_base = Base(the_class=Guest, the_blueprint=blueprint, the_blueprints=blueprints)
  30. @Utils.dumps2response
  31. def r_create():
  32. args_rules = [
  33. Rules.LABEL.value,
  34. Rules.PUBLIC_KEY.value
  35. ]
  36. try:
  37. ret = dict()
  38. ret['state'] = ji.Common.exchange_state(20000)
  39. ji.Check.previewing(args_rules, request.json)
  40. ssh_key = SSHKey()
  41. ssh_key.label = request.json.get('label')
  42. ssh_key.public_key = request.json.get('public_key')
  43. if ssh_key.exist_by('public_key'):
  44. ret['state'] = ji.Common.exchange_state(40901)
  45. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', ssh_key.public_key])
  46. return ret
  47. ssh_key.create()
  48. return ret
  49. except ji.PreviewingError, e:
  50. return json.loads(e.message)
  51. @Utils.dumps2response
  52. def r_update(_id):
  53. ssh_key = SSHKey()
  54. args_rules = [
  55. Rules.ID.value
  56. ]
  57. if 'label' in request.json:
  58. args_rules.append(
  59. Rules.LABEL.value,
  60. )
  61. if 'public_key' in request.json:
  62. args_rules.append(
  63. Rules.PUBLIC_KEY.value,
  64. )
  65. if args_rules.__len__() < 2:
  66. ret = dict()
  67. ret['state'] = ji.Common.exchange_state(20000)
  68. return ret
  69. request.json['id'] = _id
  70. try:
  71. ji.Check.previewing(args_rules, request.json)
  72. ssh_key.id = request.json.get('id')
  73. ssh_key.get()
  74. ssh_key.label = request.json.get('label', ssh_key.label)
  75. ssh_key.public_key = request.json.get('public_key', ssh_key.public_key)
  76. ssh_key.update()
  77. ssh_key.get()
  78. ret = dict()
  79. ret['state'] = ji.Common.exchange_state(20000)
  80. ret['data'] = ssh_key.__dict__
  81. return ret
  82. except ji.PreviewingError, e:
  83. return json.loads(e.message)
  84. @Utils.dumps2response
  85. def r_get(ids):
  86. return ssh_key_base.get(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
  87. @Utils.dumps2response
  88. def r_get_by_filter():
  89. return ssh_key_base.get_by_filter()
  90. @Utils.dumps2response
  91. def r_content_search():
  92. return ssh_key_base.content_search()
  93. def update_ssh_key(uuid):
  94. guest = Guest()
  95. guest.uuid = uuid
  96. guest.get_by('uuid')
  97. # 不支持更新离线虚拟机的 SSH-KEY
  98. if guest.status != GuestState.running.value:
  99. return
  100. os_template_image = OSTemplateImage()
  101. os_template_profile = OSTemplateProfile()
  102. os_template_image.id = guest.os_template_image_id
  103. os_template_image.get()
  104. os_template_profile.id = os_template_image.os_template_profile_id
  105. os_template_profile.get()
  106. # 不支持更新 Windows 虚拟机的 SSH-KEY
  107. if os_template_profile.os_type == 'windows':
  108. return
  109. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['guest_uuid', 'eq', uuid]))
  110. ssh_keys_id = list()
  111. for row in rows:
  112. ssh_keys_id.append(row['ssh_key_id'].__str__())
  113. ssh_keys = list()
  114. if ssh_keys_id.__len__() > 0:
  115. rows, _ = SSHKey.get_by_filter(filter_str=':'.join(['id', 'in', ','.join(ssh_keys_id)]))
  116. for row in rows:
  117. ssh_keys.append(row['public_key'])
  118. else:
  119. ssh_keys.append('')
  120. message = {
  121. '_object': 'guest',
  122. 'uuid': uuid,
  123. 'node_id': guest.node_id,
  124. 'action': 'update_ssh_key',
  125. 'ssh_keys': ssh_keys,
  126. 'os_type': os_template_profile.os_type,
  127. 'passback_parameters': {'uuid': uuid, 'ssh_keys': ssh_keys, 'os_type': os_template_profile.os_type}
  128. }
  129. Utils.emit_instruction(message=json.dumps(message, ensure_ascii=False))
  130. @Utils.dumps2response
  131. def r_delete(ids):
  132. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'in', ids]))
  133. SSHKeyGuestMapping.delete_by_filter(filter_str=':'.join(['ssh_key_id', 'in', ids]))
  134. for row in rows:
  135. update_ssh_key(uuid=row['guest_uuid'])
  136. return ssh_key_base.delete(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
  137. @Utils.dumps2response
  138. def r_bound(ssh_key_id):
  139. args_rules = [
  140. Rules.SSH_KEY_ID_EXT.value,
  141. ]
  142. try:
  143. ji.Check.previewing(args_rules, {'ssh_key_id': ssh_key_id})
  144. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'eq', ssh_key_id]))
  145. guests_uuid = list()
  146. for row in rows:
  147. guests_uuid.append(row['guest_uuid'])
  148. if guests_uuid.__len__() == 0:
  149. guests_uuid.append('_')
  150. request.__setattr__('args', ImmutableMultiDict([
  151. ('filter', ':'.join(['uuid', 'in', ','.join(guests_uuid)])),
  152. ('page_size', 10000)
  153. ]))
  154. return guest_base.get_by_filter()
  155. except ji.PreviewingError, e:
  156. return json.loads(e.message)
  157. @Utils.dumps2response
  158. def r_unbound(ssh_key_id):
  159. args_rules = [
  160. Rules.SSH_KEY_ID_EXT.value,
  161. ]
  162. try:
  163. ji.Check.previewing(args_rules, {'ssh_key_id': ssh_key_id})
  164. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'eq', ssh_key_id]))
  165. guests_uuid = list()
  166. for row in rows:
  167. guests_uuid.append(row['guest_uuid'])
  168. if guests_uuid.__len__() == 0:
  169. guests_uuid.append('_')
  170. request.__setattr__('args', ImmutableMultiDict([
  171. ('filter', ':'.join(['uuid', 'notin', ','.join(guests_uuid)])),
  172. ('page_size', 10000)
  173. ]))
  174. return guest_base.get_by_filter()
  175. except ji.PreviewingError, e:
  176. return json.loads(e.message)
  177. @Utils.dumps2response
  178. def r_bind(ssh_key_id, uuids):
  179. args_rules = [
  180. Rules.SSH_KEY_ID_EXT.value,
  181. Rules.UUIDS.value
  182. ]
  183. try:
  184. ji.Check.previewing(args_rules, {'ssh_key_id': ssh_key_id, 'uuids': uuids})
  185. ret = dict()
  186. ret['state'] = ji.Common.exchange_state(20000)
  187. ssh_key = SSHKey()
  188. ssh_key.id = ssh_key_id
  189. # 判断 ssh_key id 为 ssh_key_id 的对象是否存在
  190. if not ssh_key.exist():
  191. ret['state'] = ji.Common.exchange_state(40401)
  192. ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ssh_key_id: ', ssh_key_id])
  193. return ret
  194. # 获取已经和该 ssh_key 绑定过的 guest uuid 集合,用于判断是否已经绑定过该 ssh_key,避免重复绑定
  195. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'eq', ssh_key_id]))
  196. guests_uuid = list()
  197. for row in rows:
  198. guests_uuid.append(row['guest_uuid'])
  199. ssh_key_guest_mapping = SSHKeyGuestMapping()
  200. for uuid in uuids.split(','):
  201. # 如果已经绑定过,则忽略
  202. if uuid in guests_uuid:
  203. continue
  204. ssh_key_guest_mapping.ssh_key_id = ssh_key_id
  205. ssh_key_guest_mapping.guest_uuid = uuid
  206. ssh_key_guest_mapping.create()
  207. update_ssh_key(uuid=uuid)
  208. # 返回执行结果
  209. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'eq', ssh_key_id]))
  210. guests_uuid = list()
  211. for row in rows:
  212. guests_uuid.append(row['guest_uuid'])
  213. if guests_uuid.__len__() == 0:
  214. guests_uuid.append('_')
  215. request.__setattr__('args', ImmutableMultiDict([
  216. ('filter', ':'.join(['uuid', 'in', ','.join(guests_uuid)])),
  217. ('page_size', 10000)
  218. ]))
  219. return guest_base.get_by_filter()
  220. except ji.PreviewingError, e:
  221. return json.loads(e.message)
  222. @Utils.dumps2response
  223. def r_unbind(ssh_key_id, uuids):
  224. args_rules = [
  225. Rules.SSH_KEY_ID_EXT.value,
  226. Rules.UUIDS.value
  227. ]
  228. try:
  229. ji.Check.previewing(args_rules, {'ssh_key_id': ssh_key_id, 'uuids': uuids})
  230. ret = dict()
  231. ret['state'] = ji.Common.exchange_state(20000)
  232. # 获取已经和该 ssh_key 绑定过的映射集合,从中获取映射 id,用于解绑操作
  233. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'eq', ssh_key_id]))
  234. guests_uuid = uuids.split(',')
  235. ssh_key_guest_mapping = SSHKeyGuestMapping()
  236. for row in rows:
  237. # 解除已经绑定过的 guest
  238. if row['guest_uuid'] in guests_uuid:
  239. ssh_key_guest_mapping.id = row['id']
  240. ssh_key_guest_mapping.delete()
  241. update_ssh_key(uuid=row['guest_uuid'])
  242. # 返回执行结果
  243. rows, _ = SSHKeyGuestMapping.get_by_filter(filter_str=':'.join(['ssh_key_id', 'eq', ssh_key_id]))
  244. guests_uuid = list()
  245. for row in rows:
  246. guests_uuid.append(row['guest_uuid'])
  247. if guests_uuid.__len__() == 0:
  248. guests_uuid.append('_')
  249. request.__setattr__('args', ImmutableMultiDict([
  250. ('filter', ':'.join(['uuid', 'in', ','.join(guests_uuid)])),
  251. ('page_size', 10000)
  252. ]))
  253. return guest_base.get_by_filter()
  254. except ji.PreviewingError, e:
  255. return json.loads(e.message)