WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] XenAPI: Add Direct PCI Device (DPCI) Assi

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] XenAPI: Add Direct PCI Device (DPCI) Assignment Support
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 03 Jul 2008 06:30:20 -0700
Delivery-date: Thu, 03 Jul 2008 06:31:11 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1215077232 -3600
# Node ID 52a388ec09f852ffd7e42a71593c63f21a7b9fad
# Parent  e65fe28b52887ffe61750474835cbd0afe8ccd48
XenAPI: Add Direct PCI Device (DPCI) Assignment Support

Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@xxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendAPI.py        |    9 +
 tools/python/xen/xend/XendConfig.py     |  159 ++++++++++++++++++++++-------
 tools/python/xen/xend/XendDPCI.py       |  154 ++++++++++++++++++++++++++++
 tools/python/xen/xend/XendDomain.py     |    3 
 tools/python/xen/xend/XendDomainInfo.py |  171 +++++++++++++++++++++++---------
 tools/python/xen/xend/XendError.py      |   11 ++
 tools/python/xen/xend/server/pciif.py   |   12 ++
 7 files changed, 435 insertions(+), 84 deletions(-)

diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Thu Jul 03 10:26:16 2008 +0100
+++ b/tools/python/xen/xend/XendAPI.py  Thu Jul 03 10:27:12 2008 +0100
@@ -41,6 +41,7 @@ from XendPIF import XendPIF
 from XendPIF import XendPIF
 from XendPBD import XendPBD
 from XendPPCI import XendPPCI
+from XendDPCI import XendDPCI
 from XendXSPolicy import XendXSPolicy, XendACMPolicy
 
 from XendAPIConstants import *
@@ -479,6 +480,7 @@ classes = {
     'PBD'          : valid_object("PBD"),
     'PIF_metrics'  : valid_object("PIF_metrics"),
     'PPCI'         : valid_object("PPCI"),
+    'DPCI'         : valid_object("DPCI")
 }
 
 autoplug_classes = {
@@ -488,6 +490,7 @@ autoplug_classes = {
     'PBD'         : XendPBD,
     'PIF_metrics' : XendPIFMetrics,
     'PPCI'        : XendPPCI,
+    'DPCI'        : XendDPCI,
     'XSPolicy'    : XendXSPolicy,
     'ACMPolicy'   : XendACMPolicy,
 }
@@ -1154,6 +1157,7 @@ class XendAPI(object):
                   'VIFs',
                   'VBDs',
                   'VTPMs',
+                  'DPCIs',
                   'tools_version',
                   'domid',
                   'is_control_domain',
@@ -1296,6 +1300,10 @@ class XendAPI(object):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return xen_api_success(dom.get_consoles())
 
+    def VM_get_DPCIs(self, session, vm_ref):
+        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        return xen_api_success(dom.get_dpcis())
+    
     def VM_get_tools_version(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return dom.get_tools_version()
@@ -1675,6 +1683,7 @@ class XendAPI(object):
             'VIFs': xeninfo.get_vifs(),
             'VBDs': xeninfo.get_vbds(),
             'VTPMs': xeninfo.get_vtpms(),
+            'DPCIs': xeninfo.get_dpcis(),
             'PV_bootloader': xeninfo.info.get('PV_bootloader'),
             'PV_kernel': xeninfo.info.get('PV_kernel'),
             'PV_ramdisk': xeninfo.info.get('PV_ramdisk'),
diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Thu Jul 03 10:26:16 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Thu Jul 03 10:27:12 2008 +0100
@@ -24,6 +24,8 @@ from xen.xend import uuid
 from xen.xend import uuid
 from xen.xend import XendOptions
 from xen.xend import XendAPIStore
+from xen.xend.XendPPCI import XendPPCI
+from xen.xend.XendDPCI import XendDPCI
 from xen.xend.XendError import VmError
 from xen.xend.XendDevices import XendDevices
 from xen.xend.PrettyPrint import prettyprintstring
@@ -773,6 +775,11 @@ class XendConfig(dict):
         """
         log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg))
 
+        # _parse_sxp() below will call device_add() and construct devices.
+        # Some devices (currently only pci) may require VM's uuid, so
+        # setup self['uuid'] beforehand.
+        self['uuid'] = sxp.child_value(sxp_cfg, 'uuid', uuid.createString())
+
         cfg = self._parse_sxp(sxp_cfg)
 
         for key, typ in XENAPI_CFG_TYPES.items():
@@ -1209,42 +1216,35 @@ class XendConfig(dict):
             dev_type = sxp.name(config)
             dev_info = {}
 
-            # Parsing the device SXP's. In most cases, the SXP looks
-            # like this:
-            #
-            # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]]
-            #
-            # However, for PCI devices it looks like this:
-            #
-            # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1]]]]
-            #
-            # It seems the reasoning for this difference is because
-            # pciif.py needs all the PCI device configurations at
-            # the same time when creating the devices.
-            #
-            # To further complicate matters, Xen 2.0 configuration format
-            # uses the following for pci device configuration:
-            #
-            # [device, [pci, [domain, 0], [bus, 0], [dev, 1], [func, 2]]]
-
             if dev_type == 'pci':
                 pci_devs_uuid = sxp.child_value(config, 'uuid',
                                                 uuid.createString())
-                pci_devs = []
-                for pci_dev in sxp.children(config, 'dev'):
-                    pci_dev_info = {}
-                    for opt_val in pci_dev[1:]:
-                        try:
-                            opt, val = opt_val
-                            pci_dev_info[opt] = val
-                        except TypeError:
-                            pass
-                    pci_devs.append(pci_dev_info)
+
+                pci_dict = self.pci_convert_sxp_to_dict(config)
+                pci_devs = pci_dict['devs']
+
+                # create XenAPI DPCI objects.
+                for pci_dev in pci_devs:
+                    dpci_uuid = pci_dev.get('uuid')
+                    ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
+                                                    pci_dev['bus'],
+                                                    pci_dev['slot'],
+                                                    pci_dev['func'])
+                    if ppci_uuid is None:
+                        continue
+                    dpci_record = {
+                        'VM': self['uuid'],
+                        'PPCI': ppci_uuid,
+                        'hotplug_slot': pci_dev.get('vslot', 0)
+                    }
+                    XendDPCI(dpci_uuid, dpci_record)
+                    
                 target['devices'][pci_devs_uuid] = (dev_type,
                                                     {'devs': pci_devs,
                                                      'uuid': pci_devs_uuid})
 
                 log.debug("XendConfig: reading device: %s" % pci_devs)
+
                 return pci_devs_uuid
 
             for opt_val in config[1:]:
@@ -1482,6 +1482,76 @@ class XendConfig(dict):
 
         return ''
 
+    def pci_convert_sxp_to_dict(self, dev_sxp):
+        """Convert pci device sxp to dict
+        @param dev_sxp: device configuration
+        @type  dev_sxp: SXP object (parsed config)
+        @return: dev_config
+        @rtype: dictionary
+        """
+        # Parsing the device SXP's. In most cases, the SXP looks
+        # like this:
+        #
+        # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]]
+        #
+        # However, for PCI devices it looks like this:
+        #
+        # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1], [func, 2]]]
+        #
+        # It seems the reasoning for this difference is because
+        # pciif.py needs all the PCI device configurations at
+        # the same time when creating the devices.
+        #
+        # To further complicate matters, Xen 2.0 configuration format
+        # uses the following for pci device configuration:
+        #
+        # [device, [pci, [domain, 0], [bus, 0], [dev, 1], [func, 2]]]
+
+        # For PCI device hotplug support, the SXP of PCI devices is
+        # extendend like this:
+        #
+        # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1], [func, 2],
+        #                      [vslt, 0]],
+        #                [state, 'Initialising']]]
+        #
+        # 'vslt' shows the virtual hotplug slot number which the PCI device
+        # is inserted in. This is only effective for HVM domains.
+        #
+        # state 'Initialising' indicates that the device is being attached,
+        # while state 'Closing' indicates that the device is being detached.
+        #
+        # The Dict looks like this:
+        #
+        # { devs: [{domain: 0, bus: 0, slot: 1, func: 2, vslt: 0}],
+        #   states: ['Initialising'] }
+
+        dev_config = {}
+
+        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:
+                    pass
+                # append uuid for each pci device.
+                dpci_uuid = pci_dev_info.get('uuid', uuid.createString())
+                pci_dev_info['uuid'] = dpci_uuid
+            pci_devs.append(pci_dev_info)
+        dev_config['devs'] = pci_devs 
+
+        pci_states = []
+        for pci_state in sxp.children(dev_sxp, 'state'):
+            try:
+                pci_states.append(pci_state[1])
+            except IndexError:
+                raise XendError("Error reading state while parsing pci sxp")
+        dev_config['states'] = pci_states
+
+        return dev_config
+
     def console_add(self, protocol, location, other_config = {}):
         dev_uuid = uuid.createString()
         if protocol == 'vt100':
@@ -1556,16 +1626,29 @@ class XendConfig(dict):
             dev_type, dev_info = self['devices'][dev_uuid]
 
             if dev_type == 'pci': # Special case for pci
-                pci_devs = []
-                for pci_dev in sxp.children(config, 'dev'):
-                    pci_dev_info = {}
-                    for opt_val in pci_dev[1:]:
-                        try:
-                            opt, val = opt_val
-                            pci_dev_info[opt] = val
-                        except TypeError:
-                            pass
-                    pci_devs.append(pci_dev_info)
+                pci_dict = self.pci_convert_sxp_to_dict(config)
+                pci_devs = pci_dict['devs']
+
+                # destroy existing XenAPI DPCI objects
+                for dpci_uuid in XendDPCI.get_by_VM(self['uuid']):
+                    XendAPIStore.deregister(dpci_uuid, "DPCI")
+
+                # create XenAPI DPCI objects.
+                for pci_dev in pci_devs:
+                    dpci_uuid = pci_dev.get('uuid')
+                    ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'],
+                                                     pci_dev['bus'],
+                                                     pci_dev['slot'],
+                                                     pci_dev['func'])
+                    if ppci_uuid is None:
+                        continue
+                    dpci_record = {
+                        'VM': self['uuid'],
+                        'PPCI': ppci_uuid,
+                        'hotplug_slot': pci_dev.get('vslot', 0)
+                    }
+                    XendDPCI(dpci_uuid, dpci_record)
+
                 self['devices'][dev_uuid] = (dev_type,
                                              {'devs': pci_devs,
                                               'uuid': dev_uuid})
diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/XendDPCI.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/XendDPCI.py Thu Jul 03 10:27:12 2008 +0100
@@ -0,0 +1,154 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (c) 2008 NEC Corporation
+#       Yosuke Iwamatsu <y-iwamatsu at ab jp nec com>
+#============================================================================
+
+from xen.xend.XendBase import XendBase
+from xen.xend.XendPPCI import XendPPCI
+from xen.xend import XendAPIStore
+from xen.xend import uuid as genuuid
+
+import XendDomain, XendNode
+
+from XendError import *
+from XendTask import XendTask
+from XendLogging import log
+
+class XendDPCI(XendBase):
+    """Representation of a passthrough PCI device."""
+
+    def getClass(self):
+        return "DPCI"
+
+    def getAttrRO(self):
+        attrRO = ['virtual_domain',
+                  'virtual_bus',
+                  'virtual_slot',
+                  'virtual_func',
+                  'virtual_name',
+                  'VM',
+                  'PPCI',
+                  'hotplug_slot']
+        return XendBase.getAttrRO() + attrRO
+
+    def getAttrRW(self):
+        attrRW = []
+        return XendBase.getAttrRW() + attrRW
+
+    def getAttrInst(self):
+        attrInst = ['VM',
+                    'PPCI',
+                    'hotplug_slot']
+        return XendBase.getAttrInst() + attrInst
+
+    def getMethods(self):
+        methods = ['destroy']
+        return XendBase.getMethods() + methods
+
+    def getFuncs(self):
+        funcs = ['create']
+        return XendBase.getFuncs() + funcs
+
+    getClass    = classmethod(getClass)
+    getAttrRO   = classmethod(getAttrRO)
+    getAttrRW   = classmethod(getAttrRW)
+    getAttrInst = classmethod(getAttrInst)
+    getMethods  = classmethod(getMethods)
+    getFuncs    = classmethod(getFuncs)
+ 
+    def create(self, dpci_struct):
+
+        # Check if VM is valid
+        xendom = XendDomain.instance()
+        if not xendom.is_valid_vm(dpci_struct['VM']):
+            raise InvalidHandleError('VM', dpci_struct['VM'])
+        dom = xendom.get_vm_by_uuid(dpci_struct['VM'])
+
+        # Check if PPCI is valid
+        xennode = XendNode.instance()
+        ppci_uuid = xennode.get_ppci_by_uuid(dpci_struct['PPCI'])
+        if not ppci_uuid:
+            raise InvalidHandleError('PPCI', dpci_struct['PPCI'])
+        for existing_dpci in XendAPIStore.get_all('DPCI'):
+            if ppci_uuid == existing_dpci.get_PPCI():
+                raise DirectPCIError("Device is in use")
+
+        # Assign PPCI to VM
+        try:
+            dpci_ref = XendTask.log_progress(0, 100, dom.create_dpci,
+                                             dpci_struct)
+        except XendError, e:
+            raise DirectPCIError("Failed to assign device")
+
+        # TODO: Retrive virtual pci device infomation.
+
+        return dpci_ref
+
+    create = classmethod(create)
+
+    def get_by_VM(cls, VM_ref):
+        result = []
+        for dpci in XendAPIStore.get_all("DPCI"):
+            if dpci.get_VM() == VM_ref:
+                result.append(dpci.get_uuid())
+        return result
+
+    get_by_VM = classmethod(get_by_VM)
+
+    def __init__(self, uuid, record):
+        XendBase.__init__(self, uuid, record)
+
+        self.virtual_domain = -1
+        self.virtual_bus = -1
+        self.virtual_slot = -1
+        self.virtual_func = -1
+
+        self.VM = record['VM']
+        self.PPCI = record['PPCI']
+        self.hotplug_slot = record['hotplug_slot']
+
+    def destroy(self):
+        xendom = XendDomain.instance()
+        dom = xendom.get_vm_by_uuid(self.get_VM())
+        if not dom:
+            raise InvalidHandleError("VM", self.get_VM())
+        XendTask.log_progress(0, 100, dom.destroy_dpci, self.get_uuid())
+
+    def get_virtual_domain(self):
+        return self.virtual_domain
+
+    def get_virtual_bus(self):
+        return self.virtual_bus
+
+    def get_virtual_slot(self):
+        return self.virtual_slot
+
+    def get_virtual_func(self):
+        return self.virtual_func
+
+    def get_virtual_name(self):
+        return "%04x:%02x:%02x.%01x" % (self.virtual_domain, self.virtual_bus,
+                                        self.virtual_slot, self.virtual_func)
+
+    def get_VM(self):
+        return self.VM
+
+    def get_PPCI(self):
+        return self.PPCI
+
+    def get_hotplug_slot(self):
+        return self.hotplug_slot
+
diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Thu Jul 03 10:26:16 2008 +0100
+++ b/tools/python/xen/xend/XendDomain.py       Thu Jul 03 10:27:12 2008 +0100
@@ -478,6 +478,8 @@ class XendDomain:
             
             if domid in self.domains:
                 del self.domains[domid]
+
+            info.destroy_xapi_device_instances()
         else:
             log.warning("Attempted to remove non-existent domain.")
 
@@ -1091,6 +1093,7 @@ class XendDomain:
         self._managed_domain_unregister(dominfo)
         self._remove_domain(dominfo)
         XendDevices.destroy_device_state(dominfo)
+        dominfo.destroy_xapi_device_instances()
 
 
     def domain_configure(self, config):
diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Jul 03 10:26:16 2008 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Jul 03 10:27:12 2008 +0100
@@ -54,6 +54,10 @@ from xen.xend.XendAPIConstants import *
 from xen.xend.XendAPIConstants import *
 
 from xen.xend.XendVMMetrics import XendVMMetrics
+
+from xen.xend.XendPPCI import XendPPCI
+from xen.xend.XendDPCI import XendDPCI
+from xen.xend import XendAPIStore
 
 MIGRATE_TIMEOUT = 30.0
 BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
@@ -642,50 +646,7 @@ class XendDomainInfo:
         xen.xend.XendDomain.instance().managed_config_save(self)
         return self.getDeviceController(dev_type).sxpr(devid)
 
-    def pci_convert_sxp_to_dict(self, dev_sxp):
-        """Convert pci device sxp to dict
-        @param dev_sxp: device configuration
-        @type  dev_sxp: SXP object (parsed config)
-        @return: dev_config
-        @rtype: dictionary
-        """
-        # In reconfigure phase, config of PCI device looks like below:
-        #
-        # sxp:
-        # [device, [pci, [dev, [domain, '0x0'], [bus, '0x0'], [slot, '0x0'],
-        #                      [func, '0x0'], [vslt, '0x0']],
-        #                [state, 'Initialising']]]
-        #
-        # dict:
-        # {devs: [{domain: '0x0', bus: '0x0', slot: '0x0', func: '0x0',
-        #          vslt: '0x0'}],
-        #  states: ['Initialising']}
-        #
-        # state 'Initialising' means the device is being attached.
-        # state 'Closing' means the device is being detached.
-
-        dev_config = {}
-        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:
-                    pass
-            pci_devs.append(pci_dev_info)
-        dev_config['devs'] = pci_devs 
-        pci_states = []
-        for pci_state in sxp.children(dev_sxp, 'state'):
-            try:
-                pci_states.append(pci_state[1])
-            except IndexError:
-                raise XendError("Error reading state while parsing pci sxp")
-        dev_config['states'] = pci_states
-        
-        return dev_config
- 
+
     def pci_device_configure(self, dev_sxp, devid = 0):
         """Configure an existing pci device.
         
@@ -711,7 +672,7 @@ class XendDomainInfo:
             raise XendError("Cannot detach when pci platform does not exist")
 
         pci_dev = sxp.children(dev_sxp, 'dev')[0]
-        dev_config = self.pci_convert_sxp_to_dict(dev_sxp)
+        dev_config = self.info.pci_convert_sxp_to_dict(dev_sxp)
         dev = dev_config['devs'][0]
                 
         # Do HVM specific processing
@@ -785,6 +746,8 @@ class XendDomainInfo:
                 self.destroyDevice('pci', devid)
                 del self.info['devices'][dev_uuid]
 
+        xen.xend.XendDomain.instance().managed_config_save(self)
+
         return True
 
     def device_configure(self, dev_sxp, devid = None):
@@ -3169,6 +3132,9 @@ class XendDomainInfo:
     def get_vtpms(self):
         return self.info.get('vtpm_refs', [])
 
+    def get_dpcis(self):
+        return XendDPCI.get_by_VM(self.info.get('uuid'))
+
     def create_vbd(self, xenapi_vbd, vdi_image_path):
         """Create a VBD using a VDI from XendStorageRepository.
 
@@ -3291,6 +3257,64 @@ class XendDomainInfo:
 
     def set_console_other_config(self, console_uuid, other_config):
         self.info.console_update(console_uuid, 'other_config', other_config)
+
+    def create_dpci(self, xenapi_pci):
+        """Create pci device from the passed struct in Xen API format.
+
+        @param xenapi_pci: DPCI struct from Xen API
+        @rtype: bool
+        #@rtype: string
+        @return: True if successfully created device
+        #@return: UUID
+        """
+
+        dpci_uuid = uuid.createString()
+
+        # Convert xenapi to sxp
+        ppci = XendAPIStore.get(xenapi_pci.get('PPCI'), 'PPCI')
+
+        target_pci_sxp = \
+            ['pci', 
+                ['dev',
+                    ['domain', '0x%02x' % ppci.get_domain()],
+                    ['bus', '0x%02x' % ppci.get_bus()],
+                    ['slot', '0x%02x' % ppci.get_slot()],
+                    ['func', '0x%1x' % ppci.get_func()],
+                    ['vslt', '0x%02x' % xenapi_pci.get('hotplug_slot')],
+                    ['uuid', dpci_uuid]
+                ],
+                ['state', 'Initialising']
+            ]
+
+        if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
+
+            old_pci_sxp = self._getDeviceInfo_pci(0)
+
+            if old_pci_sxp is None:
+                dev_uuid = self.info.device_add('pci', cfg_sxp = 
target_pci_sxp)
+                if not dev_uuid:
+                    raise XendError('Failed to create device')
+
+            else:
+                new_pci_sxp = ['pci']
+                for existing_dev in sxp.children(old_pci_sxp, 'dev'):
+                    new_pci_sxp.append(existing_dev)
+                new_pci_sxp.append(sxp.child0(target_pci_sxp, 'dev'))
+
+                dev_uuid = sxp.child_value(old_pci_sxp, 'uuid')
+                self.info.device_update(dev_uuid, new_pci_sxp)
+
+            xen.xend.XendDomain.instance().managed_config_save(self)
+
+        else:
+            try:
+                self.device_configure(target_pci_sxp)
+
+            except Exception, exn:
+                raise XendError('Failed to create device')
+
+        return dpci_uuid
+
 
     def destroy_device_by_uuid(self, dev_type, dev_uuid):
         if dev_uuid not in self.info['devices']:
@@ -3318,6 +3342,63 @@ class XendDomainInfo:
 
     def destroy_vtpm(self, dev_uuid):
         self.destroy_device_by_uuid('vtpm', dev_uuid)
+
+    def destroy_dpci(self, dev_uuid):
+
+        dpci = XendAPIStore.get(dev_uuid, 'DPCI')
+        ppci = XendAPIStore.get(dpci.get_PPCI(), 'PPCI')
+
+        old_pci_sxp = self._getDeviceInfo_pci(0)
+        dev_uuid = sxp.child_value(old_pci_sxp, 'uuid')
+        target_dev = None
+        new_pci_sxp = ['pci']
+        for dev in sxp.children(old_pci_sxp, 'dev'):
+            domain = int(sxp.child_value(dev, 'domain'), 16)
+            bus = int(sxp.child_value(dev, 'bus'), 16)
+            slot = int(sxp.child_value(dev, 'slot'), 16)
+            func = int(sxp.child_value(dev, 'func'), 16)
+            name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
+            if ppci.get_name() == name:
+                target_dev = dev
+            else:
+                new_pci_sxp.append(dev)
+
+        if target_dev is None:
+            raise XendError('Failed to destroy device')
+
+        target_pci_sxp = ['pci', target_dev, ['state', 'Closing']]
+
+        if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
+
+            self.info.device_update(dev_uuid, new_pci_sxp)
+            if len(sxp.children(new_pci_sxp, 'dev')) == 0:
+                del self.info['devices'][dev_uuid]
+            xen.xend.XendDomain.instance().managed_config_save(self)
+
+        else:
+            try:
+                self.device_configure(target_pci_sxp)
+
+            except Exception, exn:
+                raise XendError('Failed to destroy device')
+
+    def destroy_xapi_device_instances(self):
+        """Destroy Xen-API device instances stored in XendAPIStore.
+        """
+        # Xen-API classes based on XendBase have their instances stored
+        # in XendAPIStore. Cleanup these virtual device instances here
+        # if they are supposed to be destroyed when the parent domain is dead.
+        #
+        # Most of the virtual devices (vif, vbd, vfb, etc) are not based on
+        # XendBase and there's no need to remove them from XendAPIStore.
+
+        from xen.xend import XendDomain
+        if XendDomain.instance().is_valid_vm(self.info.get('uuid')):
+            # domain still exists.
+            return
+
+        for dpci_uuid in XendDPCI.get_by_VM(self.info.get('uuid')):
+            XendAPIStore.deregister(dpci_uuid, "DPCI")
             
     def has_device(self, dev_class, dev_uuid):
         return (dev_uuid in self.info['%s_refs' % dev_class.lower()])
diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/XendError.py
--- a/tools/python/xen/xend/XendError.py        Thu Jul 03 10:26:16 2008 +0100
+++ b/tools/python/xen/xend/XendError.py        Thu Jul 03 10:27:12 2008 +0100
@@ -174,6 +174,17 @@ class NetworkError(XendAPIError):
 
     def __str__(self):
         return 'NETWORK_ERROR: %s %s' % (self.error, self.network)
+
+class DirectPCIError(XendAPIError):
+    def __init__(self, error):
+        XendAPIError.__init__(self)
+        self.error = error
+
+    def get_api_error(self):
+        return ['DIRECT_PCI_ERROR', self.error]
+
+    def __str__(self):
+        return 'DIRECT_PCI_ERROR: %s' % self.error
 
 from xen.util.xsconstants import xserr2string
 
diff -r e65fe28b5288 -r 52a388ec09f8 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py     Thu Jul 03 10:26:16 2008 +0100
+++ b/tools/python/xen/xend/server/pciif.py     Thu Jul 03 10:27:12 2008 +0100
@@ -76,6 +76,7 @@ class PciController(DevController):
 
             back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%02x" % \
                                         (domain, bus, slot, func)
+            back['uuid-%i' % pcidevid] = pci_config.get('uuid', '')
             pcidevid += 1
 
         if vslots != "":
@@ -101,6 +102,7 @@ class PciController(DevController):
             try:
                 dev = back['dev-%i' % i]
                 state = states[i]
+                uuid = back['uuid-%i' %i]
             except:
                 raise XendError('Error reading config')
 
@@ -121,6 +123,7 @@ class PciController(DevController):
                 self.writeBackend(devid, 'dev-%i' % (num_olddevs + i), dev)
                 self.writeBackend(devid, 'state-%i' % (num_olddevs + i),
                                   str(xenbusState['Initialising']))
+                self.writeBackend(devid, 'uuid-%i' % (num_olddevs + i), uuid)
                 self.writeBackend(devid, 'num_devs', str(num_olddevs + i + 1))
 
                 # Update vslots
@@ -141,7 +144,7 @@ class PciController(DevController):
                     raise XendError('Device %s is not connected' % dev)
 
                 # Update vslots
-                if back['vslots'] is not None:
+                if back.get('vslots') is not None:
                     vslots = old_vslots
                     for vslt in back['vslots'].split(';'):
                         if vslt != '':
@@ -185,6 +188,9 @@ class PciController(DevController):
                                  'bus': '0x%(bus)s' % pci_dev_info,
                                  'slot': '0x%(slot)s' % pci_dev_info,
                                  'func': '0x%(func)s' % pci_dev_info}
+
+                # Per device uuid info
+                dev_dict['uuid'] = self.readBackend(devid, 'uuid-%d' % i)
 
                 #append vslot info
                 if vslots is not None:
@@ -442,6 +448,7 @@ class PciController(DevController):
                 self.removeBackend(devid, 'dev-%i' % i)
                 self.removeBackend(devid, 'vdev-%i' % i)
                 self.removeBackend(devid, 'state-%i' % i)
+                self.removeBackend(devid, 'uuid-%i' % i)
             else:
                 if new_num_devs != i:
                     tmpdev = self.readBackend(devid, 'dev-%i' % i)
@@ -455,6 +462,9 @@ class PciController(DevController):
                     tmpstate = self.readBackend(devid, 'state-%i' % i)
                     self.writeBackend(devid, 'state-%i' % new_num_devs, 
tmpstate)
                     self.removeBackend(devid, 'state-%i' % i)
+                    tmpuuid = self.readBackend(devid, 'uuid-%i' % i)
+                    self.writeBackend(devid, 'uuid-%i' % new_num_devs, tmpuuid)
+                    self.removeBackend(devid, 'uuid-%i' % i)
                 new_num_devs = new_num_devs + 1
 
         self.writeBackend(devid, 'num_devs', str(new_num_devs))

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] XenAPI: Add Direct PCI Device (DPCI) Assignment Support, Xen patchbot-unstable <=