Răsfoiți Sursa

实现创建虚拟机前半部分

James Iter 9 ani în urmă
părinte
comite
aba4a2dc53
7 a modificat fișierele cu 107 adăugiri și 41 ștergeri
  1. 1 1
      models/guest.py
  2. 5 5
      models/guest_xml.py
  3. 2 2
      models/rules.py
  4. 66 0
      tests/test_guest.py
  5. 5 3
      tests/test_os_init_write.py
  6. 1 0
      tests/test_os_template.py
  7. 27 30
      views/guest.py

+ 1 - 1
models/guest.py

@@ -26,7 +26,7 @@ class Guest(ORM):
         self.uuid = None
         self.uuid = None
         self.name = None
         self.name = None
         self.password = None
         self.password = None
-        self.remark = None
+        self.remark = ''
         self.os_template_id = None
         self.os_template_id = None
         self.create_time = ji.Common.tus()
         self.create_time = ji.Common.tus()
         self.status = GuestStatus.shutdown.value
         self.status = GuestStatus.shutdown.value

+ 5 - 5
models/guest_xml.py

@@ -51,14 +51,14 @@ class GuestXML(object):
     </domain>
     </domain>
     """
     """
 
 
-    def __init__(self, guest=None, disks=None, g_config=None):
+    def __init__(self, guest=None, disks=None, config=None):
         assert isinstance(guest, Guest)
         assert isinstance(guest, Guest)
         assert isinstance(disks, list)
         assert isinstance(disks, list)
-        assert isinstance(g_config, Config)
+        assert isinstance(config, Config)
 
 
         self.guest = guest
         self.guest = guest
         self.disks = disks
         self.disks = disks
-        self.g_config = g_config
+        self.config = config
 
 
     def get_domain(self):
     def get_domain(self):
         return """
         return """
@@ -125,7 +125,7 @@ class GuestXML(object):
         disks = []
         disks = []
         dev_table = ['vda', 'vdb', 'vdc', 'vdd']
         dev_table = ['vda', 'vdb', 'vdc', 'vdd']
 
 
-        for i, disk in self.disks:
+        for i, disk in enumerate(self.disks):
             disks.append("""
             disks.append("""
                 <disk type='network' device='disk'>
                 <disk type='network' device='disk'>
                     <driver name='qemu' type='qcow2' cache='none'/>
                     <driver name='qemu' type='qcow2' cache='none'/>
@@ -134,7 +134,7 @@ class GuestXML(object):
                     </source>
                     </source>
                     <target dev='{4}' bus='virtio'/>
                     <target dev='{4}' bus='virtio'/>
                 </disk>
                 </disk>
-            """.format(self.g_config.glusterfs_volume, self.guest.name, disk['label'], disk['format'], dev_table[i]))
+            """.format(self.config.glusterfs_volume, self.guest.name, disk['label'], disk['format'], dev_table[i]))
 
 
         return ''.join(disks)
         return ''.join(disks)
 
 

+ 2 - 2
models/rules.py

@@ -41,12 +41,12 @@ class Rules(Enum):
 
 
     CPU = (int, 'cpu')
     CPU = (int, 'cpu')
     MEMORY = (int, 'memory')
     MEMORY = (int, 'memory')
-    OS_TEMPLATE_ID = (basestring, 'os_template_id')
+    OS_TEMPLATE_ID = (int, 'os_template_id')
     DISKS = (list, 'disks')
     DISKS = (list, 'disks')
     QUANTITY = (int, 'quantity')
     QUANTITY = (int, 'quantity')
     NAME = (basestring, 'name')
     NAME = (basestring, 'name')
     PASSWORD = (basestring, 'password')
     PASSWORD = (basestring, 'password')
-    LEASE_TERM = (basestring, 'lease_term')
+    LEASE_TERM = (int, 'lease_term')
 
 
     REMARK = (basestring, 'remark')
     REMARK = (basestring, 'remark')
     LABEL = (basestring, 'label')
     LABEL = (basestring, 'label')

+ 66 - 0
tests/test_guest.py

@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+import requests
+import json
+import unittest
+
+
+__author__ = 'James Iter'
+__date__ = '2017/4/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2017 by James Iter.'
+
+
+class TestGuest(unittest.TestCase):
+
+    base_url = 'http://127.0.0.1:8008/api'
+    os_init_id = 0
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    # 创建Guest
+    def test_11_create(self):
+        payload = {
+            "cpu": 4,
+            "memory": 4,
+            "os_template_id": 5,
+            "disks": [{"size": 200}],
+            "quantity": 2,
+            "name": "",
+            "password": "pswd.com",
+            "lease_term": 100
+        }
+
+        url = TestGuest.base_url + '/guest'
+        headers = {'content-type': 'application/json'}
+        r = requests.post(url, data=json.dumps(payload), headers=headers)
+        j_r = json.loads(r.content)
+        print json.dumps(j_r, ensure_ascii=False)
+        self.assertEqual('200', j_r['state']['code'])
+
+    # 获取Guest列表
+    def test_12_get(self):
+        pass
+
+    # 更新Guest属性
+    def test_13_update(self):
+        pass
+
+    # 校验更新结果
+    def test_14_get(self):
+        pass
+
+    # 删除Guest
+    def test_15_delete(self):
+        pass
+
+
+if __name__ == '__main__':
+    unittest.main()
+

+ 5 - 3
tests/test_os_init_write.py

@@ -45,7 +45,7 @@ class TestOSInitWrite(unittest.TestCase):
         payload = {
         payload = {
             "os_init_id": TestOSInitWrite.os_init_id,
             "os_init_id": TestOSInitWrite.os_init_id,
             "path": "/etc/resolv.conf",
             "path": "/etc/resolv.conf",
-            "content": "".join([
+            "content": "\n".join([
                 "nameserver {DNS1}",
                 "nameserver {DNS1}",
                 "nameserver {DNS2}"
                 "nameserver {DNS2}"
             ])
             ])
@@ -90,7 +90,7 @@ class TestOSInitWrite(unittest.TestCase):
         payload = {
         payload = {
             "os_init_id": TestOSInitWrite.os_init_id,
             "os_init_id": TestOSInitWrite.os_init_id,
             "path": "/etc/hostname",
             "path": "/etc/hostname",
-            "content": "{HOSTNAME}"
+            "content": "hostname"
         }
         }
 
 
         url = TestOSInitWrite.base_url + '/os_init_write'
         url = TestOSInitWrite.base_url + '/os_init_write'
@@ -128,7 +128,7 @@ class TestOSInitWrite(unittest.TestCase):
         payload = {
         payload = {
             "os_init_id": TestOSInitWrite.os_init_id,
             "os_init_id": TestOSInitWrite.os_init_id,
             "path": "/etc/hostname",
             "path": "/etc/hostname",
-            "content": "hostname"
+            "content": "{HOSTNAME}"
         }
         }
 
 
         url = TestOSInitWrite.base_url + '/os_init_write/' + TestOSInitWrite.os_init_write_id.__str__()
         url = TestOSInitWrite.base_url + '/os_init_write/' + TestOSInitWrite.os_init_write_id.__str__()
@@ -138,6 +138,7 @@ class TestOSInitWrite(unittest.TestCase):
         print json.dumps(j_r, ensure_ascii=False)
         print json.dumps(j_r, ensure_ascii=False)
         self.assertEqual('200', j_r['state']['code'])
         self.assertEqual('200', j_r['state']['code'])
 
 
+    @unittest.skip('skip delete os init write!')
     def test_27_delete(self):
     def test_27_delete(self):
         url = TestOSInitWrite.base_url + '/os_init_write/' + TestOSInitWrite.os_init_write_id.__str__()
         url = TestOSInitWrite.base_url + '/os_init_write/' + TestOSInitWrite.os_init_write_id.__str__()
         headers = {'content-type': 'application/json'}
         headers = {'content-type': 'application/json'}
@@ -146,6 +147,7 @@ class TestOSInitWrite(unittest.TestCase):
         print json.dumps(j_r, ensure_ascii=False)
         print json.dumps(j_r, ensure_ascii=False)
         self.assertEqual('200', j_r['state']['code'])
         self.assertEqual('200', j_r['state']['code'])
 
 
+    @unittest.skip('skip delete os init!')
     # 删除系统初始化组列表更新结果
     # 删除系统初始化组列表更新结果
     def test_31_delete(self):
     def test_31_delete(self):
         url = TestOSInitWrite.base_url + '/os_init/' + TestOSInitWrite.os_init_id.__str__()
         url = TestOSInitWrite.base_url + '/os_init/' + TestOSInitWrite.os_init_id.__str__()

+ 1 - 0
tests/test_os_template.py

@@ -72,6 +72,7 @@ class TestOSTemplate(unittest.TestCase):
         self.assertEqual('200', j_r['state']['code'])
         self.assertEqual('200', j_r['state']['code'])
         self.assertEqual('CentOS-72', j_r['data'][0]['label'])
         self.assertEqual('CentOS-72', j_r['data'][0]['label'])
 
 
+    @unittest.skip('skip delete os template!')
     # 删除系统模板
     # 删除系统模板
     def test_15_delete(self):
     def test_15_delete(self):
         url = TestOSTemplate.base_url + '/os_template/' + TestOSTemplate.os_template_id.__str__()
         url = TestOSTemplate.base_url + '/os_template/' + TestOSTemplate.os_template_id.__str__()

+ 27 - 30
views/guest.py

@@ -4,13 +4,14 @@
 
 
 import copy
 import copy
 from flask import Blueprint
 from flask import Blueprint
-from flask import request, g
+from flask import request
 import json
 import json
 from uuid import uuid4
 from uuid import uuid4
 import jimit as ji
 import jimit as ji
 
 
 from models import OSInitWrite
 from models import OSInitWrite
 from models.initialize import app
 from models.initialize import app
+from models import Database as db
 from models import Config
 from models import Config
 from models import GuestDisk
 from models import GuestDisk
 from models import Rules
 from models import Rules
@@ -53,13 +54,9 @@ def r_create():
 
 
         ji.Check.previewing(args_rules, request.json)
         ji.Check.previewing(args_rules, request.json)
 
 
-        if g.config is None:
-            config = Config()
-            config.id = 1
-            config.get()
-            g.config = config
-
-        assert isinstance(g.config, Config)
+        config = Config()
+        config.id = 1
+        config.get()
 
 
         os_template = OSTemplate()
         os_template = OSTemplate()
         os_template.id = request.json.get('os_template_id')
         os_template.id = request.json.get('os_template_id')
@@ -70,10 +67,10 @@ def r_create():
 
 
         os_template.get()
         os_template.get()
 
 
-        os_init_writes = OSInitWrite.get_by_filter(
+        os_init_writes, os_init_writes_count = OSInitWrite.get_by_filter(
             filter_str='os_init_id:in:' + os_template.os_init_id.__str__())
             filter_str='os_init_id:in:' + os_template.os_init_id.__str__())
 
 
-        if g.r.scard(app.config['ip_available_set']) < 1:
+        if db.r.scard(app.config['ip_available_set']) < 1:
             ret['state'] = ji.Common.exchange_state(50350)
             ret['state'] = ji.Common.exchange_state(50350)
             return ret
             return ret
 
 
@@ -84,8 +81,8 @@ def r_create():
             guest = Guest()
             guest = Guest()
             guest.uuid = uuid4().__str__()
             guest.uuid = uuid4().__str__()
             guest.cpu = request.json.get('cpu')
             guest.cpu = request.json.get('cpu')
-            # 虚拟机内存单位默认KiB,所以这个乘1024的平方,使得用户填入的单位变为GiB
-            guest.memory = request.json.get('memory') * 1024 * 1024
+            # 虚拟机内存单位,模板生成方法中已置其为GiB
+            guest.memory = request.json.get('memory')
             guest.os_template_id = request.json.get('os_template_id')
             guest.os_template_id = request.json.get('os_template_id')
             guest.name = request.json.get('name')
             guest.name = request.json.get('name')
 
 
@@ -96,19 +93,19 @@ def r_create():
             while guest.name.__len__() < 1 or guest.exist_by('name'):
             while guest.name.__len__() < 1 or guest.exist_by('name'):
                 guest.name = ji.Common.generate_random_code(length=8)
                 guest.name = ji.Common.generate_random_code(length=8)
 
 
-            guest.ip = g.r.spop(app.config['ip_available_set'])
-            g.r.sadd(app.config['ip_used_set'], guest.ip)
+            guest.ip = db.r.spop(app.config['ip_available_set'])
+            db.r.sadd(app.config['ip_used_set'], guest.ip)
 
 
-            guest.network = g.config.vm_network
-            guest.manage_network = g.config.vm_manage_network
+            guest.network = config.vm_network
+            guest.manage_network = config.vm_manage_network
 
 
-            guest.vnc_port = g.r.spop(app.config['vnc_port_available_set'])
-            g.r.sadd(app.config['vnc_port_used_set'], guest.vnc_port)
+            guest.vnc_port = db.r.spop(app.config['vnc_port_available_set'])
+            db.r.sadd(app.config['vnc_port_used_set'], guest.vnc_port)
 
 
             guest.vnc_password = ji.Common.generate_random_code(length=16)
             guest.vnc_password = ji.Common.generate_random_code(length=16)
 
 
             guest_disks = list()
             guest_disks = list()
-            guest_disks.append({'label': uuid4(), 'size': -1, 'format': 'qcow2'})
+            guest_disks.append({'label': uuid4().__str__(), 'size': -1, 'format': 'qcow2'})
 
 
             for i, disk in enumerate(request.json.get('disks')):
             for i, disk in enumerate(request.json.get('disks')):
                 guest_disk = GuestDisk()
                 guest_disk = GuestDisk()
@@ -119,37 +116,37 @@ def r_create():
                     continue
                     continue
 
 
                 guest_disk.guest_uuid = guest.uuid
                 guest_disk.guest_uuid = guest.uuid
-                guest_disk.label = uuid4()
+                guest_disk.label = uuid4().__str__()
                 guest_disk.sequence = i + 1
                 guest_disk.sequence = i + 1
                 guest_disk.format = 'qcow2'
                 guest_disk.format = 'qcow2'
                 guest_disk.create()
                 guest_disk.create()
 
 
                 guest_disks.append({'label': guest_disk.label, 'size': guest_disk.size, 'format': guest_disk.format})
                 guest_disks.append({'label': guest_disk.label, 'size': guest_disk.size, 'format': guest_disk.format})
 
 
+            guest_xml = GuestXML(guest=guest, disks=guest_disks, config=config)
+            guest.xml = guest_xml.get_domain()
             guest.create()
             guest.create()
-            guest_xml = GuestXML(guest=guest, disks=guest_disks, g_config=g.config)
-            guest_xml.get_domain()
 
 
             # 替换占位符为有效内容
             # 替换占位符为有效内容
             _os_init_writes = copy.deepcopy(os_init_writes)
             _os_init_writes = copy.deepcopy(os_init_writes)
-            for k, v in _os_init_writes:
-                _os_init_writes[k] = v.replace('{IP}', guest.ip).\
+            for k, v in enumerate(_os_init_writes):
+                _os_init_writes[k] = v['content'].replace('{IP}', guest.ip).\
                     replace('{HOSTNAME}', guest.name).\
                     replace('{HOSTNAME}', guest.name).\
-                    replace('{NETMASK}', g.config.netmask).\
-                    replace('{GATEWAY}', g.config.gateway).\
-                    replace('{DNS1}', g.config.dns1).\
-                    replace('{DNS2}', g.config.dns2)
+                    replace('{NETMASK}', config.netmask).\
+                    replace('{GATEWAY}', config.gateway).\
+                    replace('{DNS1}', config.dns1).\
+                    replace('{DNS2}', config.dns2)
 
 
             create_vm_msg = {
             create_vm_msg = {
                 'uuid': guest.uuid,
                 'uuid': guest.uuid,
-                'glusterfs_volume': g.config.glusterfs_volume,
+                'glusterfs_volume': config.glusterfs_volume,
                 'template_path': 'template_pool/' + os_template.name,
                 'template_path': 'template_pool/' + os_template.name,
                 'guest_disks': guest_disks,
                 'guest_disks': guest_disks,
                 'writes': _os_init_writes,
                 'writes': _os_init_writes,
                 'password': guest.password,
                 'password': guest.password,
                 'xml': guest_xml.get_domain()
                 'xml': guest_xml.get_domain()
             }
             }
-            g.r.rpush(app.config['vm_create_queue'], json.dumps(create_vm_msg, ensure_ascii=False))
+            db.r.rpush(app.config['vm_create_queue'], json.dumps(create_vm_msg, ensure_ascii=False))
 
 
         return ret
         return ret