# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1181553671 -3600
# Node ID 31ee1768e911336c227d13fd1519961d07cdc562
# Parent 6f06bd06ef473726b4132e6fe95309fce6963fd5
xend: 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>
---
tools/python/xen/xend/XendConfig.py | 15 ++++++++
tools/python/xen/xend/XendDomainInfo.py | 19 +++++++++-
tools/python/xen/xend/server/DevController.py | 46 ++++++++++++++++++++++++--
3 files changed, 75 insertions(+), 5 deletions(-)
diff -r 6f06bd06ef47 -r 31ee1768e911 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Mon Jun 11 10:16:54 2007 +0100
+++ b/tools/python/xen/xend/XendConfig.py Mon Jun 11 10:21:11 2007 +0100
@@ -1268,6 +1268,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 -r 6f06bd06ef47 -r 31ee1768e911 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Mon Jun 11 10:16:54 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py Mon Jun 11 10:21:11 2007 +0100
@@ -557,7 +557,23 @@ class XendDomainInfo:
return None
log.debug("dev = %s", dev)
- return self.getDeviceController(deviceClass).destroyDevice(dev, force)
+
+ dev_control = self.getDeviceController(deviceClass)
+ dev_uuid = dev_control.readBackend(dev, 'uuid')
+
+ ret = None
+
+ try:
+ ret = dev_control.destroyDevice(dev, force)
+ except EnvironmentError:
+ # We failed to detach the device
+ raise VmError("Failed to detach device %d" % dev)
+
+ # 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):
@@ -570,7 +586,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 -r 6f06bd06ef47 -r 31ee1768e911
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py Mon Jun 11 10:16:54
2007 +0100
+++ b/tools/python/xen/xend/server/DevController.py Mon Jun 11 10:21:11
2007 +0100
@@ -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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|