[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEND] Fix bugs in vbd_create logic when handling VDIs



# HG changeset patch
# User Alastair Tse <atse@xxxxxxxxxxxxx>
# Node ID d34c657e5c74495c2c95fb71b38eb4fac998084d
# Parent  a02f6d28eded3f395a6ac3cd63b9276fd820df36
[XEND] Fix bugs in vbd_create logic when handling VDIs

Attempt to handle 'tap' devices as 'vbd' devices even though the
internal configuration has no idea that 'tap' is a subclass of 'vbd'.

Add option parsing to vbd-create and vdi-create so you can override
the configuration file options.

Signed-off-by: Alastair Tse <atse@xxxxxxxxxxxxx>
---
 tools/python/scripts/xapi.py            |   74 +++++++++++++++++++++++++++-----
 tools/python/xen/xend/XendAPI.py        |   12 +++--
 tools/python/xen/xend/XendDomainInfo.py |   61 +++++++++++++++++---------
 3 files changed, 111 insertions(+), 36 deletions(-)

diff -r a02f6d28eded -r d34c657e5c74 tools/python/scripts/xapi.py
--- a/tools/python/scripts/xapi.py      Fri Oct 13 15:38:13 2006 +0100
+++ b/tools/python/scripts/xapi.py      Fri Oct 13 17:17:45 2006 +0100
@@ -35,7 +35,9 @@ COMMANDS = {
 COMMANDS = {
     'host-info': ('', 'Get Xen Host Info'),
     'sr-list':   ('', 'List all SRs'),
-    'vbd-create': ('<domname> <pycfg>', 'Create VBD attached to domname'),
+    'vbd-create': ('<domname> <pycfg> [opts]',
+                   'Create VBD attached to domname'),
+    'vdi-create': ('<pycfg> [opts]', 'Create a VDI'),
     'vdi-list'  : ('', 'List all VDI'),
     'vdi-rename': ('<vdi_uuid> <new_name>', 'Rename VDI'),
     'vdi-delete': ('<vdi_uuid>', 'Delete VDI'),
@@ -57,7 +59,28 @@ OPTIONS = {
                  {'action':'store_true',
                   'help':'List all properties of VMs'})
                ],
-   
+    
+    'vdi-create': [(('--label',), {'help': 'Name for VDI'}),
+                   (('--description',), {'help': 'Description for VDI'}),
+                   (('--sector-size',), {'type': 'int',
+                                         'help': 'Sector size'}),
+                   (('--virtual-size',), {'type': 'int',
+                                          'help': 'Size of VDI in sectors'}),
+                   (('--type',), {'choices': ['system', 'user', 'ephemeral'],
+                                  'help': 'VDI type'}),
+                   (('--sharable',), {'action': 'store_true',
+                                      'help': 'VDI sharable'}),
+                   (('--read-only',), {'action': 'store_true',
+                                       'help': 'Read only'})],
+    
+    'vbd-create': [(('--VDI',), {'help': 'UUID of VDI to attach to.'}),
+                   (('--mode',), {'choices': ['RO', 'RW'],
+                                  'help': 'device mount mode'}),
+                   (('--driver',), {'choices':['paravirtualised', 'ioemu'],
+                                    'help': 'Driver for VBD'}),
+                   (('--device',), {'help': 'Device name on guest domain'}),
+                   (('--image',), {'help': 'Location of drive image.'})]
+                   
 }
 
 class OptionError(Exception):
@@ -69,6 +92,16 @@ class XenAPIError(Exception):
 # 
 # Extra utility functions
 #
+
+class IterableValues(Values):
+    """Better interface to the list of values from optparse."""
+
+    def __iter__(self):
+        for opt, val in self.__dict__.items():
+            if opt[0] == '_' or callable(val):
+                continue
+            yield opt, val        
+
 
 def parse_args(cmd_name, args):
     argstring, desc = COMMANDS[cmd_name]
@@ -77,8 +110,11 @@ def parse_args(cmd_name, args):
     if cmd_name in OPTIONS:
         for optargs, optkwds in OPTIONS[cmd_name]:
             parser.add_option(*optargs, **optkwds)
-            
-    (opts, extraargs) = parser.parse_args(list(args))
+
+    default_values = parser.get_default_values()
+    defaults = IterableValues(default_values.__dict__)
+    (opts, extraargs) = parser.parse_args(args = list(args),
+                                          values = defaults)
     return opts, extraargs
 
 def execute(fn, *args):
@@ -106,7 +142,7 @@ def _read_python_cfg(filename):
     return cfg
 
 def resolve_vm(server, session, vm_name):
-    vm_uuid = execute(server.VM.get_by_label, session, vm_name)
+    vm_uuid = execute(server.VM.get_by_name_label, session, vm_name)
     if not vm_uuid:
         return None
     else:
@@ -204,7 +240,7 @@ def xapi_vm_start(*args):
         raise OptionError("No Domain name specified.")
     
     server, session = _connect()
-    vm_uuid = execute(server.VM.get_by_label, session, args[0])
+    vm_uuid = resolve_vm(server, session, args[0])
     print 'Starting VM %s (%s)' % (args[0], vm_uuid)
     success = execute(server.VM.start, session, vm_uuid)
     print 'Done.'
@@ -233,9 +269,16 @@ def xapi_vbd_create(*args):
     if len(args) < 2:
         raise OptionError("Configuration file not specified")
 
+    opts, args = parse_args('vbd-create', args)
     domname = args[0]
     filename = args[1]
-    cfg = _read_python_cfg(filename)
+
+    cfg = {}
+    for opt, val in opts:
+        cfg[opt] = val
+    cfg.update(_read_python_cfg(filename))
+    
+    
     print 'Creating VBD from %s ..' % filename
     server, session = _connect()
     vm_uuid = resolve_vm(server, session, domname)
@@ -250,6 +293,7 @@ def xapi_vif_create(*args):
     domname = args[0]
     filename = args[1]
     cfg = _read_python_cfg(filename)
+    
     print 'Creating VIF from %s ..' % filename
     server, session = _connect()
     vm_uuid = resolve_vm(server, session, domname)
@@ -283,9 +327,17 @@ def xapi_sr_list(*args):
         print SR_LIST_FORMAT % sr_struct
 
 def xapi_vdi_create(*args):
-    server, session = _connect()
-    cfg = _read_python_cfg(args[0])
-
+    opts, args = parse_args('vdi-create', args)
+
+    if len(args) < 1:
+        raise OptionError("Not enough arguments.")
+
+    cfg = {}
+    for opt, val in opts:
+        cfg[opt] = val
+    cfg.update(_read_python_cfg(args[0]))
+
+    server, session = _connect()
     srs = execute(server.SR.get_all, session)
     sr = srs[0]
     cfg['SR'] = sr
@@ -359,6 +411,8 @@ def main(args):
     except XenAPIError, e:
         print 'Error: %s' % str(e.args[1])
         sys.exit(2)
+    except OptionError, e:
+        print 'Error: %s' % e
 
     sys.exit(0)
     
diff -r a02f6d28eded -r d34c657e5c74 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Fri Oct 13 15:38:13 2006 +0100
+++ b/tools/python/xen/xend/XendAPI.py  Fri Oct 13 17:17:45 2006 +0100
@@ -1001,10 +1001,10 @@ class XendAPI:
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
         if not vm:
-            return xen_api_error(XEND_ERROR_VIF_INVALID)
+            return xen_api_error(XEND_ERROR_VBD_INVALID)
         cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
         if not cfg:
-            return xen_api_error(XEND_ERROR_VIF_INVALID)
+            return xen_api_error(XEND_ERROR_VBD_INVALID)
         return xen_api_success(cfg)
     
     # class methods
@@ -1016,7 +1016,7 @@ class XendAPI:
         dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
         vbd_ref = ''
         try:
-            if vbd_struct.get('VDI', None):
+            if not vbd_struct.get('VDI', None):
                 # this is a traditional VBD without VDI and SR 
                 vbd_ref = dom.create_vbd(vbd_struct)
             else:
@@ -1024,8 +1024,10 @@ class XendAPI:
                 vdi_ref = vbd_struct.get('VDI')
                 sr = XendNode.instance().get_sr()
                 vdi_image = sr.xen_api_get_by_uuid(vdi_ref)
-                vdi_image_path = vdi_image.image_path
-                vbd_ref = dom.create_vbd_with_vdi(vbd_struct, vdi_image_path)
+                if not vdi_image:
+                    return xen_api_error(XEND_ERROR_VDI_INVALID)
+                vdi_image = vdi_image.qcow_path
+                vbd_ref = dom.create_vbd_with_vdi(vbd_struct, vdi_image)
         except XendError:
             return xen_api_todo()
 
diff -r a02f6d28eded -r d34c657e5c74 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Fri Oct 13 15:38:13 2006 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Oct 13 17:17:45 2006 +0100
@@ -28,6 +28,7 @@ import time
 import time
 import threading
 import re
+import copy
 
 import xen.lowlevel.xc
 from xen.util import asserts
@@ -1719,28 +1720,44 @@ class XendDomainInfo:
 
     def get_dev_config_by_uuid(self, dev_class, dev_uuid):
         """ Get's a device configuration either from XendConfig or
-        from the DevController."""
+        from the DevController.
+
+        @param dev_class: device class, either, 'vbd' or 'vif'
+        @param dev_uuid: device UUID
+
+        @rtype: dictionary
+        """
+        dev_type_config = self.info['device'].get(dev_uuid)
+
+        # shortcut if the domain isn't started because
+        # the devcontrollers will have no better information
+        # than XendConfig.
         if self.state in (XEN_API_VM_POWER_STATE_HALTED,):
-            dev = self.info['device'].get(dev_uuid)
-            if dev:
-                return dev[1].copy()
+            if dev_type_config:
+                return copy.deepcopy(dev_type_config[1])
             return None
-        else:
-            controller = self.getDeviceController(dev_class)
-            if not controller:
-                return None
+
+        # instead of using dev_class, we use the dev_type
+        # that is from XendConfig.
+        # This will accomdate 'tap' as well as 'vbd'
+        dev_type = dev_type_config[0]
+        
+        controller = self.getDeviceController(dev_type)
+        if not controller:
+            return None
             
-            all_configs = controller.getAllDeviceConfigurations()
-            if not all_configs:
-                return None
-
-            for _devid, _devcfg in all_configs.items():
-                if _devcfg.get('uuid') == dev_uuid:
-                    devcfg = _devcfg.copy()
-                    devcfg['id'] = _devid
-                    return devcfg
-
-        return None
+        all_configs = controller.getAllDeviceConfigurations()
+        if not all_configs:
+            return None
+
+        dev_config = copy.deepcopy(dev_type_config[1])
+        for _devid, _devcfg in all_configs.items():
+            if _devcfg.get('uuid') == dev_uuid:
+                dev_config.update(_devcfg)
+                dev_config['id'] = _devid
+                return dev_config
+
+        return dev_config
                     
     def get_dev_xenapi_config(self, dev_class, dev_uuid):
         config = self.get_dev_config_by_uuid(dev_class, dev_uuid)
@@ -1770,10 +1787,11 @@ class XendDomainInfo:
             config['IO_bandwidth_incoming_kbs'] = 0.0
             config['IO_bandwidth_outgoing_kbs'] = 0.0
 
-        if dev_class == 'vbd':
+        if dev_class =='vbd':
             config['VDI'] = '' # TODO
             config['device'] = config.get('dev', '')
-            config['driver'] = config.get('uname', '')
+            config['driver'] = 'paravirtualised' # TODO
+            config['image'] = config.get('uname', '')
             config['IO_bandwidth_incoming_kbs'] = 0.0
             config['IO_bandwidth_outgoing_kbs'] = 0.0
             if config['mode'] == 'r':
@@ -1835,6 +1853,7 @@ class XendDomainInfo:
         @return: uuid of the device
         """
         xenapi_vbd['image'] = vdi_image_path
+        log.debug('create_vbd_with_vdi: %s' % xenapi_vbd)
         dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd)
         if not dev_uuid:
             raise XendError('Failed to create device')

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.