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(a)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