[Kimchi-devel] [PATCHv3 3/8] Change 'cdrom' to a optional param

lvroyce0210 at gmail.com lvroyce0210 at gmail.com
Sun Jul 20 15:08:00 UTC 2014


From: Royce Lv <lvroyce at linux.vnet.ibm.com>

Multiple files modification for change 'cdrom' to optional param.

Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
---
 src/kimchi/control/templates.py |  2 +-
 src/kimchi/i18n.py              |  2 +-
 src/kimchi/imageinfo.py         | 19 ++++++++++++++++++-
 src/kimchi/mockmodel.py         | 27 +++++++++++++++++++++------
 src/kimchi/model/templates.py   | 13 ++++++++-----
 src/kimchi/vmtemplate.py        | 37 +++++++++++++++++++++++++++----------
 tests/test_rest.py              |  2 +-
 tests/test_vmtemplate.py        |  2 +-
 8 files changed, 78 insertions(+), 26 deletions(-)

diff --git a/src/kimchi/control/templates.py b/src/kimchi/control/templates.py
index 907929f..65b6805 100644
--- a/src/kimchi/control/templates.py
+++ b/src/kimchi/control/templates.py
@@ -47,7 +47,7 @@ class Template(Resource):
                 'os_version': self.info['os_version'],
                 'cpus': self.info['cpus'],
                 'memory': self.info['memory'],
-                'cdrom': self.info['cdrom'],
+                'cdrom': self.info.get('cdrom', None),
                 'disks': self.info['disks'],
                 'storagepool': self.info['storagepool'],
                 'networks': self.info['networks'],
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 0c3aae5..f872bee 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -118,7 +118,7 @@ messages = {
     "KCHTMPL0013E": _("Amount of memory (MB) must be an integer greater than 512"),
     "KCHTMPL0014E": _("Template CDROM must be a local or remote ISO file"),
     "KCHTMPL0015E": _("Invalid storage pool URI %(value)s specified for template"),
-    "KCHTMPL0016E": _("Specify an ISO image as CDROM to create a template"),
+    "KCHTMPL0016E": _("Specify an ISO image as CDROM or a base image to create a template"),
     "KCHTMPL0017E": _("All networks for the template must be specified in a list."),
     "KCHTMPL0018E": _("Must specify a volume to a template, when storage pool is iscsi or scsi"),
     "KCHTMPL0019E": _("The volume: %(volume)s in not in storage pool %(pool)s"),
diff --git a/src/kimchi/imageinfo.py b/src/kimchi/imageinfo.py
index f874ece..f4c6356 100644
--- a/src/kimchi/imageinfo.py
+++ b/src/kimchi/imageinfo.py
@@ -17,11 +17,28 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 
+import json
 import os
 import sys
 import guestfs
 
-from kimchi.exception import ImageFormatError
+from kimchi.exception import ImageFormatError, TimeoutExpired
+from kimchi.utils import run_command, kimchi_log
+
+
+def probe_img_info(path):
+    cmd = ["qemu-img", "info", "--output=json", path]
+    info = dict()
+    try:
+        out = run_command(cmd, 10)[0]
+    except TimeoutExpired:
+        kimchi_log.warning("Cannot decide format of base img %s", path)
+        return None
+
+    info = json.loads(out)
+    info['virtual-size'] = info['virtual-size'] >> 30
+    info['actual-size'] = info['actual-size'] >> 30
+    return info
 
 
 def probe_image(image_path):
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
index 0e45d1e..ccaa4d8 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -201,8 +201,10 @@ class MockModel(object):
             index += 1
 
         cdrom = "hd" + string.ascii_lowercase[index + 1]
-        cdrom_params = {'dev': cdrom, 'path': t_info['cdrom'], 'type': 'cdrom'}
-        vm.storagedevices[cdrom] = MockVMStorageDevice(cdrom_params)
+        if t_info.get('cdrom'):
+            cdrom_params = {
+                'dev': cdrom, 'path': t_info['cdrom'], 'type': 'cdrom'}
+            vm.storagedevices[cdrom] = MockVMStorageDevice(cdrom_params)
 
         self._mock_vms[name] = vm
         return name
@@ -238,11 +240,24 @@ class MockModel(object):
 
     def templates_create(self, params):
         name = params.get('name', '').strip()
+        iso = params.get('cdrom')
         if not name:
-            iso = params['cdrom']
-            iso_name = os.path.splitext(iso[iso.rfind('/') + 1:])[0]
-            name = iso_name + str(int(time.time() * 1000))
-            params['name'] = name
+            if iso:
+                iso_name = os.path.splitext(iso[iso.rfind('/') + 1:])[0]
+                name = iso_name + str(int(time.time() * 1000))
+                params['name'] = name
+            else:
+                raise InvalidParameter("KCHTMPL0008E")
+
+        base_tmpl = False
+        if not iso:
+            if 'disks' in params:
+                for d in params['disks']:
+                    if 'base' in d:
+                        base_tmpl = True
+                        break
+            if not base_tmpl:
+                raise InvalidParameter("KCHTMPL0016E")
 
         if name in self._mock_templates:
             raise InvalidOperation("KCHTMPL0001E", {'name': name})
diff --git a/src/kimchi/model/templates.py b/src/kimchi/model/templates.py
index 60f4de5..0e07a78 100644
--- a/src/kimchi/model/templates.py
+++ b/src/kimchi/model/templates.py
@@ -40,9 +40,9 @@ class TemplatesModel(object):
 
     def create(self, params):
         name = params.get('name', '').strip()
-        iso = params['cdrom']
+        iso = params.get('cdrom')
         # check search permission
-        if iso.startswith('/') and os.path.isfile(iso):
+        if iso and iso.startswith('/') and os.path.isfile(iso):
             user = UserTests().probe_user()
             ret, excp = probe_file_permission_as_user(iso, user)
             if ret is False:
@@ -51,9 +51,12 @@ class TemplatesModel(object):
                                         'err': excp})
 
         if not name:
-            iso_name = os.path.splitext(iso[iso.rfind('/') + 1:])[0]
-            name = iso_name + str(int(time.time() * 1000))
-            params['name'] = name
+            if iso:
+                iso_name = os.path.splitext(iso[iso.rfind('/') + 1:])[0]
+                name = iso_name + str(int(time.time() * 1000))
+                params['name'] = name
+            else:
+                raise InvalidParameter('KCHTMPL0008E')
 
         conn = self.conn.get()
         pool_uri = params.get(u'storagepool', '')
diff --git a/src/kimchi/vmtemplate.py b/src/kimchi/vmtemplate.py
index 8d5217a..0903b7f 100644
--- a/src/kimchi/vmtemplate.py
+++ b/src/kimchi/vmtemplate.py
@@ -24,7 +24,8 @@ import urlparse
 
 
 from kimchi import osinfo
-from kimchi.exception import InvalidParameter, IsoFormatError
+from kimchi.exception import InvalidParameter, IsoFormatError, ImageFormatError
+from kimchi.imageinfo import probe_image, probe_img_info
 from kimchi.isoinfo import IsoImage
 from kimchi.utils import check_url_path, pool_name_from_uri
 from lxml import etree
@@ -54,6 +55,19 @@ class VMTemplate(object):
         iso_distro = iso_version = 'unknown'
         iso = args.get('cdrom', '')
 
+        # if ISO not specified and base disk image specified,
+        # prevent cdrom from filling automatically
+        if len(iso) == 0 and 'disks' in args:
+            for d in args['disks']:
+                if 'base' in d:
+                    try:
+                        distro, version = probe_image(d['base'])
+                    except ImageFormatError:
+                        pass
+                    if 'size' not in d:
+                        d['size'] = probe_img_info(d['base'])['virtual-size']
+                    break
+
         if scan and len(iso) > 0:
             iso_distro, iso_version = self.get_iso_info(iso)
             if not iso.startswith('/'):
@@ -84,6 +98,8 @@ class VMTemplate(object):
             raise InvalidParameter("KCHISO0001E", {'filename': iso})
 
     def _get_cdrom_xml(self, libvirt_stream_protocols, qemu_stream_dns):
+        if 'cdrom' not in self.info:
+            return None
         bus = self.info['cdrom_bus']
         dev = "%s%s" % (self._bus_to_dev[bus],
                         string.lowercase[self.info['cdrom_index']])
@@ -325,13 +341,14 @@ drive=drive-%(bus)s0-1-0,id=%(bus)s0-1-0'/>
         libvirt_stream_protocols = kwargs.get('libvirt_stream_protocols', [])
         cdrom_xml = self._get_cdrom_xml(libvirt_stream_protocols,
                                         qemu_stream_dns)
-
-        if not urlparse.urlparse(self.info['cdrom']).scheme in \
-           libvirt_stream_protocols and params.get('iso_stream', False):
-            params['qemu-namespace'] = QEMU_NAMESPACE
-            params['qemu-stream-cmdline'] = cdrom_xml
-        else:
-            params['cdroms'] = cdrom_xml
+        if cdrom_xml:
+            if not urlparse.urlparse(self.info['cdrom']).scheme in \
+                    libvirt_stream_protocols and \
+                    params.get('iso_stream', False):
+                params['qemu-namespace'] = QEMU_NAMESPACE
+                params['qemu-stream-cmdline'] = cdrom_xml
+            else:
+                params['cdroms'] = cdrom_xml
 
         xml = """
         <domain type='%(domain)s' %(qemu-namespace)s>
@@ -414,8 +431,8 @@ drive=drive-%(bus)s0-1-0,id=%(bus)s0-1-0'/>
 
         # validate iso integrity
         # FIXME when we support multiples cdrom devices
-        iso = self.info['cdrom']
-        if not (os.path.isfile(iso) or check_url_path(iso)):
+        iso = self.info.get('cdrom')
+        if iso and not (os.path.isfile(iso) or check_url_path(iso)):
             invalid['cdrom'] = [iso]
 
         self.info['invalid'] = invalid
diff --git a/tests/test_rest.py b/tests/test_rest.py
index 54209ef..97668e7 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -1068,7 +1068,7 @@ class RestTests(unittest.TestCase):
         self.assertEquals(200, resp.status)
         self.assertEquals(0, len(json.loads(resp.read())))
 
-        # Create a template without cdrom fails with 400
+        # Create a template without cdrom and disk specified fails with 400
         t = {'name': 'test', 'os_distro': 'ImagineOS',
              'os_version': '1.0', 'memory': 1024, 'cpus': 1,
              'storagepool': '/storagepools/alt'}
diff --git a/tests/test_vmtemplate.py b/tests/test_vmtemplate.py
index 821ca24..319f250 100644
--- a/tests/test_vmtemplate.py
+++ b/tests/test_vmtemplate.py
@@ -29,7 +29,7 @@ class VMTemplateTests(unittest.TestCase):
     def test_minimal_construct(self):
         fields = (('name', 'test'), ('os_distro', 'unknown'),
                   ('os_version', 'unknown'), ('cpus', 1),
-                  ('memory', 1024), ('cdrom', ''), ('networks', ['default']),
+                  ('memory', 1024), ('networks', ['default']),
                   ('disk_bus', 'ide'), ('nic_model', 'e1000'),
                   ('graphics', {'type': 'vnc', 'listen': '0.0.0.0'}))
 
-- 
1.8.3.2




More information about the Kimchi-devel mailing list