]> xenbits.xensource.com Git - xen.git/commitdiff
xend: pass-through: sxp.merge() cant deal with values being a list
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 16 Jun 2009 10:37:41 +0000 (11:37 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 16 Jun 2009 10:37:41 +0000 (11:37 +0100)
sxp.merge() can't deal with values being a list so instead
of storing pci options as:

[ 'opts', [ 'key1' 'value1'], [ 'key2', 'value2'], ...]

store them as:

[ 'opts', [ 'key1' 'value1'], ['opts', [ 'key2', 'value2']], ...

Signed-off-by: Simon Horman <horms@verge.net.au>
tools/python/xen/util/pci.py
tools/python/xen/xend/XendConfig.py
tools/python/xen/xend/server/pciif.py
tools/python/xen/xm/create.py
tools/python/xen/xm/main.py
tools/python/xen/xm/xenapi_create.py

index 536963463577b4b1c48c348f163ad5a14df5338a..9e7e534a33b31a98b19a49b8c21bb8579b4b8396 100644 (file)
@@ -118,14 +118,26 @@ def PCI_BDF(domain, bus, slot, func):
     return (((domain & 0xffff) << 16) | ((bus & 0xff) << 8) |
             PCI_DEVFN(slot, func))
 
+def check_pci_opts(opts):
+    def f((k, v)):
+        if k not in ['msitranslate', 'power_mgmt'] or \
+           not v.lower() in ['0', '1', 'yes', 'no']:
+            raise PciDeviceParseError('Invalid pci option %s=%s: ' % (k, v))
+
+    map(f, opts)
+
 def serialise_pci_opts(opts):
-    return reduce(lambda x, y: x+','+y, map(lambda (x, y): x+'='+y, opts))
+    return ','.join(map(lambda x: '='.join(x), opts))
 
 def split_pci_opts(opts):
-    return map(lambda x: x.split('='), opts.split(','))
+    return map(lambda x: x.split('='),
+               filter(lambda x: x != '', opts.split(',')))
 
 def pci_opts_list_to_sxp(list):
-    ['dev'] + map(lambda x: ['opts', x], list)
+    return ['dev'] + map(lambda x: ['opts', x], list)
+
+def pci_opts_list_from_sxp(dev):
+    return map(lambda x: sxp.children(x)[0], sxp.children(dev, 'opts'))
 
 def parse_hex(val):
     try:
index fd5dc6f9eb282164e85af117b45bd205419346c6..3b960c773a7568330dfc5063f145979c899f2c7a 100644 (file)
@@ -36,6 +36,7 @@ from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.server.BlktapController import blktap_disk_types
 from xen.xend.server.netif import randomMAC
 from xen.util.blkif import blkdev_name_to_number, blkdev_uname_to_file
+from xen.util.pci import pci_opts_list_from_sxp
 from xen.util import xsconstants
 import xen.util.auxbin
 
@@ -1605,11 +1606,10 @@ class XendConfig(dict):
         return ''
 
     def pci_convert_dict_to_sxp(self, dev, state, sub_state = None):
-        sxp =  ['pci', ['dev'] + map(lambda (x, y): [x, y], dev.items()),
-                ['state', state]]
+        pci_sxp = ['pci', self.dev_dict_to_sxp(dev), ['state', state]]
         if sub_state != None:
-            sxp.append(['sub_state', sub_state])
-        return sxp
+            pci_sxp.append(['sub_state', sub_state])
+        return pci_sxp
 
     def pci_convert_sxp_to_dict(self, dev_sxp):
         """Convert pci device sxp to dict
@@ -1658,13 +1658,9 @@ class XendConfig(dict):
 
         pci_devs = []
         for pci_dev in sxp.children(dev_sxp, 'dev'):
-            pci_dev_info = {}
-            for opt_val in pci_dev[1:]:
-                try:
-                    opt, val = opt_val
-                    pci_dev_info[opt] = val
-                except (TypeError, ValueError):
-                    pass
+            pci_dev_info = dict(pci_dev[1:])
+            if 'opts' in pci_dev_info:
+                pci_dev_info['opts'] = pci_opts_list_from_sxp(pci_dev)
             # append uuid to each pci device that does't already have one.
             if not pci_dev_info.has_key('uuid'):
                 dpci_uuid = pci_dev_info.get('uuid', uuid.createString())
@@ -1975,6 +1971,15 @@ class XendConfig(dict):
         result.extend([u for u in target['devices'].keys() if u not in result])
         return result
 
+    # This includes a generic equivalent of pci_opts_list_to_sxp()
+    def dev_dict_to_sxp(self, dev):
+        def f((key, val)):
+            if isinstance(val, types.ListType):
+                return map(lambda x: [key, x], val)
+            return [[key, val]]
+        dev_sxp = ['dev'] + reduce(lambda x, y: x + y, map(f, dev.items()))
+        return dev_sxp
+
     def all_devices_sxpr(self, target = None):
         """Returns the SXPR for all devices in the current configuration."""
         sxprs = []
@@ -1997,10 +2002,7 @@ class XendConfig(dict):
                     if dev_info.has_key('backend'):
                         sxpr.append(['backend', dev_info['backend']])
                 for pci_dev_info in dev_info['devs']:
-                    pci_dev_sxpr = ['dev']
-                    for opt, val in pci_dev_info.items():
-                        pci_dev_sxpr.append([opt, val])
-                    sxpr.append(pci_dev_sxpr)
+                    sxpr.append(self.dev_dict_to_sxp(pci_dev_info))
                 sxprs.append((dev_type, sxpr))
             else:
                 sxpr = self.device_sxpr(dev_type = dev_type,
@@ -2127,11 +2129,7 @@ class XendConfig(dict):
                 slot = sxp.child_value(dev, 'slot')
                 func = sxp.child_value(dev, 'func')
                 vslot = sxp.child_value(dev, 'vslot')
-                opts = ''
-                for opt in sxp.child_value(dev, 'opts', []):
-                    if opts:
-                        opts += ','
-                    opts += '%s=%s' % (opt[0], str(opt[1]))
+                opts = pci_opts_list_from_sxp(dev)
                 pci.append([domain, bus, slot, func, vslot, opts])
         self['platform']['pci'] = pci
 
index c660ba6cd5b529e98fd77dcf6aa7236fd6ffe5d6..0806905ea01ec172419c3d509215064b95d20701 100644 (file)
@@ -222,7 +222,8 @@ class PciController(DevController):
             dev_sxpr = ['dev']
             for dev_key, dev_val in dev.items():
                 if dev_key == 'opts':
-                    dev_sxpr.append(['opts', split_pci_opts(dev_val)])
+                    opts_sxpr = pci_opts_list_to_sxp(split_pci_opts(dev_val))
+                    dev_sxpr = sxp.merge(dev_sxpr, opts_sxpr)
                 else:
                     dev_sxpr.append([dev_key, dev_val])
             sxpr.append(dev_sxpr)
index 2d96e4aa82900b579813bc98684eb617ac2a2c6b..fd6286dfc4a3fef1609f829d45c81a9416c65242 100644 (file)
@@ -38,6 +38,8 @@ from xen.util import vscsi_util
 import xen.util.xsm.xsm as security
 from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
 from xen.util import utils, auxbin
+from xen.util.pci import split_pci_opts, check_pci_opts, \
+                         pci_opts_list_to_sxp
 
 from xen.xm.opts import *
 
@@ -706,23 +708,18 @@ def configure_pci(config_devs, vals):
     """
     config_pci = []
     for (domain, bus, slot, func, vslot, opts) in vals.pci:
-        config_pci_opts = []
-        d = comma_sep_kv_to_dict(opts)
-
-        def f(k):
-            if k not in ['msitranslate', 'power_mgmt']:
-                err('Invalid pci option: ' + k)
-
-            config_pci_opts.append([k, d[k]])
-
         config_pci_bdf = ['dev', ['domain', domain], ['bus', bus], \
                           ['slot', slot], ['func', func],
                           ['vslot', vslot]]
-        map(f, d.keys())
-        if len(config_pci_opts)>0:
-            config_pci_bdf.append(['opts', config_pci_opts])
 
-        config_pci.append(config_pci_bdf)
+        opts_list = split_pci_opts(opts)
+        try:
+            check_pci_opts(opts_list)
+        except PciDeviceParseError, ex:
+            err(str(ex))
+
+        config_opts = pci_opts_list_to_sxp(split_pci_opts(opts))
+        config_pci.append(sxp.merge(config_pci_bdf, config_opts))
 
     if len(config_pci)>0:
         config_pci.insert(0, 'pci')
index d14eabcc913bf150c3f434350d290664e7e6f243..515d937e612f3e1fc4dafffacf74b636be8adc43 100644 (file)
@@ -2507,12 +2507,15 @@ def parse_pci_configuration(args, state, opts = ''):
                 ['slot', '0x'+ pci_dev_info['slot']],
                 ['func', '0x'+ pci_dev_info['func']],
                 ['vslot', '0x%x' % int(vslot, 16)]]
-        if len(opts) > 0:
-            pci_bdf.append(['opts', opts])
-        pci.append(pci_bdf)
-
     except:
         raise OptionError("Invalid argument: %s %s" % (pci_dev_str, vslot))
+
+    try:
+        check_pci_opts(opts)
+    except PciDeviceParseError, ex:
+        raise OptionError(str(ex))
+
+    pci.append(sxp.merge(pci_bdf, pci_opts_list_to_sxp(opts)))
     pci.append(['state', state])
 
     return (dom, pci)
index 54e0cd665f77e9570cae8c5f38ee64ba459230c7..790a6149dd6bb7798bf29d0ffb6ebd7bcc5538c4 100644 (file)
@@ -26,6 +26,7 @@ from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
      XEN_API_ON_CRASH_BEHAVIOUR
 from xen.xm.opts import OptionError
 from xen.util import xsconstants
+from xen.util.pci import pci_opts_list_from_sxp
 from xen.util.path import SHAREDIR
 import xen.util.xsm.xsm as security
 
@@ -945,12 +946,11 @@ class sxp2xml:
                     = get_child_by_name(dev_sxp, "func", "0")
                 pci.attributes["vslot"] \
                     = get_child_by_name(dev_sxp, "vslot", "0")
-                for opt in get_child_by_name(dev_sxp, "opts", ""):
-                    if len(opt) > 0:
-                        pci_opt = document.createElement("pci_opt")
-                        pci_opt.attributes["key"] = opt[0]
-                        pci_opt.attributes["value"] = opt[1]
-                        pci.appendChild(pci_opt)
+                for opt in pci_opts_list_from_sxp(dev_sxp):
+                    pci_opt = document.createElement("pci_opt")
+                    pci_opt.attributes["key"] = opt[0]
+                    pci_opt.attributes["value"] = opt[1]
+                    pci.appendChild(pci_opt)
 
                 pcis.append(pci)