From 0eceb3bc1474c0220ac8e6b9f066e977a051b668 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Wed, 21 Feb 2018 14:18:03 +0100 Subject: [PATCH] qemu: New file for all APIs related to migration parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the end, this will allow us to have most of the logic around migration parameters and capabilities done in one place. Signed-off-by: Jiri Denemark Reviewed-by: Ján Tomko --- 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 0dcd1cab28..be2874487c 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 cf328c296a..45fe8dae5f 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 a0071cc089..34eb3eb9e5 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, @@ -2363,238 +2212,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, @@ -6074,40 +5691,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 3424404dc4..adf788c909 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 */ @@ -136,17 +135,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); @@ -297,11 +285,6 @@ void qemuMigrationAnyPostcopyFailed(virQEMUDriverPtr driver, virDomainObjPtr vm); -void -qemuMigrationParamsReset(virQEMUDriverPtr driver, - virDomainObjPtr vm, - qemuDomainAsyncJob job); - int qemuMigrationSrcFetchMirrorStats(virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -312,4 +295,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 + * . + * + */ + +#include + +#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 + * . + * + */ + +#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 c46a852db1..0530939214 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"