[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Fix xm block/network-detach command.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1186672901 -3600
# Node ID 95f90f24f3b1f33f911d3e9a01cb1d7bce5b29e0
# Parent  f0298301ba8b34ac3e5470cf953a3591f7730d26
Fix xm block/network-detach command.

 - To remove device info, it waits for the backend path of the device
   to be removed.
 - It removes device info from domain info.
 - It saves domain info to the config.sxp of the managed domain.

Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
---
 tools/python/xen/xend/XendDomainInfo.py       |   82 +++++++++++++++++++++++++-
 tools/python/xen/xend/server/DevController.py |   71 ++++++++++++++++++----
 tools/python/xen/xend/server/blkif.py         |   18 ++++-
 tools/python/xen/xm/main.py                   |    3 
 4 files changed, 155 insertions(+), 19 deletions(-)

diff -r f0298301ba8b -r 95f90f24f3b1 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Aug 09 16:14:56 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Aug 09 16:21:41 2007 +0100
@@ -558,9 +558,64 @@ class XendDomainInfo:
         for devclass in XendDevices.valid_devices():
             self.getDeviceController(devclass).waitForDevices()
 
-    def destroyDevice(self, deviceClass, devid, force = False):
-        log.debug("dev = %s", devid)
-        return self.getDeviceController(deviceClass).destroyDevice(devid, 
force)
+    def destroyDevice(self, deviceClass, devid, force = False, rm_cfg = False):
+        log.debug("XendDomainInfo.destroyDevice: deviceClass = %s, device = 
%s",
+                  deviceClass, devid)
+
+        if rm_cfg:
+            # Convert devid to device number.  A device number is
+            # needed to remove its configuration.
+            dev = 
self.getDeviceController(deviceClass).convertToDeviceNumber(devid)
+            
+            # Save current sxprs.  A device number and a backend
+            # path are needed to remove its configuration but sxprs
+            # do not have those after calling destroyDevice.
+            sxprs = self.getDeviceSxprs(deviceClass)
+
+        rc = None
+        if self.domid is not None:
+            rc = self.getDeviceController(deviceClass).destroyDevice(devid, 
force)
+            if not force and rm_cfg:
+                # The backend path, other than the device itself,
+                # has to be passed because its accompanied frontend
+                # path may be void until its removal is actually
+                # issued.  It is probable because destroyDevice is
+                # issued first.
+                for dev_num, dev_info in sxprs:
+                    dev_num = int(dev_num)
+                    if dev_num == dev:
+                        for x in dev_info:
+                            if x[0] == 'backend':
+                                backend = x[1]
+                                break
+                        break
+                self._waitForDevice_destroy(deviceClass, devid, backend)
+
+        if rm_cfg:
+            if deviceClass == 'vif':
+                if self.domid is not None:
+                    for dev_num, dev_info in sxprs:
+                        dev_num = int(dev_num)
+                        if dev_num == dev:
+                            for x in dev_info:
+                                if x[0] == 'mac':
+                                    mac = x[1]
+                                    break
+                            break
+                    dev_info = self.getDeviceInfo_vif(mac)
+                else:
+                    _, dev_info = sxprs[dev]
+            else:  # 'vbd' or 'tap'
+                dev_info = self.getDeviceInfo_vbd(dev)
+            if dev_info is None:
+                return rc
+
+            dev_uuid = sxp.child_value(dev_info, 'uuid')
+            del self.info['devices'][dev_uuid]
+            self.info['%s_refs' % deviceClass].remove(dev_uuid)
+            xen.xend.XendDomain.instance().managed_config_save(self)
+
+        return rc
 
     def getDeviceSxprs(self, deviceClass):
         if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
@@ -573,6 +628,23 @@ class XendDomainInfo:
                     sxprs.append([dev_num, dev_info])
                     dev_num += 1
             return sxprs
+
+    def getDeviceInfo_vif(self, mac):
+        for dev_type, dev_info in self.info.all_devices_sxpr():
+            if dev_type != 'vif':
+                continue
+            if mac == sxp.child_value(dev_info, 'mac'):
+                return dev_info
+
+    def getDeviceInfo_vbd(self, devid):
+        for dev_type, dev_info in self.info.all_devices_sxpr():
+            if dev_type != 'vbd' and dev_type != 'tap':
+                continue
+            dev = sxp.child_value(dev_info, 'dev')
+            dev = dev.split(':')[0]
+            dev = self.getDeviceController(dev_type).convertToDeviceNumber(dev)
+            if devid == dev:
+                return dev_info
 
 
     def setMemoryTarget(self, target):
@@ -1321,6 +1393,10 @@ class XendDomainInfo:
         deviceClass, config = self.info['devices'].get(dev_uuid)
         self._waitForDevice(deviceClass, config['devid'])
 
+    def _waitForDevice_destroy(self, deviceClass, devid, backpath):
+        return self.getDeviceController(deviceClass).waitForDevice_destroy(
+            devid, backpath)
+
     def _reconfigureDevice(self, deviceClass, devid, devconfig):
         return self.getDeviceController(deviceClass).reconfigureDevice(
             devid, devconfig)
diff -r f0298301ba8b -r 95f90f24f3b1 
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py     Thu Aug 09 16:14:56 
2007 +0100
+++ b/tools/python/xen/xend/server/DevController.py     Thu Aug 09 16:21:41 
2007 +0100
@@ -28,17 +28,19 @@ from xen.xend.xenstore.xswatch import xs
 
 import os
 
-DEVICE_CREATE_TIMEOUT = 100
+DEVICE_CREATE_TIMEOUT  = 100
+DEVICE_DESTROY_TIMEOUT = 100
 HOTPLUG_STATUS_NODE = "hotplug-status"
 HOTPLUG_ERROR_NODE  = "hotplug-error"
 HOTPLUG_STATUS_ERROR = "error"
 HOTPLUG_STATUS_BUSY  = "busy"
 
-Connected = 1
-Error     = 2
-Missing   = 3
-Timeout   = 4
-Busy      = 5
+Connected    = 1
+Error        = 2
+Missing      = 3
+Timeout      = 4
+Busy         = 5
+Disconnected = 6
 
 xenbusState = {
     'Unknown'      : 0,
@@ -185,6 +187,18 @@ class DevController:
                           (devid, self.deviceClass, err))
 
 
+    def waitForDevice_destroy(self, devid, backpath):
+        log.debug("Waiting for %s - destroyDevice.", devid)
+
+        if not self.hotplug:
+            return
+
+        status = self.waitForBackend_destroy(backpath)
+
+        if status == Timeout:
+            raise VmError("Device %s (%s) could not be disconnected. " %
+                          (devid, self.deviceClass))
+
 
     def reconfigureDevice(self, devid, config):
         """Reconfigure the specified device.
@@ -209,12 +223,7 @@ class DevController:
         here.
         """
 
-        try:
-            dev = int(devid)
-        except ValueError:
-            # Does devid contain devicetype/deviceid?
-            # Propogate exception if unable to find an integer devid
-            dev = int(type(devid) is str and devid.split('/')[-1] or None)
+        dev = self.convertToDeviceNumber(devid)
 
         # Modify online status /before/ updating state (latter is watched by
         # drivers, so this ordering avoids a race).
@@ -282,6 +291,15 @@ class DevController:
             config_dict = self.getDeviceConfiguration(devid)
             all_configs[devid] = config_dict
         return all_configs
+
+
+    def convertToDeviceNumber(self, devid):
+        try:
+            return int(devid)
+        except ValueError:
+            # Does devid contain devicetype/deviceid?
+            # Propogate exception if unable to find an integer devid
+            return int(type(devid) is str and devid.split('/')[-1] or None)
 
     ## protected:
 
@@ -513,6 +531,19 @@ class DevController:
             return (Missing, None)
 
 
+    def waitForBackend_destroy(self, backpath):
+
+        statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
+        ev = Event()
+        result = { 'status': Timeout }
+
+        xswatch(statusPath, deviceDestroyCallback, 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.
 
@@ -561,3 +592,19 @@ def hotplugStatusCallback(statusPath, ev
 
     ev.set()
     return 0
+
+
+def deviceDestroyCallback(statusPath, ev, result):
+    log.debug("deviceDestroyCallback %s.", statusPath)
+
+    status = xstransact.Read(statusPath)
+
+    if status is None:
+        result['status'] = Disconnected
+    else:
+        return 1
+
+    log.debug("deviceDestroyCallback %d.", result['status'])
+
+    ev.set()
+    return 0
diff -r f0298301ba8b -r 95f90f24f3b1 tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py     Thu Aug 09 16:14:56 2007 +0100
+++ b/tools/python/xen/xend/server/blkif.py     Thu Aug 09 16:21:41 2007 +0100
@@ -165,11 +165,23 @@ class BlkifController(DevController):
         try:
             DevController.destroyDevice(self, devid, force)
         except ValueError:
-            devid_end = type(devid) is str and devid.split('/')[-1] or None
+            dev = self.convertToDeviceNumber(devid)
 
             for i in self.deviceIDs():
-                d = self.readBackend(i, 'dev')
-                if d == devid or (devid_end and d == devid_end):
+                if i == dev:
                     DevController.destroyDevice(self, i, force)
                     return
             raise VmError("Device %s not connected" % devid)
+
+    def convertToDeviceNumber(self, devid):
+        try:
+            dev = int(devid)
+        except ValueError:
+            if type(devid) is not str:
+                raise VmError("devid %s is wrong type" % str(devid))
+            try:
+                dev = devid.split('/')[-1]
+                dev = int(dev)
+            except ValueError:
+                dev = blkif.blkdev_name_to_number(dev)
+        return dev
diff -r f0298301ba8b -r 95f90f24f3b1 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Thu Aug 09 16:14:56 2007 +0100
+++ b/tools/python/xen/xm/main.py       Thu Aug 09 16:21:41 2007 +0100
@@ -2186,6 +2186,7 @@ def xm_network_attach(args):
 
 
 def detach(args, deviceClass):
+    rm_cfg = True
     dom = args[0]
     dev = args[1]
     try:
@@ -2196,7 +2197,7 @@ def detach(args, deviceClass):
     except IndexError:
         force = None
 
-    server.xend.domain.destroyDevice(dom, deviceClass, dev, force)
+    server.xend.domain.destroyDevice(dom, deviceClass, dev, force, rm_cfg)
 
 
 def xm_block_detach(args):

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.