--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list