瀏覽代碼

实现在创建虚拟机时,可以指定计算节点功能。

James Iter 8 年之前
父節點
當前提交
f8a137cf2f
共有 6 個文件被更改,包括 68 次插入4 次删除
  1. 15 1
      api/guest.py
  2. 1 0
      models/event_processor.py
  3. 11 1
      models/guest.py
  4. 1 0
      models/rules.py
  5. 27 1
      templates/guest_create.html
  6. 13 1
      views/guest.py

+ 15 - 1
api/guest.py

@@ -59,6 +59,11 @@ def r_create():
         Rules.LEASE_TERM.value
     ]
 
+    if 'on_host' in request.json:
+        args_rules.append(
+            Rules.GUEST_ON_HOST.value,
+        )
+
     try:
         ret = dict()
         ret['state'] = ji.Common.exchange_state(20000)
@@ -88,12 +93,17 @@ def r_create():
             ret['state'] = ji.Common.exchange_state(50350)
             return ret
 
+        on_host = request.json.get('on_host', None)
         available_hosts = Guest.get_available_hosts()
 
         if available_hosts.__len__() == 0:
             ret['state'] = ji.Common.exchange_state(50351)
             return ret
 
+        if on_host is not None and on_host not in [host['hostname'] for host in available_hosts]:
+            ret['state'] = ji.Common.exchange_state(50351)
+            return ret
+
         quantity = request.json.get('quantity')
 
         while quantity:
@@ -131,6 +141,7 @@ def r_create():
             disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
             disk.guest_uuid = ''
             disk.quota(config=config)
+            # disk.on_host 由 guest 事件处理机更新。涉及迁移时,其所属 on_host 会变更。参见 models/event_processory.py:111 附近。
             disk.create()
 
             guest_xml = GuestXML(guest=guest, disk=disk, config=config, os_type=os_template.os_type)
@@ -138,8 +149,11 @@ def r_create():
 
             # 在可用计算节点中平均分配任务
             chosen_host = available_hosts[quantity % available_hosts.__len__()]
-
             guest.on_host = chosen_host['hostname']
+
+            if on_host is not None:
+                guest.on_host = on_host
+
             guest.create()
 
             # 替换占位符为有效内容

+ 1 - 0
models/event_processor.py

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

+ 11 - 1
models/guest.py

@@ -118,7 +118,14 @@ class Guest(ORM):
         return lightest_host
 
     @staticmethod
-    def get_available_hosts():
+    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
 
@@ -132,6 +139,9 @@ class Guest(ORM):
             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)
 

+ 1 - 0
models/rules.py

@@ -69,6 +69,7 @@ class Rules(Enum):
     LOGIN_NAME = (basestring, 'login_name')
     PASSWORD = (basestring, 'password')
     LEASE_TERM = (int, 'lease_term')
+    GUEST_ON_HOST = (basestring, 'on_host', (1, 128))
     DESTINATION_HOST = (basestring, 'destination_host', (5, 64))
     DISK_UUID = (basestring, 'disk_uuid', (36, 36))
     DISK_SIZE = (int, 'size')

+ 27 - 1
templates/guest_create.html

@@ -116,6 +116,14 @@
             verticaldownclass: 'glyph-icon icon-minus'
         });
     });
+
+    function allocation_by_random_click_handler(me) {
+        if ($(me).prop('checked')) {
+            $('#on_host').parent().parent().css('display', 'none')
+        } else {
+            $('#on_host').parent().parent().css('display', 'unset')
+        }
+    }
 </script>
 <div class="container" style="padding-top: 100px;">
     <div class="panel">
@@ -192,7 +200,7 @@
                         <label class="col-sm-2 control-label"><span class="glyph-icon icon-elusive-inbox-alt"></span>&nbsp;&nbsp;系统模板</label>
                         <div class="col-sm-6">
                             <select id="os_template" name="os_template_id" title="请选择系统模板..." class="selectpicker" data-width="100%">
-                                {% for item in os_template_data %}
+                                {% for item in os_template_ret.data %}
                                     <option value="{{ item.id }}" data-icon="{{ item.icon }}">&nbsp;&nbsp;{{ item.label }}</option>
                                 {% endfor %}
                             </select>
@@ -229,6 +237,24 @@
                             </div>
                         </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>
+                        <div class="col-sm-6">
+                            <div class="row form-group">
+                                <label class="col-sm-2 control-label">随机分配:</label>
+                                <div class="col-sm-6">
+                                    <input onclick="allocation_by_random_click_handler(this);" type="checkbox" name="allocation_by_random" title="随机分配" class="form-control" id="allocation_by_random" checked>
+                                </div>
+                            </div>
+                            <div class="row form-group" style="display: none;">
+                                <select id="on_host" name="on_host" title="请选择计算节点..." class="selectpicker" data-width="100%">
+                                    {% for item in hosts_ret.data %}
+                                        <option value="{{ item.hostname }}" data-icon="{{ item.icon }}">&nbsp;&nbsp;{{ item.hostname }}</option>
+                                    {% endfor %}
+                                </select>
+                            </div>
+                        </div>
+                    </div>
                     <div class="form-group">
                         <label class="col-sm-2 control-label"></label>
                         <div class="col-sm-3 pull-right">

+ 13 - 1
views/guest.py

@@ -123,6 +123,8 @@ def create():
         quantity = request.form.get('quantity')
         password = request.form.get('password')
         remark = request.form.get('remark')
+        allocation_by_random = 'allocation_by_random' in request.form
+        on_host = request.form.get('on_host')
 
         if not isinstance(ability, basestring):
             pass
@@ -144,10 +146,14 @@ def create():
             "lease_term": 100
         }
 
+        if not allocation_by_random:
+            payload['on_host'] = on_host
+
         url = host_url + '/api/guest'
         headers = {'content-type': 'application/json'}
         r = requests.post(url, data=json.dumps(payload), headers=headers, cookies=request.cookies)
         j_r = json.loads(r.content)
+        # TODO: 状态码返回非200时,转到失败页面。
 
         guests_url = host_url + url_for('api_guests.r_get_by_filter')
         guests_ret = requests.get(url=guests_url, cookies=request.cookies)
@@ -163,9 +169,15 @@ def create():
 
     else:
         os_template_url = host_url + url_for('api_os_templates.r_get_by_filter')
+        hosts_url = host_url + url_for('api_hosts.r_get_by_filter', alive=True)
+
         os_template_ret = requests.get(url=os_template_url, cookies=request.cookies)
         os_template_ret = json.loads(os_template_ret.content)
-        return render_template('guest_create.html', os_template_data=os_template_ret['data'])
+
+        hosts_ret = requests.get(url=hosts_url, cookies=request.cookies)
+        hosts_ret = json.loads(hosts_ret.content)
+
+        return render_template('guest_create.html', os_template_ret=os_template_ret, hosts_ret=hosts_ret)
 
 
 def port_is_opened(port):