[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 5/5] Migration support for ephemeral hostdevs.



---
 src/qemu/qemu_migration.c |   94 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index d52ec59..dd1a2a7 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -32,6 +32,7 @@
 #include "qemu_monitor.h"
 #include "qemu_domain.h"
 #include "qemu_process.h"
+#include "qemu_hotplug.h"
 #include "qemu_capabilities.h"
 #include "qemu_cgroup.h"
 
@@ -50,6 +51,7 @@
 #include "storage_file.h"
 #include "viruri.h"
 #include "hooks.h"
+#include "network/bridge_driver.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -149,6 +151,79 @@ struct _qemuMigrationCookie {
     qemuMigrationCookieNetworkPtr network;
 };
 
+static void
+qemuMigrationRemoveEphemeralDevices(struct qemud_driver *driver,
+                                    virDomainObjPtr vm)
+{
+    virDomainHostdevDefPtr dev;
+    virDomainDeviceDef def;
+    unsigned int i;
+
+    for (i = 0; i < vm->def->nhostdevs; i++) {
+        dev = vm->def->hostdevs[i];
+        if (dev->ephemeral == 1) {
+            def.type = VIR_DOMAIN_DEVICE_HOSTDEV;
+            def.data.hostdev = dev;
+
+            if (qemuDomainDetachHostDevice(driver, vm, &def) >= 0) {
+                continue; /* nhostdevs reduced */
+            }
+        }
+    }
+}
+
+static void
+qemuMigrationRestoreEphemeralDevices(struct qemud_driver *driver,
+                                     virDomainObjPtr vm)
+{
+    virDomainNetDefPtr net;
+    unsigned int i;
+
+    /* Do nothing if ephemeral devices are present in which case this
+       function was called before qemuMigrationRemoveEphemeralDevices */
+
+    for (i = 0; i < vm->def->nhostdevs; i++) {
+        if (vm->def->hostdevs[i]->ephemeral == 1)
+            return;
+    }
+
+    for (i = 0; i < vm->def->nnets; i++) {
+        net = vm->def->nets[i];
+
+        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+            if (qemuDomainAttachHostDevice(driver, vm,
+                                           virDomainNetGetActualHostdev(net)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Hostdev cannot be restored"));
+                networkReleaseActualDevice(net);
+            }
+        }
+        return;
+    }
+}
+
+static void
+qemuMigrationAttachEphemeralDevices(struct qemud_driver *driver,
+                                    virDomainObjPtr vm)
+{
+    virDomainNetDefPtr net;
+    unsigned int i;
+
+    for (i = 0; i < vm->def->nnets; i++) {
+        net = vm->def->nets[i];
+
+        if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+            if (qemuDomainAttachHostDevice(driver, vm,
+                                           virDomainNetGetActualHostdev(net)) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Hostdev cannot be attached after migration"));
+                networkReleaseActualDevice(net);
+            }
+        }
+    }
+    return;
+}
+
 static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
 {
     if (!grap)
@@ -1041,21 +1116,22 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm,
         def = vm->def;
     }
 
-    /* Migration with USB host devices is allowed, all other devices are
+    /* Migration with USB and ephemeral PCI host devices is allowed, all other devices are
      * forbidden.
      */
     forbid = false;
     for (i = 0; i < def->nhostdevs; i++) {
         virDomainHostdevDefPtr hostdev = def->hostdevs[i];
         if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
-            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+            ((hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) &&
+             (hostdev->ephemeral == 0))) {
             forbid = true;
             break;
         }
     }
     if (forbid) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("Domain with assigned non-USB host devices "
+                       _("Domain with assigned non-USB and non-ephemeral host devices "
                          "cannot be migrated"));
         return false;
     }
@@ -2347,6 +2423,7 @@ static int doNativeMigrate(struct qemud_driver *driver,
               "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu",
               driver, vm, uri, NULLSTR(cookiein), cookieinlen,
               cookieout, cookieoutlen, flags, resource);
+    qemuMigrationRemoveEphemeralDevices(driver, vm);
 
     if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) {
         char *tmp;
@@ -2374,6 +2451,9 @@ static int doNativeMigrate(struct qemud_driver *driver,
     ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
                            cookieoutlen, flags, resource, &spec, dconn);
 
+    if (ret != 0)
+        qemuMigrationRestoreEphemeralDevices(driver, vm);
+
     if (spec.destType == MIGRATION_DEST_FD)
         VIR_FORCE_CLOSE(spec.dest.fd.qemu);
 
@@ -2412,6 +2492,8 @@ static int doTunnelMigrate(struct qemud_driver *driver,
         return -1;
     }
 
+    qemuMigrationRemoveEphemeralDevices(driver, vm);
+
     spec.fwdType = MIGRATION_FWD_STREAM;
     spec.fwd.stream = st;
 
@@ -2458,6 +2540,8 @@ static int doTunnelMigrate(struct qemud_driver *driver,
                            cookieoutlen, flags, resource, &spec, dconn);
 
 cleanup:
+    if (ret != 0)
+        qemuMigrationRestoreEphemeralDevices(driver, vm);
     if (spec.destType == MIGRATION_DEST_FD) {
         VIR_FORCE_CLOSE(spec.dest.fd.qemu);
         VIR_FORCE_CLOSE(spec.dest.fd.local);
@@ -3366,6 +3450,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
             goto endjob;
         }
 
+        qemuMigrationAttachEphemeralDevices(driver, vm);
+
         /* Guest is successfully running, so cancel previous auto destroy */
         qemuProcessAutoDestroyRemove(driver, vm);
     } else {
@@ -3463,6 +3549,8 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
             VIR_WARN("Failed to save status on vm %s", vm->def->name);
             goto cleanup;
         }
+
+        qemuMigrationRestoreEphemeralDevices(driver, vm);
     }
 
     qemuMigrationCookieFree(mig);
-- 
1.7.4.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]