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,