# 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
|