# HG changeset patch
# User john.levon@xxxxxxx
# Date 1181305288 25200
# Node ID b6e22518c35a85e708a62ac526daeb18d16f28a2
# Parent 286d8ec9ccf4082b8db0a17a8ab74ad32a2bf218
Make device detach wait for detach to complete.
*-detach will wait till device is detached or time'ed out.
XendConfig will be updated, if detached.
Signed-off-by: Max Zhen <max.zhen@xxxxxxx>
diff --git a/tools/python/xen/xend/XendConfig.py
b/tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -1274,6 +1274,21 @@ class XendConfig(dict):
return False
+ def device_remove(self, dev_uuid):
+ """Remove an existing device referred by dev_uuid.
+ """
+
+ if dev_uuid in self['devices']:
+ dev_config = self['devices'].get(dev_uuid)
+ dev_type = dev_config[0]
+
+ del self['devices'][dev_uuid]
+ # Remove dev references for certain device types (see device_add)
+ if dev_type in ('vif', 'vbd', 'vtpm'):
+ param = '%s_refs' % dev_type
+ if param in self:
+ if dev_uuid in self[param]:
+ self[param].remove(dev_uuid)
def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None):
"""Get Device SXPR by either giving the device UUID or (type, config).
diff --git a/tools/python/xen/xend/XendDomainInfo.py
b/tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -569,8 +569,25 @@ class XendDomainInfo:
if not found:
log.debug("Could not find the device %s", devid)
return None
+
log.debug("devid = %s", devid)
- return self.getDeviceController(deviceClass).destroyDevice(devid,
force)
+
+ dev_control = self.getDeviceController(deviceClass)
+ dev_uuid = dev_control.readBackend(devid, 'uuid')
+
+ ret = None
+
+ try:
+ ret = dev_control.destroyDevice(devid, force)
+ except EnvironmentError:
+ # We failed to detach the device
+ raise VmError("Failed to detach device %d" % devid)
+
+ # update XendConfig
+ if dev_uuid:
+ self.info.device_remove(dev_uuid)
+
+ return ret
def getDeviceSxprs(self, deviceClass):
if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
@@ -583,7 +600,6 @@ class XendDomainInfo:
sxprs.append([dev_num, dev_info])
dev_num += 1
return sxprs
-
def setMemoryTarget(self, target):
"""Set the memory target of this domain.
diff --git a/tools/python/xen/xend/server/DevController.py
b/tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py
+++ b/tools/python/xen/xend/server/DevController.py
@@ -29,6 +29,7 @@ import os
import os
DEVICE_CREATE_TIMEOUT = 100
+DEVICE_DESTROY_TIMEOUT = 10
HOTPLUG_STATUS_NODE = "hotplug-status"
HOTPLUG_ERROR_NODE = "hotplug-error"
HOTPLUG_STATUS_ERROR = "error"
@@ -211,17 +212,34 @@ class DevController:
devid = int(devid)
+ frontpath = self.frontendPath(devid)
+ if frontpath:
+ backpath = xstransact.Read(frontpath, "backend")
+
# Modify online status /before/ updating state (latter is watched by
# drivers, so this ordering avoids a race).
self.writeBackend(devid, 'online', "0")
self.writeBackend(devid, 'state', str(xenbusState['Closing']))
if force:
- frontpath = self.frontendPath(devid)
- backpath = xstransact.Read(frontpath, "backend")
if backpath:
xstransact.Remove(backpath)
- xstransact.Remove(frontpath)
+ if frontpath:
+ xstransact.Remove(frontpath)
+ return
+
+ # Wait till both frontpath and backpath are removed from
+ # xenstore, or timed out
+ if frontpath:
+ status = self.waitUntilDestroyed(frontpath)
+ if status == Timeout:
+ # Exception will be caught by destroyDevice in XendDomainInfo.py
+ raise EnvironmentError
+ if backpath:
+ status = self.waitUntilDestroyed(backpath)
+ if status == Timeout:
+ # Exception will be caught by destroyDevice in XendDomainInfo.py
+ raise EnvironmentError
self.vm._removeVm("device/%s/%d" % (self.deviceClass, devid))
@@ -508,6 +526,16 @@ class DevController:
return (Missing, None)
+ def waitUntilDestroyed(self, path):
+ ev = Event()
+ result = { 'path': path, 'status': Timeout }
+
+ xswatch(path, destroyCallback, ev, result)
+
+ ev.wait(DEVICE_DESTROY_TIMEOUT)
+ return result['status']
+
+
def backendPath(self, backdom, devid):
"""Construct backend path given the backend domain and device id.
@@ -537,6 +565,18 @@ class DevController:
self.deviceClass)
+def destroyCallback(devPath, ev, result):
+ log.debug("destroyCallback %s.", devPath)
+
+ list = xstransact.List(result['path'])
+ if list:
+ return 1
+
+ result['status'] = Missing
+ ev.set()
+ log.debug("destroyCallback %s is destroyed", result['path'])
+ return 0
+
def hotplugStatusCallback(statusPath, ev, result):
log.debug("hotplugStatusCallback %s.", statusPath)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|