Переглянути джерело

实现兼容单机版创建Guest

James Iter 9 роки тому
батько
коміт
a5ac201e10
10 змінених файлів з 76 додано та 81 видалено
  1. 3 3
      api/disk.py
  2. 20 26
      api/guest.py
  3. 2 0
      main.py
  4. 5 3
      misc/init.sql
  5. 4 3
      models/config.py
  6. 3 0
      models/event_processor.py
  7. 4 2
      models/guest.py
  8. 22 43
      models/guest_xml.py
  9. 3 1
      models/rules.py
  10. 10 0
      models/status.py

+ 3 - 3
api/disk.py

@@ -78,7 +78,7 @@ def r_create():
 
             disk.path = config.storage_path + '/' + disk.uuid + '.' + disk.format
 
-            message = {'action': 'create_disk', 'glusterfs_volume': config.glusterfs_volume,
+            message = {'action': 'create_disk', 'glusterfs_volume': config.dfs_volume,
                        'image_path': disk.path, 'size': disk.size, 'uuid': disk.uuid}
 
             db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
@@ -129,7 +129,7 @@ def r_resize(uuid, size):
             config.id = 1
             config.get()
 
-            message['glusterfs_volume'] = config.glusterfs_volume
+            message['glusterfs_volume'] = config.dfs_volume
             message['image_path'] = disk.path
 
             db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
@@ -174,7 +174,7 @@ def r_delete(uuids):
             disk.get_by('uuid')
 
             message = {'action': 'delete_disk', 'uuid': disk.uuid,
-                       'glusterfs_volume': config.glusterfs_volume, 'image_path': disk.path}
+                       'glusterfs_volume': config.dfs_volume, 'image_path': disk.path}
             db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
 
         return ret

+ 20 - 26
api/guest.py

@@ -163,10 +163,12 @@ def r_create():
 
             create_vm_msg = {
                 'action': 'create',
+                'jimv_edition': config.jimv_edition,
+                'dfs': config.dfs,
+                'dfs_volume': config.dfs_volume,
                 'uuid': guest.uuid,
                 'hostname': lightest_host['hostname'],
                 'name': guest.label,
-                'glusterfs_volume': config.glusterfs_volume,
                 'template_path': os_template.path,
                 'disk': disk.__dict__,
                 'xml': guest_xml.get_domain(),
@@ -419,9 +421,19 @@ def r_delete(uuids):
             guest.uuid = uuid
             guest.get_by('uuid')
 
+        config = Config()
+        config.id = 1
+        config.get()
+
         # 执行删除操作
         for uuid in uuids.split(','):
-            message = {'action': 'delete_guest', 'uuid': uuid}
+            message = {
+                'action': 'delete_guest',
+                'uuid': uuid,
+                'jimv_edition': config.jimv_edition,
+                'dfs': config.dfs,
+                'dfs_volume': config.dfs_volume
+            }
             Guest.emit_instruction(message=json.dumps(message))
 
         ret = dict()
@@ -484,18 +496,9 @@ def r_attach_disk(uuid, disk_uuid):
         config.id = 1
         config.get()
 
-        xml = """
-            <disk type='network' device='disk'>
-                <driver name='qemu' type='qcow2' cache='none'/>
-                <source protocol='gluster' name='{0}/Images/{1}.{2}'>
-                    <host name='127.0.0.1' port='24007'/>
-                </source>
-                <target dev='{3}' bus='virtio'/>
-            </disk>
-        """.format(config.glusterfs_volume, disk.uuid, disk.format,
-                   dev_table[disk.sequence])
-
-        message = {'action': 'attach_disk', 'uuid': uuid, 'xml': xml,
+        guest_xml = GuestXML(guest=guest, disk=disk, config=config)
+
+        message = {'action': 'attach_disk', 'uuid': uuid, 'xml': guest_xml.get_disk(),
                    'passback_parameters': {'disk_uuid': disk.uuid, 'sequence': disk.sequence}}
         Guest.emit_instruction(message=json.dumps(message))
         disk.update()
@@ -542,18 +545,9 @@ def r_detach_disk(disk_uuid):
         config.id = 1
         config.get()
 
-        xml = """
-            <disk type='network' device='disk'>
-                <driver name='qemu' type='qcow2' cache='none'/>
-                <source protocol='gluster' name='{0}/Images/{1}.{2}'>
-                    <host name='127.0.0.1' port='24007'/>
-                </source>
-                <target dev='{3}' bus='virtio'/>
-            </disk>
-        """.format(config.glusterfs_volume, disk.uuid, disk.format,
-                   dev_table[disk.sequence])
-
-        message = {'action': 'detach_disk', 'uuid': disk.guest_uuid, 'xml': xml,
+        guest_xml = GuestXML(guest=guest, disk=disk, config=config)
+
+        message = {'action': 'detach_disk', 'uuid': disk.guest_uuid, 'xml': guest_xml.get_disk(),
                    'passback_parameters': {'disk_uuid': disk.uuid}}
         Guest.emit_instruction(message=json.dumps(message))
 

+ 2 - 0
main.py

@@ -39,6 +39,7 @@ from api.performance import blueprints as performance_blueprints
 from api.host_performance import blueprint as host_performance_blueprint
 from api.host_performance import blueprints as host_performance_blueprints
 
+from views.config import blueprint as view_config_blueprint
 from views.dashboard import blueprint as view_dashboard_blueprint
 from views.guest import blueprint as view_guest_blueprint
 from views.guest import blueprints as view_guest_blueprints
@@ -122,6 +123,7 @@ try:
     app.register_blueprint(host_performance_blueprint)
     app.register_blueprint(host_performance_blueprints)
 
+    app.register_blueprint(view_config_blueprint)
     app.register_blueprint(view_dashboard_blueprint)
     app.register_blueprint(view_guest_blueprint)
     app.register_blueprint(view_guest_blueprints)

+ 5 - 3
misc/init.sql

@@ -60,6 +60,7 @@ CREATE TABLE IF NOT EXISTS disk(
     uuid CHAR(36) NOT NULL,
     path VARCHAR(255) NOT NULL,
     size INT UNSIGNED NOT NULL,
+    on_host VARCHAR(128) NOT NULL DEFAULT '',
     remark VARCHAR(255) NOT NULL DEFAULT '',
     sequence TINYINT NOT NULL,
     format CHAR(16) NOT NULL DEFAULT 'qcow2',
@@ -73,6 +74,7 @@ CREATE TABLE IF NOT EXISTS disk(
 
 ALTER TABLE disk ADD INDEX (size);
 ALTER TABLE disk ADD INDEX (guest_uuid);
+ALTER TABLE disk ADD INDEX (on_host);
 ALTER TABLE disk ADD INDEX (remark);
 
 
@@ -113,7 +115,9 @@ CREATE TABLE IF NOT EXISTS operate_rule(
 
 CREATE TABLE IF NOT EXISTS config(
     id BIGINT UNSIGNED NOT NULL DEFAULT 1,
-    glusterfs_volume VARCHAR(255) NOT NULL,
+    jimv_edition TINYINT UNSIGNED NOT NULL DEFAULT 0,
+    dfs TINYINT UNSIGNED NOT NULL DEFAULT 0,
+    dfs_volume VARCHAR(255) NOT NULL DEFAULT '',
     storage_path VARCHAR(255) NOT NULL,
     vm_network VARCHAR(255) NOT NULL,
     vm_manage_network VARCHAR(255) NOT NULL,
@@ -124,8 +128,6 @@ CREATE TABLE IF NOT EXISTS config(
     gateway CHAR(15) NOT NULL,
     dns1 CHAR(15) NOT NULL DEFAULT '223.5.5.5',
     dns2 CHAR(15) NOT NULL DEFAULT '8.8.8.8',
-    rsa_private text NOT NULL DEFAULT '',
-    rsa_public text NOT NULL DEFAULT '',
     PRIMARY KEY (id))
     ENGINE=InnoDB
     DEFAULT CHARSET=utf8;

+ 4 - 3
models/config.py

@@ -9,6 +9,7 @@ from IPy import IP, intToIp
 from initialize import app
 from models import Database as db
 from models import ORM
+from models import status
 
 
 __author__ = 'James Iter'
@@ -26,7 +27,9 @@ class Config(ORM):
         super(Config, self).__init__()
         # 配置条目的 id 只会是 1
         self.id = 1
-        self.glusterfs_volume = ''
+        self.jimv_edition = status.JimVEdition.standalone.value
+        self.dfs = status.DFS.ceph.value
+        self.dfs_volume = ''
         self.storage_path = ''
         self.vm_network = ''
         self.vm_manage_network = ''
@@ -37,8 +40,6 @@ class Config(ORM):
         self.gateway = ''
         self.dns1 = ''
         self.dns2 = ''
-        self.rsa_private = ''
-        self.rsa_public = ''
 
     @staticmethod
     def get_filter_keywords():

+ 3 - 0
models/event_processor.py

@@ -99,6 +99,7 @@ class EventProcessor(object):
                     cls.guest_migrate_info.create()
 
         cls.guest.update()
+        cls.disk.update_by_filter({'on_host': cls.guest.on_host}, filter_str='guest_uuid:eq:' + cls.guest.uuid)
 
     @classmethod
     def host_event_processor(cls):
@@ -123,6 +124,7 @@ class EventProcessor(object):
         uuid = cls.message['message']['uuid']
         state = cls.message['type']
         data = cls.message['message']['data']
+        hostname = cls.message['host']
 
         if action == 'create':
             if state == ResponseState.success.value:
@@ -169,6 +171,7 @@ class EventProcessor(object):
         elif action == 'create_disk':
             cls.disk.uuid = uuid
             cls.disk.get_by('uuid')
+            cls.disk.on_host = hostname
             if state == ResponseState.success.value:
                 cls.disk.state = DiskState.idle.value
 

+ 4 - 2
models/guest.py

@@ -114,6 +114,7 @@ class Disk(ORM):
         self.size = None
         self.sequence = None
         self.state = DiskState.pending.value
+        self.on_host = ''
         self.format = 'qcow2'
         self.create_time = ji.Common.tus()
         self.guest_uuid = None
@@ -127,16 +128,17 @@ class Disk(ORM):
             'size': FilterFieldType.INT.value,
             'state': FilterFieldType.INT.value,
             'sequence': FilterFieldType.INT.value,
+            'on_host': FilterFieldType.STR.value,
             'guest_uuid': FilterFieldType.STR.value
         }
 
     @staticmethod
     def get_allow_update_keywords():
-        return []
+        return ['on_host']
 
     @staticmethod
     def get_allow_content_search_keywords():
-        return ['remark', 'size', 'guest_uuid', 'uuid']
+        return ['remark', 'size', 'guest_uuid', 'uuid', 'on_host']
 
 
 class GuestMigrateInfo(ORM):

+ 22 - 43
models/guest_xml.py

@@ -4,6 +4,7 @@
 
 from models import Config, Disk
 from models import Guest
+from models import status
 
 
 __author__ = 'James Iter'
@@ -13,45 +14,6 @@ __copyright__ = '(c) 2017 by James Iter.'
 
 
 class GuestXML(object):
-    """
-    <?xml version="1.0" encoding="utf-8"?>
-    <domain type="kvm">
-      <features>
-        <acpi/>
-        <apic/>
-      </features>
-      <name>10v022</name>
-      <vcpu>16</vcpu>
-      <memory unit="GiB">64</memory>
-      <os>
-        <boot dev="hd"/>
-        <type arch="x86_64">hvm</type>
-        <bootmenu timeout="3000" enable="yes"/>
-      </os>
-      <devices>
-        <interface type='network'>
-          <source network='net-br0'/>
-          <model type='virtio'/>
-        </interface>
-        <disk type='network' device='disk'>
-            <driver name='qemu' type='qcow2' cache='none'/>
-            <source protocol='gluster' name='gv0/VMs/disk_pool/10v01251/L_10v01251.qcow2'>
-                <host name='127.0.0.1' port='24007'/>
-            </source>
-            <target dev='vda' bus='virtio'/>
-        </disk>
-        <graphics passwd="000000" keymap="en-us" port="6002" type="vnc">
-          <listen network="net-br0" type="network"/>
-        </graphics>
-        <serial type='pty'>
-            <target port='0'/>
-        </serial>
-        <console type='pty'>
-            <target type='serial' port='0'/>
-        </console>
-      </devices>
-    </domain>
-    """
 
     def __init__(self, guest=None, disk=None, config=None):
         assert isinstance(guest, Guest)
@@ -129,15 +91,32 @@ class GuestXML(object):
 
         from initialize import dev_table
 
-        return """
+        if self.config.jimv_edition == status.JimVEdition.hyper_convergence.value:
+            dfs_protocol = 'ceph'
+            if self.config.dfs == status.DFS.glusterfs.value:
+                dfs_protocol = 'gluster'
+
+            disk_xml = """
                 <disk type='network' device='disk'>
                     <driver name='qemu' type='{0}' cache='none'/>
-                    <source protocol='gluster' name='{1}/{2}'>
+                    <source protocol='{1}' name='{2}/{3}'>
                         <host name='127.0.0.1' port='24007'/>
                     </source>
-                    <target dev='{3}' bus='virtio'/>
+                    <target dev='{4}' bus='virtio'/>
+                </disk>
+            """.format(self.disk.format, dfs_protocol, self.config.dfs_volume, self.disk.path,
+                       dev_table[self.disk.sequence])
+
+        else:
+            disk_xml = """
+                <disk type='file' device='disk'>
+                    <driver name='qemu' type='{0}' cache='none'/>
+                    <source file='{1}'/>
+                    <target dev='{2}' bus='virtio'/>
                 </disk>
-        """.format(self.disk.format, self.config.glusterfs_volume, self.disk.path, dev_table[self.disk.sequence])
+            """.format(self.disk.format, self.disk.path, dev_table[self.disk.sequence])
+
+        return disk_xml
 
     def get_graphics(self):
         return """

+ 3 - 1
models/rules.py

@@ -31,7 +31,9 @@ class Rules(Enum):
     BOOT_JOBS_ID = (REG_NUMBERS, 'boot_jobs_id')
 
     CONFIG_ID = (int, 'id')
-    GLUSTERFS_VOLUME = (basestring, 'glusterfs_volume')
+    JIMV_EDITION = (int, 'jimv_edition')
+    DFS = (int, 'dfs')
+    DFS_VOLUME = (basestring, 'dfs_volume')
     STORAGE_PATH = (basestring, 'storage_path')
     VM_NETWORK = (basestring, 'vm_network')
     VM_MANAGE_NETWORK = (basestring, 'vm_manage_network')

+ 10 - 0
models/status.py

@@ -11,6 +11,16 @@ __contact__ = 'james.iter.cn@gmail.com'
 __copyright__ = '(c) 2017 by James Iter.'
 
 
+class JimVEdition(IntEnum):
+    standalone = 0
+    hyper_convergence = 1
+
+
+class DFS(IntEnum):
+    ceph = 0
+    glusterfs = 1
+
+
 class EmitKind(IntEnum):
     log = 0
     guest_event = 1