[libvirt] [PATCH 4/5] qemu: Allow network device-detach by PCI address and/or MAC

Michal Privoznik mprivozn at redhat.com
Thu Mar 17 14:38:48 UTC 2011


Until now, users could detach interface by MAC address, which is not
sufficient in cases when MAC is not unique. Therefore we need to
support detaching via PCI address as well. Or in case when domain has
exactly one interface users does not need to specify any MAC/PCI
address at all.
---
 src/qemu/qemu_driver.c  |    3 ++-
 src/qemu/qemu_hotplug.c |   46 ++++++++++++++++++++++++++++++++++------------
 2 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index dac2bf2..3bf5d2e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4293,7 +4293,8 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
     }
 
     dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
-                                  VIR_DOMAIN_XML_INACTIVE);
+                                  VIR_DOMAIN_XML_INACTIVE |
+                                  VIR_DOMAIN_PARSE_NO_GENERATE);
     if (dev == NULL)
         goto endjob;
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index d8a8e5d..4175d2c 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1470,7 +1470,7 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
                               virDomainDeviceDefPtr dev,
                               virBitmapPtr qemuCaps)
 {
-    int i, ret = -1;
+    int i, interface_num = 0, ret = -1;
     virDomainNetDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int vlan;
@@ -1478,19 +1478,41 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
 
     for (i = 0 ; i < vm->def->nnets ; i++) {
         virDomainNetDefPtr net = vm->def->nets[i];
-
-        if (!memcmp(net->mac, dev->data.net->mac, VIR_MAC_BUFLEN)) {
+        virDomainDevicePCIAddress pci[2] = {net->info.addr.pci,
+                                            dev->data.net->info.addr.pci};
+
+        if ( ((dev->data.net->mac != NULL) &&
+              !memcmp(net->mac, dev->data.net->mac, VIR_MAC_BUFLEN)) ||
+             ((dev->data.net->mac == NULL) && (vm->def->nnets == 1)) ||
+             ((pci[0].domain == pci[1].domain) &&
+              (pci[0].bus == pci[1].bus) &&
+              (pci[0].slot == pci[1].slot) &&
+              (pci[0].function == pci[1].function)) ) {
+            if (detach) {
+                qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                                _("ambiguous device specification. "
+                                  "Use <mac> and/or <address>"));
+                goto cleanup;
+            }
             detach = net;
-            break;
+            interface_num = i;
         }
     }
 
     if (!detach) {
-        qemuReportError(VIR_ERR_OPERATION_FAILED,
-                        _("network device %02x:%02x:%02x:%02x:%02x:%02x not found"),
-                        dev->data.net->mac[0], dev->data.net->mac[1],
-                        dev->data.net->mac[2], dev->data.net->mac[3],
-                        dev->data.net->mac[4], dev->data.net->mac[5]);
+        if (vm->def->nnets == 0) {
+            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                            _("domain has no device to detach"));
+        } else  if (dev->data.net->mac) {
+            qemuReportError(VIR_ERR_OPERATION_FAILED,
+                            _("network device %02x:%02x:%02x:%02x:%02x:%02x not found"),
+                            dev->data.net->mac[0], dev->data.net->mac[1],
+                            dev->data.net->mac[2], dev->data.net->mac[3],
+                            dev->data.net->mac[4], dev->data.net->mac[5]);
+        } else {
+            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                            _("network device not found. Use <mac> and/or <address>"));
+        }
         goto cleanup;
     }
 
@@ -1571,10 +1593,10 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
     }
 
     if (vm->def->nnets > 1) {
-        memmove(vm->def->nets + i,
-                vm->def->nets + i + 1,
+        memmove(vm->def->nets + interface_num,
+                vm->def->nets + interface_num + 1,
                 sizeof(*vm->def->nets) *
-                (vm->def->nnets - (i + 1)));
+                (vm->def->nnets - (interface_num + 1)));
         vm->def->nnets--;
         if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets) < 0) {
             /* ignore, harmless */
-- 
1.7.4




More information about the libvir-list mailing list