guest.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import jimit as ji
  4. import json
  5. from filter import FilterFieldType
  6. from orm import ORM
  7. from status import GuestState, DiskState
  8. from database import Database as db
  9. from initialize import app
  10. __author__ = 'James Iter'
  11. __date__ = '2017/3/22'
  12. __contact__ = 'james.iter.cn@gmail.com'
  13. __copyright__ = '(c) 2017 by James Iter.'
  14. class Guest(ORM):
  15. _table_name = 'guest'
  16. _primary_key = 'id'
  17. def __init__(self):
  18. super(Guest, self).__init__()
  19. self.id = 0
  20. self.uuid = None
  21. self.label = None
  22. self.password = None
  23. self.remark = ''
  24. self.os_template_id = None
  25. self.create_time = ji.Common.tus()
  26. self.status = GuestState.no_state.value
  27. self.progress = 0
  28. self.on_host = ''
  29. self.cpu = None
  30. self.memory = None
  31. self.ip = None
  32. self.network = None
  33. self.manage_network = None
  34. self.vnc_port = None
  35. self.vnc_password = None
  36. self.xml = None
  37. @staticmethod
  38. def get_filter_keywords():
  39. return {
  40. 'id': FilterFieldType.INT.value,
  41. 'uuid': FilterFieldType.STR.value,
  42. 'label': FilterFieldType.STR.value,
  43. 'remark': FilterFieldType.STR.value,
  44. 'on_host': FilterFieldType.STR.value,
  45. 'ip': FilterFieldType.STR.value
  46. }
  47. @staticmethod
  48. def get_allow_update_keywords():
  49. return ['remark', 'cpu', 'memory', 'network', 'manage_network', 'vnc_password']
  50. @staticmethod
  51. def get_allow_content_search_keywords():
  52. return ['label', 'remark', 'on_host', 'ip']
  53. @staticmethod
  54. def emit_instruction(message):
  55. db.r.publish(app.config['instruction_channel'], message=message)
  56. def get_boot_jobs_key(self):
  57. return ':'.join([app.config['guest_boot_jobs'], self.uuid])
  58. def add_boot_jobs(self, boot_jobs_id):
  59. if not isinstance(boot_jobs_id, list):
  60. raise ValueError('The boot_jobs_id must be a list.')
  61. key = self.get_boot_jobs_key()
  62. db.r.sadd(key, *boot_jobs_id)
  63. db.r.expire(key, app.config['guest_boot_jobs_wait_time'])
  64. def get_boot_jobs(self):
  65. return db.r.ttl(self.get_boot_jobs_key()), list(db.r.smembers(self.get_boot_jobs_key()))
  66. def delete_boot_jobs(self, boot_jobs_id):
  67. if not isinstance(boot_jobs_id, list):
  68. raise ValueError('The boot_jobs_id must be a list.')
  69. key = self.get_boot_jobs_key()
  70. db.r.srem(key, *boot_jobs_id)
  71. # 如果集合下还有值,则更新启动作业有效时间
  72. if db.r.exists(key):
  73. db.r.expire(key, app.config['guest_boot_jobs_wait_time'])
  74. @staticmethod
  75. def get_uuids_of_all_had_boot_job():
  76. boot_job_keys = db.r.keys(pattern=app.config['guest_boot_jobs'] + '*')
  77. uuids = list()
  78. for boot_job_key in boot_job_keys:
  79. uuids.append(boot_job_key.split(':')[-1])
  80. return uuids
  81. @staticmethod
  82. def get_lightest_host():
  83. # 负载最小的宿主机
  84. lightest_host = None
  85. for k, v in db.r.hgetall(app.config['hosts_info']).items():
  86. v = json.loads(v)
  87. if lightest_host is None:
  88. lightest_host = v
  89. if float(lightest_host['system_load'][0]) / lightest_host['cpu'] > \
  90. float(v['system_load'][0]) / v['cpu']:
  91. lightest_host = v
  92. return lightest_host
  93. @staticmethod
  94. def get_available_hosts(randomable=None):
  95. """
  96. :param randomable: {None, True, False}
  97. None for all;
  98. True for host can be allocation guest by random;
  99. False on the contrary.
  100. :return:
  101. """
  102. from models import Host
  103. hosts = list()
  104. for k, v in db.r.hgetall(app.config['hosts_info']).items():
  105. v = json.loads(v)
  106. v = Host.alive_check(v)
  107. if not v['alive']:
  108. continue
  109. if randomable is not None and v['randomable'] != randomable:
  110. continue
  111. v['system_load_per_cpu'] = float(v['system_load'][0]) / v['cpu']
  112. hosts.append(v)
  113. hosts.sort(key=lambda _k: _k['system_load_per_cpu'])
  114. return hosts
  115. class Disk(ORM):
  116. _table_name = 'disk'
  117. _primary_key = 'id'
  118. def __init__(self):
  119. super(Disk, self).__init__()
  120. self.id = 0
  121. self.uuid = None
  122. self.remark = None
  123. self.path = None
  124. self.size = None
  125. self.sequence = None
  126. self.state = DiskState.pending.value
  127. self.on_host = ''
  128. self.format = 'qcow2'
  129. self.create_time = ji.Common.tus()
  130. self.guest_uuid = None
  131. self.iops = 0
  132. self.iops_rd = 0
  133. self.iops_wr = 0
  134. self.iops_max = 0
  135. self.iops_max_length = 0
  136. self.bps = 0
  137. self.bps_rd = 0
  138. self.bps_wr = 0
  139. self.bps_max = 0
  140. self.bps_max_length = 0
  141. def quota(self, config=None):
  142. from models import Config
  143. assert isinstance(config, Config)
  144. # 系统盘 IOPS 默认不计算增益
  145. if self.sequence != 0:
  146. self.iops = config.iops_base + config.iops_pre_unit * self.size
  147. else:
  148. self.iops = config.iops_base
  149. if self.iops > config.iops_cap:
  150. self.iops = config.iops_cap
  151. self.iops_max = config.iops_max
  152. self.iops_max_length = config.iops_max_length
  153. self.iops_rd = 0
  154. self.iops_wr = 0
  155. # 系统盘 BPS 默认不计算增益
  156. if self.sequence != 0:
  157. self.bps = config.bps_base + config.bps_pre_unit * self.size
  158. else:
  159. self.bps = config.bps_base
  160. if self.bps > config.bps_cap:
  161. self.bps = config.bps_cap
  162. self.bps_max = config.bps_max
  163. self.bps_max_length = config.bps_max_length
  164. self.bps_rd = 0
  165. self.bps_wr = 0
  166. @staticmethod
  167. def get_filter_keywords():
  168. return {
  169. 'id': FilterFieldType.INT.value,
  170. 'uuid': FilterFieldType.STR.value,
  171. 'remark': FilterFieldType.STR.value,
  172. 'size': FilterFieldType.INT.value,
  173. 'state': FilterFieldType.INT.value,
  174. 'sequence': FilterFieldType.INT.value,
  175. 'on_host': FilterFieldType.STR.value,
  176. 'guest_uuid': FilterFieldType.STR.value
  177. }
  178. @staticmethod
  179. def get_allow_update_keywords():
  180. return ['on_host', 'sequence', 'state', 'guest_uuid']
  181. @staticmethod
  182. def get_allow_content_search_keywords():
  183. return ['remark', 'size', 'guest_uuid', 'uuid', 'on_host']
  184. class GuestMigrateInfo(ORM):
  185. _table_name = 'guest_migrate_info'
  186. _primary_key = 'id'
  187. def __init__(self):
  188. super(GuestMigrateInfo, self).__init__()
  189. self.id = 0
  190. self.uuid = None
  191. self.type = None
  192. self.time_elapsed = None
  193. self.time_remaining = None
  194. self.data_total = None
  195. self.data_processed = None
  196. self.data_remaining = None
  197. self.mem_total = None
  198. self.mem_processed = None
  199. self.mem_remaining = None
  200. self.file_total = None
  201. self.file_processed = None
  202. self.file_remaining = None
  203. @staticmethod
  204. def get_filter_keywords():
  205. return {
  206. 'id': FilterFieldType.INT.value,
  207. 'uuid': FilterFieldType.STR.value
  208. }
  209. @staticmethod
  210. def get_allow_update_keywords():
  211. return []
  212. @staticmethod
  213. def get_allow_content_search_keywords():
  214. return []