Sfoglia il codice sorgente

实现计算机节点加入是否接受自动分配虚拟机开关

James Iter 8 anni fa
parent
commit
3ab33dba52

+ 8 - 2
api/guest.py

@@ -10,7 +10,7 @@ from uuid import uuid4
 import jimit as ji
 
 from api.base import Base
-from models import DiskState
+from models import DiskState, Host
 from models import OperateRule
 from models.initialize import app, dev_table
 from models import Database as db
@@ -94,7 +94,13 @@ def r_create():
             return ret
 
         on_host = request.json.get('on_host', None)
-        available_hosts = Guest.get_available_hosts()
+
+        # 默认只取可随机分配虚拟机的 hosts
+        available_hosts = Host.get_available_hosts(nonrandom=False)
+
+        # 当指定了 host 时,取全部活着的 hosts
+        if on_host is not None:
+            available_hosts = Host.get_available_hosts(nonrandom=None)
 
         if available_hosts.__len__() == 0:
             ret['state'] = ji.Common.exchange_state(50351)

+ 34 - 19
api/host.py

@@ -30,6 +30,34 @@ blueprints = Blueprint(
 )
 
 
+@Utils.dumps2response
+def r_nonrandom(hosts_name, random):
+
+    args_rules = [
+        Rules.HOSTS_NAME.value
+    ]
+
+    try:
+        ji.Check.previewing(args_rules, {args_rules[0][1]: hosts_name})
+
+        if str(random).lower() in ['false', '0']:
+            random = False
+
+        else:
+            random = True
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+
+        Host.set_allocation_mode(hosts_name=hosts_name.split(','), random=random)
+
+        ret['data'] = Host.get_all()
+        return ret
+
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
 @Utils.dumps2response
 def r_get(nodes_id):
 
@@ -88,18 +116,11 @@ def r_get_by_filter():
             else:
                 alive = True
 
-        for k, v in db.r.hgetall(app.config['hosts_info']).items():
-            v = json.loads(v)
-            v = Host.alive_check(v)
-            v['node_id'] = k
-
-            if alive is not None and alive is not v['alive']:
+        for host in Host.get_all():
+            if alive is not None and alive is not host['alive']:
                 continue
 
-            ret['data'].append(v)
-
-        if ret['data'].__len__() > 1:
-            ret['data'].sort(key=lambda _k: _k['boot_time'])
+            ret['data'].append(host)
 
         return ret
 
@@ -122,15 +143,9 @@ def r_content_search():
         ret['state'] = ji.Common.exchange_state(20000)
         ret['data'] = list()
 
-        for k, v in db.r.hgetall(app.config['hosts_info']).items():
-            v = json.loads(v)
-            if -1 != v['hostname'].find(keyword):
-                v = Host.alive_check(v)
-                v['node_id'] = k
-                ret['data'].append(v)
-
-        if ret['data'].__len__() > 1:
-            ret['data'].sort(key=lambda _k: _k['boot_time'])
+        for host in Host.get_all():
+            if -1 != host['hostname'].find(keyword):
+                ret['data'].append(host)
 
         return ret
 

+ 2 - 1
api_route_table.py

@@ -103,11 +103,12 @@ add_rule_api(log.blueprints, '/<ids>', api_func='log.r_get', methods=['GET'])
 add_rule_api(log.blueprints, '', api_func='log.r_get_by_filter', methods=['GET'])
 add_rule_api(log.blueprints, '/_search', api_func='log.r_content_search', methods=['GET'])
 
-# 宿主机查询
+# 计算节点操作
 add_rule_api(host.blueprints, '/<nodes_id>', api_func='host.r_get', methods=['GET'])
 add_rule_api(host.blueprints, '', api_func='host.r_get_by_filter', methods=['GET'])
 add_rule_api(host.blueprints, '/_search', api_func='host.r_content_search', methods=['GET'])
 add_rule_api(host.blueprints, '/<nodes_id>', api_func='host.r_delete', methods=['DELETE'])
+add_rule_api(host.blueprints, '/<hosts_name>/<random>', api_func='host.r_nonrandom', methods=['PUT'])
 
 # Guest 性能查询
 add_rule_api(performance.blueprint, '/cpu_memory', api_func='performance.r_cpu_memory_get_by_filter', methods=['GET'])

+ 3 - 2
docs/todo.md

@@ -72,7 +72,8 @@
 - [x] 安装脚本、文档加入ntp时间同步环节
 - [ ] 周期轮询试的同步虚拟机状态
 - [ ] 实现类似于VMware的故障转移功能
-- [ ] 实现创建虚拟机时,手动指定计算节点功能
-- [ ] 计算机节点加入是否接受自动分配虚拟机开关
+- [x] 实现创建虚拟机时,手动指定计算节点功能
+- [x] 计算机节点加入是否接受自动分配虚拟机开关
+- [ ] 替换 host 对象中的 node_id 为 hostname,统一主键。并消除 node_id
 
 

+ 1 - 1
models/event_processor.py

@@ -122,7 +122,7 @@ class EventProcessor(object):
             'interfaces': cls.message['message']['interfaces'],
             'disks': cls.message['message']['disks'],
             'boot_time': cls.message['message']['boot_time'],
-            'randomable': True,
+            'nonrandom': False,
             'timestamp': ji.Common.ts()
         }
 

+ 0 - 32
models/guest.py

@@ -117,38 +117,6 @@ class Guest(ORM):
 
         return lightest_host
 
-    @staticmethod
-    def get_available_hosts(randomable=None):
-        """
-        :param randomable: {None, True, False}
-            None for all;
-            True for host can be allocation guest by random;
-            False on the contrary.
-        :return:
-        """
-
-        from models import Host
-
-        hosts = list()
-
-        for k, v in db.r.hgetall(app.config['hosts_info']).items():
-            v = json.loads(v)
-
-            v = Host.alive_check(v)
-
-            if not v['alive']:
-                continue
-
-            if randomable is not None and v['randomable'] != randomable:
-                continue
-
-            v['system_load_per_cpu'] = float(v['system_load'][0]) / v['cpu']
-            hosts.append(v)
-
-        hosts.sort(key=lambda _k: _k['system_load_per_cpu'])
-
-        return hosts
-
 
 class Disk(ORM):
 

+ 65 - 0
models/host.py

@@ -2,8 +2,12 @@
 # -*- coding: utf-8 -*-
 
 
+import json
 from flask import g
 
+from initialize import app
+from models import Database as db
+
 
 __author__ = 'James Iter'
 __date__ = '2017/9/19'
@@ -31,3 +35,64 @@ class Host(object):
 
         return v
 
+    @staticmethod
+    def set_allocation_mode(hosts_name=None, random=True):
+        if not isinstance(hosts_name, list):
+            raise ValueError('The hosts_name must be a list.')
+
+        if random:
+            db.r.sadd(app.config['compute_nodes_of_allocation_by_nonrandom'], *hosts_name)
+
+        else:
+            db.r.srem(app.config['compute_nodes_of_allocation_by_nonrandom'], *hosts_name)
+
+    @classmethod
+    def get_all(cls):
+
+        ret = list()
+        compute_nodes_of_allocation_by_nonrandom = \
+            list(db.r.smembers(app.config['compute_nodes_of_allocation_by_nonrandom']))
+
+        for k, v in db.r.hgetall(app.config['hosts_info']).items():
+            v = json.loads(v)
+            v = cls.alive_check(v)
+            v['node_id'] = k
+
+            if v['hostname'] in compute_nodes_of_allocation_by_nonrandom:
+                v['nonrandom'] = True
+            else:
+                v['nonrandom'] = False
+
+            ret.append(v)
+
+        if ret.__len__() > 1:
+            ret.sort(key=lambda _k: _k['boot_time'])
+
+        return ret
+
+    @classmethod
+    def get_available_hosts(cls, nonrandom=None):
+        """
+        :param nonrandom: {None, True, False}
+            None for all;
+            False for host can be allocation guest by random;
+            True on the contrary.
+        :return:
+        """
+
+        hosts = list()
+
+        for host in cls.get_all():
+
+            if not host['alive']:
+                continue
+
+            if nonrandom is not None and host['nonrandom'] != nonrandom:
+                continue
+
+            host['system_load_per_cpu'] = float(host['system_load'][0]) / host['cpu']
+            hosts.append(host)
+
+        hosts.sort(key=lambda _k: _k['system_load_per_cpu'])
+
+        return hosts

+ 1 - 0
models/initialize.py

@@ -47,6 +47,7 @@ class Init(object):
         'ipc_queue': 'Q:IPC',
         'hosts_info': 'H:HostsInfo',
         'compute_nodes_hostname_key': 'S:ComputeNodesHostname',
+        'compute_nodes_of_allocation_by_nonrandom': 'S:ComputeNodesOfAllocationByNonrandom',
         'guest_boot_jobs': 'S:GuestBootJobs',
         'guest_boot_jobs_wait_time': 600,
         'db_charset': 'utf8',

+ 2 - 0
models/rules.py

@@ -16,6 +16,7 @@ class Rules(Enum):
     REG_NUMBER = 'regex:^\d{1,17}$'
     REG_NUMBERS = 'regex:^(\d{1,17})(,\d{1,17})*$'
     REG_UUIDS = 'regex:^([\w-]{36})(,[\w-]{36})*$'
+    REG_HOSTS_NAME = 'regex:^([\S-]{1,128})(,[\S-]{1,128})*$'
     REG_IP = 'regex:^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))$'
 
     OFFSET = (REG_NUMBER, 'offset')
@@ -28,6 +29,7 @@ class Rules(Enum):
 
     ID = (REG_NUMBER, 'id')
     IDS = (REG_NUMBERS, 'ids')
+    HOSTS_NAME = (REG_HOSTS_NAME, 'hosts_name')
     BOOT_JOBS_ID = (REG_NUMBERS, 'boot_jobs_id')
 
     CONFIG_ID = (int, 'id')

+ 1 - 1
templates/guest_create.html

@@ -238,7 +238,7 @@
                         </div>
                     </div>
                     <div class="form-group">
-                        <label class="col-sm-2 control-label"><span class="glyph-icon icon-elusive-compass-circled"></span>&nbsp;&nbsp;创建模式</label>
+                        <label class="col-sm-2 control-label"><span class="glyph-icon icon-elusive-shuffle"></span>&nbsp;&nbsp;创建模式</label>
                         <div class="col-sm-6">
                             <div class="row form-group">
                                 <label class="col-sm-2 control-label">随机分配:</label>

+ 17 - 0
templates/hosts_show.html

@@ -68,6 +68,22 @@
     function panel_onmouseout(me) {
         $(me).find(".show_detail_link").css('display','none');
     }
+
+    function nonrandom_click_handler(hostname, nonrandom) {
+        $.ajax({
+            url : '/api/hosts/' + hostname + '/' + (! nonrandom),
+            type : 'PUT',
+            error : function() {
+                alter_danger('计算节点随机分配模式指令发送失败!');
+            },
+            success : function() {
+                alter_success('计算节点随机分配模式指令发送成功!');
+                setTimeout(function() {
+                    refresh();
+                }, 1000);
+            }
+        });
+    }
 </script>
     <div class="panel">
         <div class="panel-body">
@@ -92,6 +108,7 @@
                         <div class="host-box content-box {% if not item.alive %}panel-gray{% endif %}">
                             <h2 class="bg-black host-title">{{ item.hostname }}
                                 <i style="float: right;" class="glyph-icon icon-circle font-size-23 {% if item.alive == true %}font-green{% else %}font-red{% endif %}"></i>
+                                <a href="javascript:;" onclick="nonrandom_click_handler('{{ item.hostname }}', {{ item.nonrandom | lower }});" title="{% if item.nonrandom == true %}加入{% else %}取消{% endif %}自动分配" style="float: left; margin-top: 8%;" class="glyph-icon icon-elusive-shuffle font-size-12 {% if item.nonrandom == true %}font-gray{% else %}font-green{% endif %}"></a>
                             </h2>
                             <div class="bg-blue host-specs">
                                 <div class="show_detail_link" style="display: none; position: absolute; z-index: 9999; margin-top: 20px; right: 2%;">