This patch implements a thread for each VM that iterates through the list of macvtap interfaces, attempting to recreate each one and reconnect it to qemu. See the PATCH 0 email for discussion. --- Index: libvirt-0.7.6/src/qemu/qemu_driver.c =================================================================== --- libvirt-0.7.6.orig/src/qemu/qemu_driver.c +++ libvirt-0.7.6/src/qemu/qemu_driver.c @@ -76,6 +76,7 @@ #include "xml.h" #include "cpu/cpu.h" #include "macvtap.h" +#include "threads.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -96,6 +97,8 @@ struct _qemuDomainObjPrivate { int *vcpupids; qemuDomainPCIAddressSetPtr pciaddrs; + + pthread_t reconnectNetBackendsThread; }; static int qemudShutdown(void); @@ -143,6 +146,8 @@ static int qemudDomainDisconnectNetBacke virDomainObjPtr vm, virDomainNetDefPtr net); +static void *qemudDomainReconnectNetBackends(void *opaque); + static struct qemud_driver *qemu_driver = NULL; @@ -2794,6 +2799,10 @@ static int qemudStartVMDaemon(virConnect if (virDomainSaveStatus(conn, driver->caps, driver->stateDir, vm) < 0) goto abort; + if (pthread_create(&priv->reconnectNetBackendsThread, NULL, + qemudDomainReconnectNetBackends, vm->def->uuid)) + goto abort; + return 0; cleanup: @@ -5627,7 +5636,7 @@ static int qemudDomainConnectNetBackend( unsigned int qemuCmdFlags) { qemuDomainObjPrivatePtr priv = vm->privateData; - char *tapfd_name = NULL; + char *hostnet_name = NULL; int tapfd = -1; char *netstr = NULL; int ret = -1; @@ -5664,27 +5673,30 @@ static int qemudDomainConnectNetBackend( if (tapfd < 0) return -1; - if (virAsprintf(&tapfd_name, "fd-%s", net->info.alias) < 0) { + if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0) { virReportOOMError(conn); close(tapfd); return -1; } if (!(netstr = qemuBuildHostNetStr(conn, net, ' ', - vlan, tapfd_name))) { - VIR_FREE(tapfd_name); + vlan, hostnet_name))) { + VIR_FREE(hostnet_name); close(tapfd); return -1; } qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) + if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) + VIR_INFO0("Did not remove existing host network"); + + if (qemuMonitorSendFileHandle(priv->mon, hostnet_name, tapfd) < 0) goto out; if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) { - if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0) - VIR_WARN(_("Failed to close tapfd with '%s'"), tapfd_name); + if (qemuMonitorCloseFileHandle(priv->mon, hostnet_name) < 0) + VIR_WARN(_("Failed to close tapfd with '%s'"), hostnet_name); goto out; } @@ -5693,7 +5705,7 @@ static int qemudDomainConnectNetBackend( out: qemuDomainObjExitMonitorWithDriver(driver, vm); VIR_FREE(netstr); - VIR_FREE(tapfd_name); + VIR_FREE(hostnet_name); close(tapfd); return ret; } @@ -8549,6 +8561,72 @@ out: return ret; } +static void *qemudDomainReconnectNetBackends(void *opaque) +{ + virConnectPtr conn = virConnectOpen("qemu:///system"); + struct qemud_driver *driver = conn->privateData; + const unsigned char *uuid = opaque; + + while (1) { + virDomainObjPtr vm; + unsigned int qemuCmdFlags; + int i; + + usleep(1000000); + + VIR_ERROR(_("qemuDomainReconnectNetBackends (%p %p)"), + conn, driver); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, uuid); + if (!vm) { + VIR_ERROR0("qemuDomainReconnectNetBackends done"); + qemuDriverUnlock(driver); + break; + } + + VIR_ERROR(_("qemuDomainReconnectNetBackends (%s)"), + vm->def->name); + + if (qemudExtractVersionInfo(vm->def->emulator, + NULL, + &qemuCmdFlags) < 0) + goto cleanup; + + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) + goto endjob; + + for (i = 0 ; i < vm->def->nnets ; i++) { + virDomainNetDefPtr net = vm->def->nets[i]; + + VIR_ERROR(_("qemuDomainReconnectNetBackends (%s)"), net->ifname); + + if (net->type != VIR_DOMAIN_NET_TYPE_DIRECT) + continue; + + if (qemudDomainConnectNetBackend(conn, driver, vm, + net, qemuCmdFlags) < 0) + VIR_ERROR(_("qemudDomainConnectNetBackend failed (%s)"), + net->ifname); + } + + endjob: + if (vm && + qemuDomainObjEndJob(vm) == 0) + vm = NULL; + + cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + } + + return NULL; +} + static int qemuCPUCompare(virConnectPtr conn, const char *xmlDesc, -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list