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

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


---
 src/xen/xm_internal.c |   65 ++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 53 insertions(+), 12 deletions(-)

diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 9a9fa0c..5b074b3 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -1445,7 +1445,7 @@ xenXMDomainDetachDeviceFlags(virDomainPtr domain, const char *xml,
     virDomainDeviceDefPtr dev = NULL;
     virDomainDefPtr def;
     int ret = -1;
-    int i;
+    int i, interface_num = -1;
     xenUnifiedPrivatePtr priv;
 
     if ((!domain) || (!domain->conn) || (!domain->name) || (!xml)) {
@@ -1475,7 +1475,8 @@ xenXMDomainDetachDeviceFlags(virDomainPtr domain, const char *xml,
 
     if (!(dev = virDomainDeviceDefParse(priv->caps,
                                         entry->def,
-                                        xml, VIR_DOMAIN_XML_INACTIVE)))
+                                        xml, VIR_DOMAIN_XML_INACTIVE |
+                                        VIR_DOMAIN_PARSE_NO_GENERATE)))
         goto cleanup;
 
     switch (dev->type) {
@@ -1501,18 +1502,58 @@ xenXMDomainDetachDeviceFlags(virDomainPtr domain, const char *xml,
     case VIR_DOMAIN_DEVICE_NET:
     {
         for (i = 0 ; i < def->nnets ; i++) {
-            if (!memcmp(def->nets[i]->mac, dev->data.net->mac,
-                        VIR_MAC_BUFLEN)) {
-                virDomainNetDefFree(def->nets[i]);
-                if (i < (def->nnets - 1))
-                    memmove(def->nets + i,
-                            def->nets + i + 1,
-                            sizeof(*def->nets) *
-                            (def->nnets - (i + 1)));
-                def->nnets--;
-                break;
+            virDomainDevicePCIAddress pci[2] = {def->nets[i]->info.addr.pci,
+                                                dev->data.net->info.addr.pci};
+
+            if ( ((dev->data.net->mac != NULL) &&
+                  !memcmp(def->nets[i]->mac, dev->data.net->mac, VIR_MAC_BUFLEN)) ||
+                 ((dev->data.net->mac == NULL) && (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 (interface_num >= 0) {
+                    xenXMError(VIR_ERR_OPERATION_FAILED, "%s",
+                               _("ambiguous device specification. "
+                                 "Use <mac> and/or <address>"));
+                    goto cleanup;
+                }
+                interface_num = i;
+            }
+        }
+
+        if (interface_num < 0) {
+            if (def->nnets == 0) {
+                xenXMError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("domain has no device to detach"));
+            } else  if (dev->data.net->mac) {
+                xenXMError(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 {
+                xenXMError(VIR_ERR_OPERATION_FAILED, "%s", _("network "
+                           "device not found. Use <mac> and/or <address>"));
             }
+            goto cleanup;
         }
+
+        if (def->nnets > 1) {
+            memmove(def->nets + interface_num,
+                    def->nets + interface_num + 1,
+                    sizeof(*def->nets) *
+                    (def->nnets - (interface_num + 1)));
+            def->nnets--;
+            if (VIR_REALLOC_N(def->nets, def->nnets) < 0) {
+                /* ingore, harmless */
+            }
+        } else {
+            VIR_FREE(def->nets);
+            def->nnets = 0;
+        }
+
+        virDomainNetDefFree(def->nets[interface_num]);
         break;
     }
     default:
-- 
1.7.4




More information about the libvir-list mailing list