Просмотр исходного кода

实现兼容单机版创建Guest

James Iter 9 лет назад
Родитель
Сommit
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
             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}
                        'image_path': disk.path, 'size': disk.size, 'uuid': disk.uuid}
 
 
             db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
             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.id = 1
             config.get()
             config.get()
 
 
-            message['glusterfs_volume'] = config.glusterfs_volume
+            message['glusterfs_volume'] = config.dfs_volume
             message['image_path'] = disk.path
             message['image_path'] = disk.path
 
 
             db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
             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')
             disk.get_by('uuid')
 
 
             message = {'action': 'delete_disk', 'uuid': disk.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))
             db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
 
 
         return ret
         return ret

+ 20 - 26
api/guest.py

@@ -163,10 +163,12 @@ def r_create():
 
 
             create_vm_msg = {
             create_vm_msg = {
                 'action': 'create',
                 'action': 'create',
+                'jimv_edition': config.jimv_edition,
+                'dfs': config.dfs,
+                'dfs_volume': config.dfs_volume,
                 'uuid': guest.uuid,
                 'uuid': guest.uuid,
                 'hostname': lightest_host['hostname'],
                 'hostname': lightest_host['hostname'],
                 'name': guest.label,
                 'name': guest.label,
-                'glusterfs_volume': config.glusterfs_volume,
                 'template_path': os_template.path,
                 'template_path': os_template.path,
                 'disk': disk.__dict__,
                 'disk': disk.__dict__,
                 'xml': guest_xml.get_domain(),
                 'xml': guest_xml.get_domain(),
@@ -419,9 +421,19 @@ def r_delete(uuids):
             guest.uuid = uuid
             guest.uuid = uuid
             guest.get_by('uuid')
             guest.get_by('uuid')
 
 
+        config = Config()
+        config.id = 1
+        config.get()
+
         # 执行删除操作
         # 执行删除操作
         for uuid in uuids.split(','):
         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))
             Guest.emit_instruction(message=json.dumps(message))
 
 
         ret = dict()
         ret = dict()
@@ -484,18 +496,9 @@ def r_attach_disk(uuid, disk_uuid):
         config.id = 1
         config.id = 1
         config.get()
         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}}
                    'passback_parameters': {'disk_uuid': disk.uuid, 'sequence': disk.sequence}}
         Guest.emit_instruction(message=json.dumps(message))
         Guest.emit_instruction(message=json.dumps(message))
         disk.update()
         disk.update()
@@ -542,18 +545,9 @@ def r_detach_disk(disk_uuid):
         config.id = 1
         config.id = 1
         config.get()
         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}}
                    'passback_parameters': {'disk_uuid': disk.uuid}}
         Guest.emit_instruction(message=json.dumps(message))
         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 blueprint as host_performance_blueprint
 from api.host_performance import blueprints as host_performance_blueprints
 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.dashboard import blueprint as view_dashboard_blueprint
 from views.guest import blueprint as view_guest_blueprint
 from views.guest import blueprint as view_guest_blueprint
 from views.guest import blueprints as view_guest_blueprints
 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_blueprint)
     app.register_blueprint(host_performance_blueprints)
     app.register_blueprint(host_performance_blueprints)
 
 
+    app.register_blueprint(view_config_blueprint)
     app.register_blueprint(view_dashboard_blueprint)
     app.register_blueprint(view_dashboard_blueprint)
     app.register_blueprint(view_guest_blueprint)
     app.register_blueprint(view_guest_blueprint)
     app.register_blueprint(view_guest_blueprints)
     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,
     uuid CHAR(36) NOT NULL,
     path VARCHAR(255) NOT NULL,
     path VARCHAR(255) NOT NULL,
     size INT UNSIGNED NOT NULL,
     size INT UNSIGNED NOT NULL,
+    on_host VARCHAR(128) NOT NULL DEFAULT '',
     remark VARCHAR(255) NOT NULL DEFAULT '',
     remark VARCHAR(255) NOT NULL DEFAULT '',
     sequence TINYINT NOT NULL,
     sequence TINYINT NOT NULL,
     format CHAR(16) NOT NULL DEFAULT 'qcow2',
     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 (size);
 ALTER TABLE disk ADD INDEX (guest_uuid);
 ALTER TABLE disk ADD INDEX (guest_uuid);
+ALTER TABLE disk ADD INDEX (on_host);
 ALTER TABLE disk ADD INDEX (remark);
 ALTER TABLE disk ADD INDEX (remark);
 
 
 
 
@@ -113,7 +115,9 @@ CREATE TABLE IF NOT EXISTS operate_rule(
 
 
 CREATE TABLE IF NOT EXISTS config(
 CREATE TABLE IF NOT EXISTS config(
     id BIGINT UNSIGNED NOT NULL DEFAULT 1,
     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,
     storage_path VARCHAR(255) NOT NULL,
     vm_network VARCHAR(255) NOT NULL,
     vm_network VARCHAR(255) NOT NULL,
     vm_manage_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,
     gateway CHAR(15) NOT NULL,
     dns1 CHAR(15) NOT NULL DEFAULT '223.5.5.5',
     dns1 CHAR(15) NOT NULL DEFAULT '223.5.5.5',
     dns2 CHAR(15) NOT NULL DEFAULT '8.8.8.8',
     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))
     PRIMARY KEY (id))
     ENGINE=InnoDB
     ENGINE=InnoDB
     DEFAULT CHARSET=utf8;
     DEFAULT CHARSET=utf8;

+ 4 - 3
models/config.py

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

+ 3 - 0
models/event_processor.py

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

+ 4 - 2
models/guest.py

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

+ 22 - 43
models/guest_xml.py

@@ -4,6 +4,7 @@
 
 
 from models import Config, Disk
 from models import Config, Disk
 from models import Guest
 from models import Guest
+from models import status
 
 
 
 
 __author__ = 'James Iter'
 __author__ = 'James Iter'
@@ -13,45 +14,6 @@ __copyright__ = '(c) 2017 by James Iter.'
 
 
 
 
 class GuestXML(object):
 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):
     def __init__(self, guest=None, disk=None, config=None):
         assert isinstance(guest, Guest)
         assert isinstance(guest, Guest)
@@ -129,15 +91,32 @@ class GuestXML(object):
 
 
         from initialize import dev_table
         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'>
                 <disk type='network' device='disk'>
                     <driver name='qemu' type='{0}' cache='none'/>
                     <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'/>
                         <host name='127.0.0.1' port='24007'/>
                     </source>
                     </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>
                 </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):
     def get_graphics(self):
         return """
         return """

+ 3 - 1
models/rules.py

@@ -31,7 +31,9 @@ class Rules(Enum):
     BOOT_JOBS_ID = (REG_NUMBERS, 'boot_jobs_id')
     BOOT_JOBS_ID = (REG_NUMBERS, 'boot_jobs_id')
 
 
     CONFIG_ID = (int, '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')
     STORAGE_PATH = (basestring, 'storage_path')
     VM_NETWORK = (basestring, 'vm_network')
     VM_NETWORK = (basestring, 'vm_network')
     VM_MANAGE_NETWORK = (basestring, 'vm_manage_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.'
 __copyright__ = '(c) 2017 by James Iter.'
 
 
 
 
+class JimVEdition(IntEnum):
+    standalone = 0
+    hyper_convergence = 1
+
+
+class DFS(IntEnum):
+    ceph = 0
+    glusterfs = 1
+
+
 class EmitKind(IntEnum):
 class EmitKind(IntEnum):
     log = 0
     log = 0
     guest_event = 1
     guest_event = 1