Selaa lähdekoodia

实现创建虚拟机前半部分

James Iter 9 vuotta sitten
vanhempi
sitoutus
aba4a2dc53
7 muutettua tiedostoa jossa 107 lisäystä ja 41 poistoa
  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.name = None
         self.password = None
-        self.remark = None
+        self.remark = ''
         self.os_template_id = None
         self.create_time = ji.Common.tus()
         self.status = GuestStatus.shutdown.value

+ 5 - 5
models/guest_xml.py

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

+ 2 - 2
models/rules.py

@@ -41,12 +41,12 @@ class Rules(Enum):
 
     CPU = (int, 'cpu')
     MEMORY = (int, 'memory')
-    OS_TEMPLATE_ID = (basestring, 'os_template_id')
+    OS_TEMPLATE_ID = (int, 'os_template_id')
     DISKS = (list, 'disks')
     QUANTITY = (int, 'quantity')
     NAME = (basestring, 'name')
     PASSWORD = (basestring, 'password')
-    LEASE_TERM = (basestring, 'lease_term')
+    LEASE_TERM = (int, 'lease_term')
 
     REMARK = (basestring, 'remark')
     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 = {
             "os_init_id": TestOSInitWrite.os_init_id,
             "path": "/etc/resolv.conf",
-            "content": "".join([
+            "content": "\n".join([
                 "nameserver {DNS1}",
                 "nameserver {DNS2}"
             ])
@@ -90,7 +90,7 @@ class TestOSInitWrite(unittest.TestCase):
         payload = {
             "os_init_id": TestOSInitWrite.os_init_id,
             "path": "/etc/hostname",
-            "content": "{HOSTNAME}"
+            "content": "hostname"
         }
 
         url = TestOSInitWrite.base_url + '/os_init_write'
@@ -128,7 +128,7 @@ class TestOSInitWrite(unittest.TestCase):
         payload = {
             "os_init_id": TestOSInitWrite.os_init_id,
             "path": "/etc/hostname",
-            "content": "hostname"
+            "content": "{HOSTNAME}"
         }
 
         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)
         self.assertEqual('200', j_r['state']['code'])
 
+    @unittest.skip('skip delete os init write!')
     def test_27_delete(self):
         url = TestOSInitWrite.base_url + '/os_init_write/' + TestOSInitWrite.os_init_write_id.__str__()
         headers = {'content-type': 'application/json'}
@@ -146,6 +147,7 @@ class TestOSInitWrite(unittest.TestCase):
         print json.dumps(j_r, ensure_ascii=False)
         self.assertEqual('200', j_r['state']['code'])
 
+    @unittest.skip('skip delete os init!')
     # 删除系统初始化组列表更新结果
     def test_31_delete(self):
         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('CentOS-72', j_r['data'][0]['label'])
 
+    @unittest.skip('skip delete os template!')
     # 删除系统模板
     def test_15_delete(self):
         url = TestOSTemplate.base_url + '/os_template/' + TestOSTemplate.os_template_id.__str__()

+ 27 - 30
views/guest.py

@@ -4,13 +4,14 @@
 
 import copy
 from flask import Blueprint
-from flask import request, g
+from flask import request
 import json
 from uuid import uuid4
 import jimit as ji
 
 from models import OSInitWrite
 from models.initialize import app
+from models import Database as db
 from models import Config
 from models import GuestDisk
 from models import Rules
@@ -53,13 +54,9 @@ def r_create():
 
         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.id = request.json.get('os_template_id')
@@ -70,10 +67,10 @@ def r_create():
 
         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__())
 
-        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)
             return ret
 
@@ -84,8 +81,8 @@ def r_create():
             guest = Guest()
             guest.uuid = uuid4().__str__()
             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.name = request.json.get('name')
 
@@ -96,19 +93,19 @@ def r_create():
             while guest.name.__len__() < 1 or guest.exist_by('name'):
                 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_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')):
                 guest_disk = GuestDisk()
@@ -119,37 +116,37 @@ def r_create():
                     continue
 
                 guest_disk.guest_uuid = guest.uuid
-                guest_disk.label = uuid4()
+                guest_disk.label = uuid4().__str__()
                 guest_disk.sequence = i + 1
                 guest_disk.format = 'qcow2'
                 guest_disk.create()
 
                 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_xml = GuestXML(guest=guest, disks=guest_disks, g_config=g.config)
-            guest_xml.get_domain()
 
             # 替换占位符为有效内容
             _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('{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 = {
                 'uuid': guest.uuid,
-                'glusterfs_volume': g.config.glusterfs_volume,
+                'glusterfs_volume': config.glusterfs_volume,
                 'template_path': 'template_pool/' + os_template.name,
                 'guest_disks': guest_disks,
                 'writes': _os_init_writes,
                 'password': guest.password,
                 '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