---
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