In the end, this will allow us to have most of the logic around
migration parameters done in one place.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
po/POTFILES.in | 1 +
src/qemu/Makefile.inc.am | 2 +
src/qemu/qemu_driver.c | 1 +
src/qemu/qemu_migration.c | 421 +---------------------------
src/qemu/qemu_migration.h | 24 +-
src/qemu/qemu_migration_params.c | 454 +++++++++++++++++++++++++++++++
src/qemu/qemu_migration_params.h | 82 ++++++
src/qemu/qemu_process.c | 1 +
8 files changed, 550 insertions(+), 436 deletions(-)
create mode 100644 src/qemu/qemu_migration_params.c
create mode 100644 src/qemu/qemu_migration_params.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d84859a4e3..0b62126a19 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -136,6 +136,7 @@ src/qemu/qemu_hotplug.c
src/qemu/qemu_interface.c
src/qemu/qemu_migration.c
src/qemu/qemu_migration_cookie.c
+src/qemu/qemu_migration_params.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_text.c
diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am
index 8ef290a6c1..25706ba4bc 100644
--- a/src/qemu/Makefile.inc.am
+++ b/src/qemu/Makefile.inc.am
@@ -33,6 +33,8 @@ QEMU_DRIVER_SOURCES = \
qemu/qemu_migration.h \
qemu/qemu_migration_cookie.c \
qemu/qemu_migration_cookie.h \
+ qemu/qemu_migration_params.c \
+ qemu/qemu_migration_params.h \
qemu/qemu_monitor.c \
qemu/qemu_monitor.h \
qemu/qemu_monitor_text.c \
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f7ad211077..519bd767c1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -57,6 +57,7 @@
#include "qemu_monitor.h"
#include "qemu_process.h"
#include "qemu_migration.h"
+#include "qemu_migration_params.h"
#include "qemu_blockjob.h"
#include "qemu_security.h"
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index f88ac02f2f..4bdaa67ea1 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -29,6 +29,7 @@
#include "qemu_migration.h"
#include "qemu_migration_cookie.h"
+#include "qemu_migration_params.h"
#include "qemu_monitor.h"
#include "qemu_domain.h"
#include "qemu_process.h"
@@ -81,8 +82,6 @@ VIR_ENUM_IMPL(qemuMigrationCompressMethod,
QEMU_MIGRATION_COMPRESS_LAST,
"mt",
);
-#define QEMU_MIGRATION_TLS_ALIAS_BASE "libvirt_migrate"
-
static int
qemuMigrationJobStart(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -115,156 +114,6 @@ qemuMigrationJobFinish(virQEMUDriverPtr driver,
virDomainObjPtr obj)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
-/* qemuMigrationParamsCheckTLSCreds
- * @driver: pointer to qemu driver
- * @vm: domain object
- * @asyncJob: migration job to join
- *
- * Query the migration parameters looking for the 'tls-creds' parameter.
- * If found, then we can support setting or clearing the parameters and thus
- * can support TLS for migration.
- *
- * Returns 0 if we were able to successfully fetch the params and
- * additionally if the tls-creds parameter exists, saves it in the
- * private domain structure. Returns -1 on failure.
- */
-static int
-qemuMigrationParamsCheckTLSCreds(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob asyncJob)
-{
- int ret = -1;
- qemuDomainObjPrivatePtr priv = vm->privateData;
- qemuMonitorMigrationParams migParams = { 0 };
-
- if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
- return -1;
-
- if (qemuMonitorGetMigrationParams(priv->mon, &migParams) < 0)
- goto cleanup;
-
- /* NB: Could steal NULL pointer too! Let caller decide what to do. */
- VIR_STEAL_PTR(priv->migTLSAlias, migParams.tlsCreds);
-
- ret = 0;
-
- cleanup:
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- ret = -1;
-
- qemuMigrationParamsClear(&migParams);
-
- return ret;
-}
-
-
-/* qemuMigrationParamsCheckSetupTLS
- * @driver: pointer to qemu driver
- * @vm: domain object
- * @cfg: configuration pointer
- * @asyncJob: migration job to join
- *
- * Check if TLS is possible and set up the environment. Assumes the caller
- * desires to use TLS (e.g. caller found VIR_MIGRATE_TLS flag).
- *
- * Ensure the qemu.conf has been properly configured to add an entry for
- * "migrate_tls_x509_cert_dir". Also check if the "tls-creds"
parameter
- * was present from a query of migration parameters
- *
- * Returns 0 on success, -1 on error/failure
- */
-static int
-qemuMigrationParamsCheckSetupTLS(virQEMUDriverPtr driver,
- virQEMUDriverConfigPtr cfg,
- virDomainObjPtr vm,
- qemuDomainAsyncJob asyncJob)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
-
- if (!cfg->migrateTLSx509certdir) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("host migration TLS directory not configured"));
- return -1;
- }
-
- if (qemuMigrationParamsCheckTLSCreds(driver, vm, asyncJob) < 0)
- return -1;
-
- if (!priv->migTLSAlias) {
- virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
- _("TLS migration is not supported with this "
- "QEMU binary"));
- return -1;
- }
-
- /* If there's a secret, then grab/store it now using the connection */
- if (cfg->migrateTLSx509secretUUID &&
- !(priv->migSecinfo =
- qemuDomainSecretInfoTLSNew(priv, QEMU_MIGRATION_TLS_ALIAS_BASE,
- cfg->migrateTLSx509secretUUID)))
- return -1;
-
- return 0;
-}
-
-
-/* qemuMigrationParamsAddTLSObjects
- * @driver: pointer to qemu driver
- * @vm: domain object
- * @cfg: configuration pointer
- * @tlsListen: server or client
- * @asyncJob: Migration job to join
- * @tlsAlias: alias to be generated for TLS object
- * @secAlias: alias to be generated for a secinfo object
- * @migParams: migration parameters to set
- *
- * Create the TLS objects for the migration and set the migParams value
- *
- * Returns 0 on success, -1 on failure
- */
-static int
-qemuMigrationParamsAddTLSObjects(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virQEMUDriverConfigPtr cfg,
- bool tlsListen,
- qemuDomainAsyncJob asyncJob,
- char **tlsAlias,
- char **secAlias,
- qemuMonitorMigrationParamsPtr migParams)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
- virJSONValuePtr tlsProps = NULL;
- virJSONValuePtr secProps = NULL;
-
- if (qemuDomainGetTLSObjects(priv->qemuCaps, priv->migSecinfo,
- cfg->migrateTLSx509certdir, tlsListen,
- cfg->migrateTLSx509verify,
- QEMU_MIGRATION_TLS_ALIAS_BASE,
- &tlsProps, tlsAlias, &secProps, secAlias) <
0)
- goto error;
-
- /* Ensure the domain doesn't already have the TLS objects defined...
- * This should prevent any issues just in case some cleanup wasn't
- * properly completed (both src and dst use the same alias) or
- * some other error path between now and perform . */
- qemuDomainDelTLSObjects(driver, vm, asyncJob, *secAlias, *tlsAlias);
-
- if (qemuDomainAddTLSObjects(driver, vm, asyncJob, *secAlias, &secProps,
- *tlsAlias, &tlsProps) < 0)
- goto error;
-
- if (VIR_STRDUP(migParams->tlsCreds, *tlsAlias) < 0)
- goto error;
-
- return 0;
-
- error:
- virJSONValueFree(tlsProps);
- virJSONValueFree(secProps);
- return -1;
-}
-
-
static void
qemuMigrationSrcStoreDomainState(virDomainObjPtr vm)
{
@@ -1325,7 +1174,7 @@ qemuMigrationAnyPostcopyFailed(virQEMUDriverPtr driver,
}
-static int
+int
qemuMigrationOptionSet(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuMonitorMigrationCaps capability,
@@ -2366,238 +2215,6 @@ qemuMigrationDstPrepare(virDomainObjPtr vm,
return inc;
}
-static int
-qemuMigrationParamsSetCompression(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob job,
- qemuMigrationCompressionPtr compression,
- qemuMonitorMigrationParamsPtr migParams)
-{
- int ret = -1;
- qemuDomainObjPrivatePtr priv = vm->privateData;
-
- if (qemuMigrationOptionSet(driver, vm,
- QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
- compression->methods &
- (1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE),
- job) < 0)
- return -1;
-
- if (qemuMigrationOptionSet(driver, vm,
- QEMU_MONITOR_MIGRATION_CAPS_COMPRESS,
- compression->methods &
- (1ULL << QEMU_MIGRATION_COMPRESS_MT),
- job) < 0)
- return -1;
-
- if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
- return -1;
-
- migParams->compressLevel_set = compression->level_set;
- migParams->compressLevel = compression->level;
-
- migParams->compressThreads_set = compression->threads_set;
- migParams->compressThreads = compression->threads;
-
- migParams->decompressThreads_set = compression->dthreads_set;
- migParams->decompressThreads = compression->dthreads;
-
- if (compression->xbzrle_cache_set &&
- qemuMonitorSetMigrationCacheSize(priv->mon,
- compression->xbzrle_cache) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- ret = -1;
-
- return ret;
-}
-
-
-void
-qemuMigrationParamsClear(qemuMonitorMigrationParamsPtr migParams)
-{
- if (!migParams)
- return;
-
- VIR_FREE(migParams->tlsCreds);
- VIR_FREE(migParams->tlsHostname);
-}
-
-
-void
-qemuMigrationParamsFree(qemuMonitorMigrationParamsPtr *migParams)
-{
- if (!*migParams)
- return;
-
- qemuMigrationParamsClear(*migParams);
- VIR_FREE(*migParams);
-}
-
-
-/* qemuMigrationParamsSetEmptyTLS
- * @driver: pointer to qemu driver
- * @vm: domain object
- * @asyncJob: migration job to join
- * @migParams: Pointer to a migration parameters block
- *
- * If we support setting the tls-creds, then set both tls-creds and
- * tls-hostname to the empty string ("") which indicates to not use
- * TLS on this migration.
- *
- * Returns 0 on success, -1 on failure
- */
-static int
-qemuMigrationParamsSetEmptyTLS(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob asyncJob,
- qemuMonitorMigrationParamsPtr migParams)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
-
- if (qemuMigrationParamsCheckTLSCreds(driver, vm, asyncJob) < 0)
- return -1;
-
- if (!priv->migTLSAlias)
- return 0;
-
- if (VIR_STRDUP(migParams->tlsCreds, "") < 0 ||
- VIR_STRDUP(migParams->tlsHostname, "") < 0)
- return -1;
-
- return 0;
-}
-
-
-qemuMonitorMigrationParamsPtr
-qemuMigrationParamsFromFlags(virTypedParameterPtr params,
- int nparams,
- unsigned long flags)
-{
- qemuMonitorMigrationParamsPtr migParams;
-
- if (VIR_ALLOC(migParams) < 0)
- return NULL;
-
- if (!params)
- return migParams;
-
-#define GET(PARAM, VAR) \
- do { \
- int rc; \
- if ((rc = virTypedParamsGetInt(params, nparams, \
- VIR_MIGRATE_PARAM_ ## PARAM, \
- &migParams->VAR)) < 0) \
- goto error; \
- \
- if (rc == 1) \
- migParams->VAR ## _set = true; \
- } while (0)
-
- GET(AUTO_CONVERGE_INITIAL, cpuThrottleInitial);
- GET(AUTO_CONVERGE_INCREMENT, cpuThrottleIncrement);
-
-#undef GET
-
- if ((migParams->cpuThrottleInitial_set ||
- migParams->cpuThrottleIncrement_set) &&
- !(flags & VIR_MIGRATE_AUTO_CONVERGE)) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("Turn auto convergence on to tune it"));
- goto error;
- }
-
- return migParams;
-
- error:
- qemuMigrationParamsFree(&migParams);
- return NULL;
-}
-
-
-static int
-qemuMigrationParamsSet(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob job,
- qemuMonitorMigrationParamsPtr migParams)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
- int ret = -1;
-
- if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
- return -1;
-
- if (qemuMonitorSetMigrationParams(priv->mon, migParams) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- ret = -1;
-
- return ret;
-}
-
-
-/* qemuMigrationParamsResetTLS
- * @driver: pointer to qemu driver
- * @vm: domain object
- * @asyncJob: migration job to join
- *
- * Deconstruct all the setup possibly done for TLS - delete the TLS and
- * security objects, free the secinfo, and reset the migration params to "".
- *
- * Returns 0 on success, -1 on failure
- */
-static int
-qemuMigrationParamsResetTLS(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob asyncJob)
-{
- qemuDomainObjPrivatePtr priv = vm->privateData;
- char *tlsAlias = NULL;
- char *secAlias = NULL;
- qemuMonitorMigrationParams migParams = { 0 };
- int ret = -1;
-
- if (qemuMigrationParamsCheckTLSCreds(driver, vm, asyncJob) < 0)
- return -1;
-
- /* If the tls-creds doesn't exist or if they're set to "" then
there's
- * nothing to do since we never set anything up */
- if (!priv->migTLSAlias || !*priv->migTLSAlias)
- return 0;
-
- /* NB: If either or both fail to allocate memory we can still proceed
- * since the next time we migrate another deletion attempt will be
- * made after successfully generating the aliases. */
- tlsAlias = qemuAliasTLSObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE);
- secAlias = qemuDomainGetSecretAESAlias(QEMU_MIGRATION_TLS_ALIAS_BASE, false);
-
- qemuDomainDelTLSObjects(driver, vm, asyncJob, secAlias, tlsAlias);
- qemuDomainSecretInfoFree(&priv->migSecinfo);
-
- if (VIR_STRDUP(migParams.tlsCreds, "") < 0 ||
- VIR_STRDUP(migParams.tlsHostname, "") < 0 ||
- qemuMigrationParamsSet(driver, vm, asyncJob, &migParams) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- VIR_FREE(tlsAlias);
- VIR_FREE(secAlias);
- qemuMigrationParamsClear(&migParams);
-
- return ret;
-}
-
-
static int
qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
virConnectPtr dconn,
@@ -6077,40 +5694,6 @@ qemuMigrationAnyCompressionDump(qemuMigrationCompressionPtr
compression,
}
-/*
- * qemuMigrationParamsReset:
- *
- * Reset all migration parameters so that the next job which internally uses
- * migration (save, managedsave, snapshots, dump) will not try to use them.
- */
-void
-qemuMigrationParamsReset(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob job)
-{
- qemuMonitorMigrationCaps cap;
- virErrorPtr err = virSaveLastError();
-
- if (!virDomainObjIsActive(vm))
- goto cleanup;
-
- if (qemuMigrationParamsResetTLS(driver, vm, job) < 0)
- goto cleanup;
-
- for (cap = 0; cap < QEMU_MONITOR_MIGRATION_CAPS_LAST; cap++) {
- if (qemuMigrationCapsGet(vm, cap) &&
- qemuMigrationOptionSet(driver, vm, cap, false, job) < 0)
- goto cleanup;
- }
-
- cleanup:
- if (err) {
- virSetError(err);
- virFreeError(err);
- }
-}
-
-
int
qemuMigrationSrcFetchMirrorStats(virQEMUDriverPtr driver,
virDomainObjPtr vm,
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index b9f7369784..7342517ca6 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -34,7 +34,6 @@
*
* Exceptions:
*
- * - qemuMigrationParamsXXX - runs on source or dest host
* - qemuMigrationOptionXXX - runs on source or dest host
* - qemuMigrationJobXXX - runs on source or dest host
* - qemuMigrationCapsXXX - runs on source or dest host
@@ -137,17 +136,6 @@ qemuMigrationAnyCompressionDump(qemuMigrationCompressionPtr
compression,
int *maxparams,
unsigned long *flags);
-void
-qemuMigrationParamsClear(qemuMonitorMigrationParamsPtr migParams);
-
-void
-qemuMigrationParamsFree(qemuMonitorMigrationParamsPtr *migParams);
-
-qemuMonitorMigrationParamsPtr
-qemuMigrationParamsFromFlags(virTypedParameterPtr params,
- int nparams,
- unsigned long flags);
-
int
qemuMigrationSrcSetOffline(virQEMUDriverPtr driver,
virDomainObjPtr vm);
@@ -298,11 +286,6 @@ void
qemuMigrationAnyPostcopyFailed(virQEMUDriverPtr driver,
virDomainObjPtr vm);
-void
-qemuMigrationParamsReset(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- qemuDomainAsyncJob job);
-
int
qemuMigrationSrcFetchMirrorStats(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -318,4 +301,11 @@ bool
qemuMigrationCapsGet(virDomainObjPtr vm,
qemuMonitorMigrationCaps cap);
+int
+qemuMigrationOptionSet(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuMonitorMigrationCaps capability,
+ bool state,
+ qemuDomainAsyncJob job);
+
#endif /* __QEMU_MIGRATION_H__ */
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
new file mode 100644
index 0000000000..72ecafd057
--- /dev/null
+++ b/src/qemu/qemu_migration_params.c
@@ -0,0 +1,454 @@
+/*
+ * qemu_migration_params.c: QEMU migration parameters handling
+ *
+ * Copyright (C) 2006-2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "virlog.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virstring.h"
+
+#include "qemu_alias.h"
+#include "qemu_hotplug.h"
+#include "qemu_migration.h"
+#include "qemu_migration_params.h"
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
+
+VIR_LOG_INIT("qemu.qemu_migration_params");
+
+#define QEMU_MIGRATION_TLS_ALIAS_BASE "libvirt_migrate"
+
+
+void
+qemuMigrationParamsClear(qemuMonitorMigrationParamsPtr migParams)
+{
+ if (!migParams)
+ return;
+
+ VIR_FREE(migParams->tlsCreds);
+ VIR_FREE(migParams->tlsHostname);
+}
+
+
+void
+qemuMigrationParamsFree(qemuMonitorMigrationParamsPtr *migParams)
+{
+ if (!*migParams)
+ return;
+
+ qemuMigrationParamsClear(*migParams);
+ VIR_FREE(*migParams);
+}
+
+
+qemuMonitorMigrationParamsPtr
+qemuMigrationParamsFromFlags(virTypedParameterPtr params,
+ int nparams,
+ unsigned long flags)
+{
+ qemuMonitorMigrationParamsPtr migParams;
+
+ if (VIR_ALLOC(migParams) < 0)
+ return NULL;
+
+ if (!params)
+ return migParams;
+
+#define GET(PARAM, VAR) \
+ do { \
+ int rc; \
+ if ((rc = virTypedParamsGetInt(params, nparams, \
+ VIR_MIGRATE_PARAM_ ## PARAM, \
+ &migParams->VAR)) < 0) \
+ goto error; \
+ \
+ if (rc == 1) \
+ migParams->VAR ## _set = true; \
+ } while (0)
+
+ GET(AUTO_CONVERGE_INITIAL, cpuThrottleInitial);
+ GET(AUTO_CONVERGE_INCREMENT, cpuThrottleIncrement);
+
+#undef GET
+
+ if ((migParams->cpuThrottleInitial_set ||
+ migParams->cpuThrottleIncrement_set) &&
+ !(flags & VIR_MIGRATE_AUTO_CONVERGE)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Turn auto convergence on to tune it"));
+ goto error;
+ }
+
+ return migParams;
+
+ error:
+ qemuMigrationParamsFree(&migParams);
+ return NULL;
+}
+
+
+int
+qemuMigrationParamsSet(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob,
+ qemuMonitorMigrationParamsPtr migParams)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret = -1;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ if (qemuMonitorSetMigrationParams(priv->mon, migParams) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ ret = -1;
+
+ return ret;
+}
+
+
+/* qemuMigrationParamsCheckTLSCreds
+ * @driver: pointer to qemu driver
+ * @vm: domain object
+ * @asyncJob: migration job to join
+ *
+ * Query the migration parameters looking for the 'tls-creds' parameter.
+ * If found, then we can support setting or clearing the parameters and thus
+ * can support TLS for migration.
+ *
+ * Returns 0 if we were able to successfully fetch the params and
+ * additionally if the tls-creds parameter exists, saves it in the
+ * private domain structure. Returns -1 on failure.
+ */
+static int
+qemuMigrationParamsCheckTLSCreds(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuMonitorMigrationParams migParams = { 0 };
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ if (qemuMonitorGetMigrationParams(priv->mon, &migParams) < 0)
+ goto cleanup;
+
+ /* NB: Could steal NULL pointer too! Let caller decide what to do. */
+ VIR_STEAL_PTR(priv->migTLSAlias, migParams.tlsCreds);
+
+ ret = 0;
+
+ cleanup:
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ ret = -1;
+
+ qemuMigrationParamsClear(&migParams);
+
+ return ret;
+}
+
+
+/* qemuMigrationParamsCheckSetupTLS
+ * @driver: pointer to qemu driver
+ * @vm: domain object
+ * @cfg: configuration pointer
+ * @asyncJob: migration job to join
+ *
+ * Check if TLS is possible and set up the environment. Assumes the caller
+ * desires to use TLS (e.g. caller found VIR_MIGRATE_TLS flag).
+ *
+ * Ensure the qemu.conf has been properly configured to add an entry for
+ * "migrate_tls_x509_cert_dir". Also check if the "tls-creds"
parameter
+ * was present from a query of migration parameters
+ *
+ * Returns 0 on success, -1 on error/failure
+ */
+int
+qemuMigrationParamsCheckSetupTLS(virQEMUDriverPtr driver,
+ virQEMUDriverConfigPtr cfg,
+ virDomainObjPtr vm,
+ int asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ if (!cfg->migrateTLSx509certdir) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("host migration TLS directory not configured"));
+ return -1;
+ }
+
+ if (qemuMigrationParamsCheckTLSCreds(driver, vm, asyncJob) < 0)
+ return -1;
+
+ if (!priv->migTLSAlias) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("TLS migration is not supported with this "
+ "QEMU binary"));
+ return -1;
+ }
+
+ /* If there's a secret, then grab/store it now using the connection */
+ if (cfg->migrateTLSx509secretUUID &&
+ !(priv->migSecinfo =
+ qemuDomainSecretInfoTLSNew(priv, QEMU_MIGRATION_TLS_ALIAS_BASE,
+ cfg->migrateTLSx509secretUUID)))
+ return -1;
+
+ return 0;
+}
+
+
+/* qemuMigrationParamsAddTLSObjects
+ * @driver: pointer to qemu driver
+ * @vm: domain object
+ * @cfg: configuration pointer
+ * @tlsListen: server or client
+ * @asyncJob: Migration job to join
+ * @tlsAlias: alias to be generated for TLS object
+ * @secAlias: alias to be generated for a secinfo object
+ * @migParams: migration parameters to set
+ *
+ * Create the TLS objects for the migration and set the migParams value
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+qemuMigrationParamsAddTLSObjects(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virQEMUDriverConfigPtr cfg,
+ bool tlsListen,
+ int asyncJob,
+ char **tlsAlias,
+ char **secAlias,
+ qemuMonitorMigrationParamsPtr migParams)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virJSONValuePtr tlsProps = NULL;
+ virJSONValuePtr secProps = NULL;
+
+ if (qemuDomainGetTLSObjects(priv->qemuCaps, priv->migSecinfo,
+ cfg->migrateTLSx509certdir, tlsListen,
+ cfg->migrateTLSx509verify,
+ QEMU_MIGRATION_TLS_ALIAS_BASE,
+ &tlsProps, tlsAlias, &secProps, secAlias) <
0)
+ goto error;
+
+ /* Ensure the domain doesn't already have the TLS objects defined...
+ * This should prevent any issues just in case some cleanup wasn't
+ * properly completed (both src and dst use the same alias) or
+ * some other error path between now and perform . */
+ qemuDomainDelTLSObjects(driver, vm, asyncJob, *secAlias, *tlsAlias);
+
+ if (qemuDomainAddTLSObjects(driver, vm, asyncJob, *secAlias, &secProps,
+ *tlsAlias, &tlsProps) < 0)
+ goto error;
+
+ if (VIR_STRDUP(migParams->tlsCreds, *tlsAlias) < 0)
+ goto error;
+
+ return 0;
+
+ error:
+ virJSONValueFree(tlsProps);
+ virJSONValueFree(secProps);
+ return -1;
+}
+
+
+/* qemuMigrationParamsSetEmptyTLS
+ * @driver: pointer to qemu driver
+ * @vm: domain object
+ * @asyncJob: migration job to join
+ * @migParams: Pointer to a migration parameters block
+ *
+ * If we support setting the tls-creds, then set both tls-creds and
+ * tls-hostname to the empty string ("") which indicates to not use
+ * TLS on this migration.
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+qemuMigrationParamsSetEmptyTLS(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob,
+ qemuMonitorMigrationParamsPtr migParams)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ if (qemuMigrationParamsCheckTLSCreds(driver, vm, asyncJob) < 0)
+ return -1;
+
+ if (!priv->migTLSAlias)
+ return 0;
+
+ if (VIR_STRDUP(migParams->tlsCreds, "") < 0 ||
+ VIR_STRDUP(migParams->tlsHostname, "") < 0)
+ return -1;
+
+ return 0;
+}
+
+
+int
+qemuMigrationParamsSetCompression(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob,
+ qemuMigrationCompressionPtr compression,
+ qemuMonitorMigrationParamsPtr migParams)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+
+ if (qemuMigrationOptionSet(driver, vm,
+ QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
+ compression->methods &
+ (1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE),
+ asyncJob) < 0)
+ return -1;
+
+ if (qemuMigrationOptionSet(driver, vm,
+ QEMU_MONITOR_MIGRATION_CAPS_COMPRESS,
+ compression->methods &
+ (1ULL << QEMU_MIGRATION_COMPRESS_MT),
+ asyncJob) < 0)
+ return -1;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ migParams->compressLevel_set = compression->level_set;
+ migParams->compressLevel = compression->level;
+
+ migParams->compressThreads_set = compression->threads_set;
+ migParams->compressThreads = compression->threads;
+
+ migParams->decompressThreads_set = compression->dthreads_set;
+ migParams->decompressThreads = compression->dthreads;
+
+ if (compression->xbzrle_cache_set &&
+ qemuMonitorSetMigrationCacheSize(priv->mon,
+ compression->xbzrle_cache) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ ret = -1;
+
+ return ret;
+}
+
+
+/* qemuMigrationParamsResetTLS
+ * @driver: pointer to qemu driver
+ * @vm: domain object
+ * @asyncJob: migration job to join
+ *
+ * Deconstruct all the setup possibly done for TLS - delete the TLS and
+ * security objects, free the secinfo, and reset the migration params to "".
+ *
+ * Returns 0 on success, -1 on failure
+ */
+static int
+qemuMigrationParamsResetTLS(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ char *tlsAlias = NULL;
+ char *secAlias = NULL;
+ qemuMonitorMigrationParams migParams = { 0 };
+ int ret = -1;
+
+ if (qemuMigrationParamsCheckTLSCreds(driver, vm, asyncJob) < 0)
+ return -1;
+
+ /* If the tls-creds doesn't exist or if they're set to "" then
there's
+ * nothing to do since we never set anything up */
+ if (!priv->migTLSAlias || !*priv->migTLSAlias)
+ return 0;
+
+ /* NB: If either or both fail to allocate memory we can still proceed
+ * since the next time we migrate another deletion attempt will be
+ * made after successfully generating the aliases. */
+ tlsAlias = qemuAliasTLSObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE);
+ secAlias = qemuDomainGetSecretAESAlias(QEMU_MIGRATION_TLS_ALIAS_BASE, false);
+
+ qemuDomainDelTLSObjects(driver, vm, asyncJob, secAlias, tlsAlias);
+ qemuDomainSecretInfoFree(&priv->migSecinfo);
+
+ if (VIR_STRDUP(migParams.tlsCreds, "") < 0 ||
+ VIR_STRDUP(migParams.tlsHostname, "") < 0 ||
+ qemuMigrationParamsSet(driver, vm, asyncJob, &migParams) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(tlsAlias);
+ VIR_FREE(secAlias);
+ qemuMigrationParamsClear(&migParams);
+
+ return ret;
+}
+
+
+/*
+ * qemuMigrationParamsReset:
+ *
+ * Reset all migration parameters so that the next job which internally uses
+ * migration (save, managedsave, snapshots, dump) will not try to use them.
+ */
+void
+qemuMigrationParamsReset(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob)
+{
+ qemuMonitorMigrationCaps cap;
+ virErrorPtr err = virSaveLastError();
+
+ if (!virDomainObjIsActive(vm))
+ goto cleanup;
+
+ if (qemuMigrationParamsResetTLS(driver, vm, asyncJob) < 0)
+ goto cleanup;
+
+ for (cap = 0; cap < QEMU_MONITOR_MIGRATION_CAPS_LAST; cap++) {
+ if (qemuMigrationCapsGet(vm, cap) &&
+ qemuMigrationOptionSet(driver, vm, cap, false, asyncJob) < 0)
+ goto cleanup;
+ }
+
+ cleanup:
+ if (err) {
+ virSetError(err);
+ virFreeError(err);
+ }
+}
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
new file mode 100644
index 0000000000..33b3c27e51
--- /dev/null
+++ b/src/qemu/qemu_migration_params.h
@@ -0,0 +1,82 @@
+/*
+ * qemu_migration_params.h: QEMU migration parameters handling
+ *
+ * Copyright (C) 2006-2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __QEMU_MIGRATION_PARAMS_H__
+# define __QEMU_MIGRATION_PARAMS_H__
+
+# include "internal.h"
+
+# include "qemu_monitor.h"
+# include "qemu_conf.h"
+
+
+qemuMonitorMigrationParamsPtr
+qemuMigrationParamsFromFlags(virTypedParameterPtr params,
+ int nparams,
+ unsigned long flags);
+
+void
+qemuMigrationParamsClear(qemuMonitorMigrationParamsPtr migParams);
+
+void
+qemuMigrationParamsFree(qemuMonitorMigrationParamsPtr *migParams);
+
+int
+qemuMigrationParamsSet(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob,
+ qemuMonitorMigrationParamsPtr migParams);
+
+int
+qemuMigrationParamsCheckSetupTLS(virQEMUDriverPtr driver,
+ virQEMUDriverConfigPtr cfg,
+ virDomainObjPtr vm,
+ int asyncJob);
+
+int
+qemuMigrationParamsAddTLSObjects(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virQEMUDriverConfigPtr cfg,
+ bool tlsListen,
+ int asyncJob,
+ char **tlsAlias,
+ char **secAlias,
+ qemuMonitorMigrationParamsPtr migParams);
+
+int
+qemuMigrationParamsSetEmptyTLS(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob,
+ qemuMonitorMigrationParamsPtr migParams);
+
+int
+qemuMigrationParamsSetCompression(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob,
+ qemuMigrationCompressionPtr compression,
+ qemuMonitorMigrationParamsPtr migParams);
+
+void
+qemuMigrationParamsReset(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob);
+
+#endif /* __QEMU_MIGRATION_PARAMS_H__ */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index df2db53a97..3a7f8ed105 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -45,6 +45,7 @@
#include "qemu_hostdev.h"
#include "qemu_hotplug.h"
#include "qemu_migration.h"
+#include "qemu_migration_params.h"
#include "qemu_interface.h"
#include "qemu_security.h"
--
2.17.0