[libvirt] [PATCH 3/2] qemu: use lighter-weight fd:n on incoming tunneled migration

Eric Blake eblake at redhat.com
Thu Dec 23 18:29:13 UTC 2010


Outgoing migration still has to use a Unix socket and or exec netcat,
since there is no way to pass a migration fd into qemu via monitor
commands, but incoming migration need not suffer from the complexity.

* src/qemu/qemu_driver.c (qemudDomainMigratePrepareTunnel):
Replace Unix socket with simpler pipe.
Suggested by Paolo Bonzini.
---

So far only compile tested.  After sending this mail, I'm going
to reboot into compatible systems to actually test it, so here's
hoping I don't have to send a v2 from something I overlooked.

 src/qemu/qemu_driver.c |   49 +++++++++++++++--------------------------------
 1 files changed, 16 insertions(+), 33 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 490dc95..3ef2c22 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7982,11 +7982,10 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
     struct qemud_driver *driver = dconn->privateData;
     virDomainDefPtr def = NULL;
     virDomainObjPtr vm = NULL;
-    char *migrateFrom;
     virDomainEventPtr event = NULL;
     int ret = -1;
     int internalret;
-    char *unixfile = NULL;
+    int dataFD[2] = { -1, -1 };
     unsigned long long qemuCmdFlags;
     qemuDomainObjPrivatePtr priv = NULL;
     struct timeval now;
@@ -8052,39 +8051,27 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
     /* Domain starts inactive, even if the domain XML had an id field. */
     vm->def->id = -1;

-    if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.dest.%s",
-                    driver->libDir, vm->def->name) < 0) {
-        virReportOOMError();
+    if (pipe(dataFD) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("cannot create pipe for tunnelled migration"));
         goto endjob;
     }
-    unlink(unixfile);

     /* check that this qemu version supports the interactive exec */
-    if (qemuCapsExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) {
+    if (qemuCapsExtractVersionInfo(vm->def->emulator, NULL,
+                                   &qemuCmdFlags) < 0) {
         qemuReportError(VIR_ERR_INTERNAL_ERROR,
                         _("Cannot determine QEMU argv syntax %s"),
                         vm->def->emulator);
         goto endjob;
     }
-    if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX)
-        internalret = virAsprintf(&migrateFrom, "unix:%s", unixfile);
-    else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)
-        internalret = virAsprintf(&migrateFrom, "exec:nc -U -l %s", unixfile);
-    else {
-        qemuReportError(VIR_ERR_OPERATION_FAILED,
-                        "%s", _("Destination qemu is too old to support tunnelled migration"));
-        goto endjob;
-    }
-    if (internalret < 0) {
-        virReportOOMError();
-        goto endjob;
-    }
+
     /* Start the QEMU daemon, with the same command-line arguments plus
-     * -incoming unix:/path/to/file or exec:nc -U /path/to/file
+     * -incoming stdin (which qemu_command might convert to exec:cat or fd:n)
      */
-    internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, true,
-                                     -1, NULL, VIR_VM_OP_MIGRATE_IN_START);
-    VIR_FREE(migrateFrom);
+    internalret = qemudStartVMDaemon(dconn, driver, vm, "stdin", true,
+                                     dataFD[1], NULL,
+                                     VIR_VM_OP_MIGRATE_IN_START);
     if (internalret < 0) {
         qemuDomainStartAudit(vm, "migrated", false);
         /* Note that we don't set an error here because qemudStartVMDaemon
@@ -8097,9 +8084,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
         goto endjob;
     }

-    if (virFDStreamConnectUNIX(st,
-                               unixfile,
-                               false) < 0) {
+    if (virFDStreamOpen(st, dataFD[0]) < 0) {
         qemuDomainStartAudit(vm, "migrated", false);
         qemudShutdownVMDaemon(driver, vm, 0);
         if (!vm->persistent) {
@@ -8107,9 +8092,8 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
                 virDomainRemoveInactive(&driver->domains, vm);
             vm = NULL;
         }
-        virReportSystemError(errno,
-                             _("cannot open unix socket '%s' for tunnelled migration"),
-                             unixfile);
+        virReportSystemError(errno, "%s",
+                             _("cannot pass pipe for tunnelled migration"));
         goto endjob;
     }

@@ -8139,9 +8123,8 @@ endjob:

 cleanup:
     virDomainDefFree(def);
-    if (unixfile)
-        unlink(unixfile);
-    VIR_FREE(unixfile);
+    VIR_FORCE_CLOSE(dataFD[0]);
+    VIR_FORCE_CLOSE(dataFD[1]);
     if (vm)
         virDomainObjUnlock(vm);
     if (event)
-- 
1.7.3.3




More information about the libvir-list mailing list