[libvirt] [PATCH 12/13] qemu: Set up the migrate TLS objects for target

John Ferlan jferlan at redhat.com
Fri Feb 17 19:39:29 UTC 2017


Support TLS for a migration is a multistep process. The target guest must
be started using the "-object tls-creds-x509,endpoint=server,...". If that
TLS object requires a passphrase an addition "-object security..." would
also be created.  The alias/id used for the TLS object is "objmigrate_tls0",
while the alias/id used for the security object is "migrate-secret0".

Once the domain is started, the "tls-creds" migration parameter must be
set to the alias/id of the "tls-creds-x509" object.

Once the migration completes, removing the two objects is necessary since
the newly started domain could then become the source of a migration and
thus would not be an endpoint.

Handle the possibility of libvirtd stop/reconnect by saving the fact that
a migration is using TLS was started in a "migrateTLS" boolean.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/qemu/qemu_command.c   | 29 ++++++++++++++++-
 src/qemu/qemu_command.h   |  4 ++-
 src/qemu/qemu_domain.c    |  5 +++
 src/qemu/qemu_domain.h    |  1 +
 src/qemu/qemu_migration.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_process.c   |  4 +++
 6 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d831d56..d8373aa 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -802,6 +802,27 @@ qemuBuildTLSx509CommandLine(virCommandPtr cmd,
 }
 
 
+static int
+qemuBuildMigrateTLSCommandLine(virCommandPtr cmd,
+                               virQEMUDriverConfigPtr cfg,
+                               virQEMUCapsPtr qemuCaps,
+                               qemuDomainSecretInfoPtr migSecinfo)
+{
+    if (migSecinfo && qemuBuildObjectSecretCommandLine(cmd, migSecinfo) < 0)
+        return -1;
+
+    /* When starting from command line this is the target of a migration
+     * so we need to start a TLS endpoint server (3rd param) */
+    if (qemuBuildTLSx509CommandLine(cmd, cfg->migrateTLSx509certdir,
+                                    true, cfg->migrateTLSx509verify,
+                                    !!cfg->migrateTLSx509secretUUID,
+                                    "migrate", qemuCaps) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 #define QEMU_DEFAULT_NBD_PORT "10809"
 #define QEMU_DEFAULT_GLUSTER_PORT "24007"
 
@@ -9639,6 +9660,8 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
                      bool monitor_json,
                      virQEMUCapsPtr qemuCaps,
                      const char *migrateURI,
+                     bool migrateTLS,
+                     qemuDomainSecretInfoPtr migSecinfo,
                      virDomainSnapshotObjPtr snapshot,
                      virNetDevVPortProfileOp vmop,
                      bool standalone,
@@ -9831,8 +9854,12 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet) < 0)
         goto error;
 
-    if (migrateURI)
+    if (migrateURI) {
         virCommandAddArgList(cmd, "-incoming", migrateURI, NULL);
+        if (migrateTLS && qemuBuildMigrateTLSCommandLine(cmd, cfg, qemuCaps,
+                                                         migSecinfo) < 0)
+            goto error;
+    }
 
     if (qemuBuildMemballoonCommandLine(cmd, def, qemuCaps) < 0)
         goto error;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 69fe846..d6349be 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -50,6 +50,8 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
                                    bool monitor_json,
                                    virQEMUCapsPtr qemuCaps,
                                    const char *migrateURI,
+                                   bool migrateTLS,
+                                   qemuDomainSecretInfoPtr migSecinfo,
                                    virDomainSnapshotObjPtr snapshot,
                                    virNetDevVPortProfileOp vmop,
                                    bool standalone,
@@ -58,7 +60,7 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
                                    size_t *nnicindexes,
                                    int **nicindexes,
                                    const char *domainLibDir)
-    ATTRIBUTE_NONNULL(15);
+    ATTRIBUTE_NONNULL(17);
 
 
 /* Generate the object properties for a secret */
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index dd3cfd5..100ab9c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1864,6 +1864,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf,
     virBufferEscapeString(buf, "<channelTargetDir path='%s'/>\n",
                           priv->channelTargetDir);
 
+    if (priv->migrateTLS)
+        virBufferAddLit(buf, "<migrateTLS/>\n");
+
     return 0;
 }
 
@@ -2132,6 +2135,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
     if (qemuDomainSetPrivatePathsOld(driver, vm) < 0)
         goto error;
 
+    priv->migrateTLS = virXPathBoolean("boolean(./migrateTLS)", ctxt) == 1;
+
     return 0;
 
  error:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index f796306..06af44a 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -287,6 +287,7 @@ struct _qemuDomainObjPrivate {
     /* for migration's using TLS with a secret (not to be saved in our */
     /* private XML). */
     qemuDomainSecretInfoPtr migSecinfo;
+    bool migrateTLS;
 };
 
 # define QEMU_DOMAIN_PRIVATE(vm)	\
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 0db1616..448d94e 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1487,6 +1487,55 @@ qemuMigrationEatCookie(virQEMUDriverPtr driver,
     return NULL;
 }
 
+
+/* qemuMigrationCheckSetupTLS
+ *
+ * Check if flags desired to use TLS and whether it's configured for the
+ * host it's being run on (src or dst depending on caller). If configured
+ * to use a secret for the TLS config, generate and save the migSecinfo.
+ *
+ * Returns 0 on success (or no TLS)
+ */
+static int
+qemuMigrationCheckSetupTLS(virQEMUDriverPtr driver,
+                           virConnectPtr dconn,
+                           virDomainObjPtr vm,
+                           unsigned int flags)
+{
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virQEMUDriverConfigPtr cfg = NULL;
+
+    if (flags & VIR_MIGRATE_TLS) {
+        cfg = virQEMUDriverGetConfig(driver);
+
+        if (!cfg->migrateTLS) {
+            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                           _("migration TLS not enabled for the host"));
+            goto cleanup;
+        }
+
+        priv->migrateTLS = true;
+        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
+                                vm, driver->caps) < 0)
+            VIR_WARN("Failed to save migrateTLS for vm %s", vm->def->name);
+
+        /* If there's a secret associated with the migrate TLS, then we
+         * need to grab it before attempting to create the command line. */
+        if (cfg->migrateTLSx509secretUUID &&
+            qemuDomainSecretMigratePrepare(dconn, priv, "migrate",
+                                           cfg->migrateTLSx509secretUUID) < 0)
+            goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    virObjectUnref(cfg);
+    return ret;
+}
+
+
 static void
 qemuMigrationStoreDomainState(virDomainObjPtr vm)
 {
@@ -3613,6 +3662,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
     bool stopProcess = false;
     bool relabel = false;
     int rv;
+    char *tlsAlias = NULL;
     qemuMonitorMigrationParams migParams = { 0 };
 
     virNWFilterReadLockFilterUpdates();
@@ -3779,6 +3829,13 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
                                  VIR_QEMU_PROCESS_START_AUTODESTROY) < 0)
         goto stopjob;
 
+    if (qemuMigrationCheckSetupTLS(driver, dconn, vm, flags) < 0)
+        goto stopjob;
+
+    if (priv->migrateTLS &&
+        !(tlsAlias = qemuAliasTLSObjFromSrcAlias("migrate")))
+        goto stopjob;
+
     if (qemuProcessPrepareHost(driver, vm, !!incoming) < 0)
         goto stopjob;
 
@@ -3806,6 +3863,12 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
                                     compression, &migParams) < 0)
         goto stopjob;
 
+    /* A set only parameter to indicate the "tls-creds-x509" object id */
+    if (priv->migrateTLS) {
+        migParams.migrateTLSAlias = tlsAlias;
+        migParams.migrateTLSAlias_set = true;
+    }
+
     if (STREQ_NULLABLE(protocol, "rdma") &&
         virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) {
         goto stopjob;
@@ -3891,6 +3954,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
+    VIR_FREE(tlsAlias);
     qemuProcessIncomingDefFree(incoming);
     VIR_FREE(xmlout);
     VIR_FORCE_CLOSE(dataFD[0]);
@@ -6185,6 +6249,22 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
     qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);
     VIR_FREE(priv->job.completed);
 
+    /* If migration used TLS, then command line creation generated a
+     * secinfo object and a TLS server object. Remove both now as this
+     * domain would now be a potential client of the next migration. */
+    if (priv->migrateTLS) {
+        char *tlsAlias = qemuAliasTLSObjFromSrcAlias("migrate");
+        char *secAlias = qemuDomainGetSecretAESAlias("migrate", false);
+
+        qemuDomainDelTLSObjects(driver, vm, secAlias, tlsAlias);
+        qemuDomainSecretMigrateDestroy(&priv->migSecinfo);
+        VIR_FREE(tlsAlias);
+        priv->migrateTLS = false;
+        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
+                                vm, driver->caps) < 0)
+            VIR_WARN("Failed to save migrateTLS on vm %s", vm->def->name);
+    }
+
     cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK |
                    QEMU_MIGRATION_COOKIE_STATS |
                    QEMU_MIGRATION_COOKIE_NBD;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 76f132b..b9d6a9d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5469,6 +5469,8 @@ qemuProcessLaunch(virConnectPtr conn,
                                      vm->def, priv->monConfig,
                                      priv->monJSON, priv->qemuCaps,
                                      incoming ? incoming->launchURI : NULL,
+                                     priv->migrateTLS,
+                                     priv->migSecinfo,
                                      snapshot, vmop,
                                      false,
                                      qemuCheckFips(),
@@ -5901,6 +5903,8 @@ qemuProcessCreatePretendCmd(virConnectPtr conn,
                                priv->monJSON,
                                priv->qemuCaps,
                                migrateURI,
+                               false,
+                               NULL,
                                NULL,
                                VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
                                standalone,
-- 
2.9.3




More information about the libvir-list mailing list