Blob Blame History Raw
changeset:   487:900bee6f2cc8
user:        "Hugh O. Brock <hbrock@redhat.com>"
date:        Tue May 01 16:22:22 2007 -0400
summary:     Allow removal of devices from inactive domains. Requires rewriting the XML and redefining the domain. To work on xen 3.0.3 userland, also requires libvirt patch to xm_internal.c.

diff -r fddee0787dde -r 900bee6f2cc8 src/virtManager/domain.py
--- a/src/virtManager/domain.py	Wed Apr 25 17:51:42 2007 -0400
+++ b/src/virtManager/domain.py	Tue May 01 16:22:22 2007 -0400
@@ -545,13 +545,69 @@ class vmmDomain(gobject.GObject):
 
         self.get_connection().define_domain(newxml)
 
-    def remove_device(self, xml):
-        logging.debug("Removing device " + xml)
+    def remove_device(self, dev_xml):
+        logging.debug("Removing device " + dev_xml)
 
         if self.is_active():
-            self.vm.detachDevice(xml)
-
-        # XXX remove from defined XML. Eek !
+            self.vm.detachDevice(dev_xml)
+        else:
+            # XXX remove from defined XML. Eek !
+            xml = self.get_xml()
+            doc = None
+            try:
+                doc = libxml2.parseDoc(xml)
+            except:
+                return
+            ctx = doc.xpathNewContext()
+            try:
+                dev_doc = libxml2.parseDoc(dev_xml)
+            except:
+                raise RuntimeError("Device XML would not parse")
+            dev_ctx = dev_doc.xpathNewContext()
+            ret = None
+            try:
+                dev = dev_ctx.xpathEval("//*")
+                dev_type = dev[0].name
+                if dev_type=="interface":
+                    address = dev_ctx.xpathEval("/interface/mac/@address")
+                    if len(address) > 0 and address[0].content != None:
+                        logging.debug("The mac address appears to be %s" % address[0].content)
+                        ret = ctx.xpathEval("/domain/devices/interface[mac/@address='%s']" % address[0].content)
+                    if len(ret) >0:
+                        ret[0].unlinkNode()
+                        ret[0].freeNode()
+                        newxml=doc.serialize()
+                        logging.debug("Redefine with " + newxml)
+                        self.get_connection().define_domain(newxml)
+                elif dev_type=="disk":
+                    disk_type_node = dev_ctx.xpathEval("/disk/@type")
+                    disk_type = None
+                    if len(disk_type_node) > 0 and disk_type_node[0].content != None:
+                        disk_type = disk_type_node[0].content
+                    logging.debug("Looking for disk type %s" % disk_type)
+                    if disk_type == "block":
+                        path = dev_ctx.xpathEval("/disk/source/@dev")
+                        if len(path) > 0 and path[0].content != None:
+                            logging.debug("Looking for path %s" % path[0].content)
+                            ret = ctx.xpathEval("/domain/devices/disk[source/@dev='%s']" % path[0].content)
+                    elif disk_type == "file":
+                        path = dev_ctx.xpathEval("/disk/source/@file")
+                        if len(path) > 0 and path[0].content != None:
+                            ret = ctx.xpathEval("/domain/devices/disk[source/@file='%s']" % path[0].content)
+                    if len(ret) > 0:
+                        ret[0].unlinkNode()
+                        ret[0].freeNode()
+                        newxml=doc.serialize()
+                        logging.debug("Redefine with " + newxml)
+                        self.get_connection().define_domain(newxml)
+
+            finally:
+                if ctx != None:
+                    ctx.xpathFreeContext()
+                if doc != None:
+                    doc.freeDoc()
+                if dev_doc != None:
+                    dev_doc.freeDoc()
 
     def set_vcpu_count(self, vcpus):
         vcpus = int(vcpus)