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