[libvirt] [RFC][PATCH 2/2] Automatically recreate macvtap interface and reconnect to qemu

Ed Swierk eswierk at aristanetworks.com
Fri Feb 19 23:35:36 UTC 2010


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,





More information about the libvir-list mailing list