qemu: Add support for sending capabilities in migration cookie

Some migration capabilities may be enabled automatically, but only if
both sides of migration support them. Thus we need to be able transfer
the list of supported migration capabilities in migration cookie.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Jiri Denemark 2018-04-06 10:18:52 +02:00
parent 0cd77cd18b
commit 40ced93b01
5 changed files with 183 additions and 6 deletions

View File

@ -1917,6 +1917,7 @@ qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver,
goto cleanup; goto cleanup;
if (qemuMigrationBakeCookie(mig, driver, vm, if (qemuMigrationBakeCookie(mig, driver, vm,
QEMU_MIGRATION_SOURCE,
cookieout, cookieoutlen, cookieout, cookieoutlen,
cookieFlags) < 0) cookieFlags) < 0)
goto cleanup; goto cleanup;
@ -2429,8 +2430,9 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
goto stopjob; goto stopjob;
done: done:
if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, if (qemuMigrationBakeCookie(mig, driver, vm,
cookieoutlen, cookieFlags) < 0) { QEMU_MIGRATION_DESTINATION,
cookieout, cookieoutlen, cookieFlags) < 0) {
/* We could tear down the whole guest here, but /* We could tear down the whole guest here, but
* cookie data is (so far) non-critical, so that * cookie data is (so far) non-critical, so that
* seems a little harsh. We'll just warn for now. * seems a little harsh. We'll just warn for now.
@ -3523,8 +3525,9 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver,
QEMU_MIGRATION_COOKIE_STATS; QEMU_MIGRATION_COOKIE_STATS;
if (qemuMigrationCookieAddPersistent(mig, &persistDef) < 0 || if (qemuMigrationCookieAddPersistent(mig, &persistDef) < 0 ||
qemuMigrationBakeCookie(mig, driver, vm, cookieout, qemuMigrationBakeCookie(mig, driver, vm,
cookieoutlen, cookieFlags) < 0) { QEMU_MIGRATION_SOURCE,
cookieout, cookieoutlen, cookieFlags) < 0) {
VIR_WARN("Unable to encode migration cookie"); VIR_WARN("Unable to encode migration cookie");
} }
@ -5019,7 +5022,9 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver,
priv->job.completed->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED; priv->job.completed->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED;
} }
if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, if (qemuMigrationBakeCookie(mig, driver, vm,
QEMU_MIGRATION_DESTINATION,
cookieout, cookieoutlen,
QEMU_MIGRATION_COOKIE_STATS) < 0) QEMU_MIGRATION_COOKIE_STATS) < 0)
VIR_WARN("Unable to encode migration cookie"); VIR_WARN("Unable to encode migration cookie");

View File

@ -33,6 +33,7 @@
#include "qemu_domain.h" #include "qemu_domain.h"
#include "qemu_migration_cookie.h" #include "qemu_migration_cookie.h"
#include "qemu_migration_params.h"
#define VIR_FROM_THIS VIR_FROM_QEMU #define VIR_FROM_THIS VIR_FROM_QEMU
@ -50,7 +51,8 @@ VIR_ENUM_IMPL(qemuMigrationCookieFlag,
"memory-hotplug", "memory-hotplug",
"cpu-hotplug", "cpu-hotplug",
"cpu", "cpu",
"allowReboot"); "allowReboot",
"capabilities");
static void static void
@ -94,6 +96,18 @@ qemuMigrationCookieNBDFree(qemuMigrationCookieNBDPtr nbd)
} }
static void
qemuMigrationCookieCapsFree(qemuMigrationCookieCapsPtr caps)
{
if (!caps)
return;
virBitmapFree(caps->supported);
virBitmapFree(caps->automatic);
VIR_FREE(caps);
}
void void
qemuMigrationCookieFree(qemuMigrationCookiePtr mig) qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
{ {
@ -112,6 +126,7 @@ qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
VIR_FREE(mig->lockDriver); VIR_FREE(mig->lockDriver);
VIR_FREE(mig->jobInfo); VIR_FREE(mig->jobInfo);
virCPUDefFree(mig->cpu); virCPUDefFree(mig->cpu);
qemuMigrationCookieCapsFree(mig->caps);
VIR_FREE(mig); VIR_FREE(mig);
} }
@ -550,6 +565,33 @@ qemuMigrationCookieAddAllowReboot(qemuMigrationCookiePtr mig,
} }
static int
qemuMigrationCookieAddCaps(qemuMigrationCookiePtr mig,
virDomainObjPtr vm,
qemuMigrationParty party)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuMigrationCookieCapsFree(mig->caps);
if (VIR_ALLOC(mig->caps) < 0)
return -1;
if (priv->migrationCaps)
mig->caps->supported = virBitmapNewCopy(priv->migrationCaps);
else
mig->caps->supported = virBitmapNew(0);
mig->caps->automatic = qemuMigrationParamsGetAlwaysOnCaps(party);
if (!mig->caps->supported || !mig->caps->automatic)
return -1;
mig->flags |= QEMU_MIGRATION_COOKIE_CAPS;
return 0;
}
static void static void
qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf, qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
qemuMigrationCookieGraphicsPtr grap) qemuMigrationCookieGraphicsPtr grap)
@ -710,6 +752,33 @@ qemuMigrationCookieStatisticsXMLFormat(virBufferPtr buf,
} }
static void
qemuMigrationCookieCapsXMLFormat(virBufferPtr buf,
qemuMigrationCookieCapsPtr caps)
{
qemuMigrationCapability cap;
virBufferAddLit(buf, "<capabilities>\n");
virBufferAdjustIndent(buf, 2);
for (cap = 0; cap < QEMU_MIGRATION_CAP_LAST; cap++) {
bool supported = false;
bool automatic = false;
ignore_value(virBitmapGetBit(caps->supported, cap, &supported));
ignore_value(virBitmapGetBit(caps->automatic, cap, &automatic));
if (supported) {
virBufferAsprintf(buf, "<cap name='%s' auto='%s'/>\n",
qemuMigrationCapabilityTypeToString(cap),
automatic ? "yes" : "no");
}
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</capabilities>\n");
}
static int static int
qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver, qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
virBufferPtr buf, virBufferPtr buf,
@ -793,6 +862,9 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
if (mig->flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT) if (mig->flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT)
qemuDomainObjPrivateXMLFormatAllowReboot(buf, mig->allowReboot); qemuDomainObjPrivateXMLFormatAllowReboot(buf, mig->allowReboot);
if (mig->flags & QEMU_MIGRATION_COOKIE_CAPS)
qemuMigrationCookieCapsXMLFormat(buf, mig->caps);
virBufferAdjustIndent(buf, -2); virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</qemu-migration>\n"); virBufferAddLit(buf, "</qemu-migration>\n");
return 0; return 0;
@ -1067,6 +1139,59 @@ qemuMigrationCookieStatisticsXMLParse(xmlXPathContextPtr ctxt)
} }
static qemuMigrationCookieCapsPtr
qemuMigrationCookieCapsXMLParse(xmlXPathContextPtr ctxt)
{
qemuMigrationCookieCapsPtr caps = NULL;
xmlNodePtr *nodes = NULL;
qemuMigrationCookieCapsPtr ret = NULL;
char *name = NULL;
char *automatic = NULL;
int cap;
size_t i;
int n;
if (VIR_ALLOC(caps) < 0)
return NULL;
if (!(caps->supported = virBitmapNew(QEMU_MIGRATION_CAP_LAST)) ||
!(caps->automatic = virBitmapNew(QEMU_MIGRATION_CAP_LAST)))
goto cleanup;
if ((n = virXPathNodeSet("./capabilities[1]/cap", ctxt, &nodes)) < 0)
goto cleanup;
for (i = 0; i < n; i++) {
if (!(name = virXMLPropString(nodes[i], "name"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing migration capability name"));
goto cleanup;
}
if ((cap = qemuMigrationCapabilityTypeFromString(name)) < 0)
VIR_DEBUG("unknown migration capability '%s'", name);
else
ignore_value(virBitmapSetBit(caps->supported, cap));
if ((automatic = virXMLPropString(nodes[i], "auto")) &&
STREQ(automatic, "yes"))
ignore_value(virBitmapSetBit(caps->automatic, cap));
VIR_FREE(name);
VIR_FREE(automatic);
}
VIR_STEAL_PTR(ret, caps);
cleanup:
qemuMigrationCookieCapsFree(caps);
VIR_FREE(nodes);
VIR_FREE(name);
VIR_FREE(automatic);
return ret;
}
static int static int
qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
virQEMUDriverPtr driver, virQEMUDriverPtr driver,
@ -1246,6 +1371,10 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
qemuDomainObjPrivateXMLParseAllowReboot(ctxt, &mig->allowReboot) < 0) qemuDomainObjPrivateXMLParseAllowReboot(ctxt, &mig->allowReboot) < 0)
goto error; goto error;
if (flags & QEMU_MIGRATION_COOKIE_CAPS &&
!(mig->caps = qemuMigrationCookieCapsXMLParse(ctxt)))
goto error;
virObjectUnref(caps); virObjectUnref(caps);
return 0; return 0;
@ -1286,6 +1415,7 @@ int
qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
virQEMUDriverPtr driver, virQEMUDriverPtr driver,
virDomainObjPtr dom, virDomainObjPtr dom,
qemuMigrationParty party,
char **cookieout, char **cookieout,
int *cookieoutlen, int *cookieoutlen,
unsigned int flags) unsigned int flags)
@ -1329,6 +1459,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
if (flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT) if (flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT)
qemuMigrationCookieAddAllowReboot(mig, dom); qemuMigrationCookieAddAllowReboot(mig, dom);
if (flags & QEMU_MIGRATION_COOKIE_CAPS &&
qemuMigrationCookieAddCaps(mig, dom, party) < 0)
return -1;
if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig))) if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
return -1; return -1;

View File

@ -19,6 +19,8 @@
#ifndef __QEMU_MIGRATION_COOKIE_H__ #ifndef __QEMU_MIGRATION_COOKIE_H__
# define __QEMU_MIGRATION_COOKIE_H__ # define __QEMU_MIGRATION_COOKIE_H__
# include "qemu_migration_params.h"
typedef enum { typedef enum {
QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS, QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE, QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
@ -30,6 +32,7 @@ typedef enum {
QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG, QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG,
QEMU_MIGRATION_COOKIE_FLAG_CPU, QEMU_MIGRATION_COOKIE_FLAG_CPU,
QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT, QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT,
QEMU_MIGRATION_COOKIE_FLAG_CAPS,
QEMU_MIGRATION_COOKIE_FLAG_LAST QEMU_MIGRATION_COOKIE_FLAG_LAST
} qemuMigrationCookieFlags; } qemuMigrationCookieFlags;
@ -47,6 +50,7 @@ typedef enum {
QEMU_MIGRATION_COOKIE_CPU_HOTPLUG = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG), QEMU_MIGRATION_COOKIE_CPU_HOTPLUG = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG),
QEMU_MIGRATION_COOKIE_CPU = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU), QEMU_MIGRATION_COOKIE_CPU = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU),
QEMU_MIGRATION_COOKIE_ALLOW_REBOOT = (1 << QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT), QEMU_MIGRATION_COOKIE_ALLOW_REBOOT = (1 << QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT),
QEMU_MIGRATION_COOKIE_CAPS = (1 << QEMU_MIGRATION_COOKIE_FLAG_CAPS),
} qemuMigrationCookieFeatures; } qemuMigrationCookieFeatures;
typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@ -92,6 +96,13 @@ struct _qemuMigrationCookieNBD {
} *disks; } *disks;
}; };
typedef struct _qemuMigrationCookieCaps qemuMigrationCookieCaps;
typedef qemuMigrationCookieCaps *qemuMigrationCookieCapsPtr;
struct _qemuMigrationCookieCaps {
virBitmapPtr supported;
virBitmapPtr automatic;
};
typedef struct _qemuMigrationCookie qemuMigrationCookie; typedef struct _qemuMigrationCookie qemuMigrationCookie;
typedef qemuMigrationCookie *qemuMigrationCookiePtr; typedef qemuMigrationCookie *qemuMigrationCookiePtr;
struct _qemuMigrationCookie { struct _qemuMigrationCookie {
@ -132,6 +143,9 @@ struct _qemuMigrationCookie {
/* If flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT */ /* If flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT */
virTristateBool allowReboot; virTristateBool allowReboot;
/* If flags & QEMU_MIGRATION_COOKIE_CAPS */
qemuMigrationCookieCapsPtr caps;
}; };
@ -139,6 +153,7 @@ int
qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
virQEMUDriverPtr driver, virQEMUDriverPtr driver,
virDomainObjPtr dom, virDomainObjPtr dom,
qemuMigrationParty party,
char **cookieout, char **cookieout,
int *cookieoutlen, int *cookieoutlen,
unsigned int flags); unsigned int flags);

View File

@ -153,6 +153,26 @@ static const qemuMigrationParamType qemuMigrationParamTypes[] = {
verify(ARRAY_CARDINALITY(qemuMigrationParamTypes) == QEMU_MIGRATION_PARAM_LAST); verify(ARRAY_CARDINALITY(qemuMigrationParamTypes) == QEMU_MIGRATION_PARAM_LAST);
virBitmapPtr
qemuMigrationParamsGetAlwaysOnCaps(qemuMigrationParty party)
{
virBitmapPtr caps = NULL;
size_t i;
if (!(caps = virBitmapNew(QEMU_MIGRATION_CAP_LAST)))
return NULL;
for (i = 0; i < ARRAY_CARDINALITY(qemuMigrationParamsAlwaysOn); i++) {
if (!(qemuMigrationParamsAlwaysOn[i].party & party))
continue;
ignore_value(virBitmapSetBit(caps, qemuMigrationParamsAlwaysOn[i].cap));
}
return caps;
}
static qemuMigrationParamsPtr static qemuMigrationParamsPtr
qemuMigrationParamsNew(void) qemuMigrationParamsNew(void)
{ {

View File

@ -65,6 +65,9 @@ typedef enum {
} qemuMigrationParty; } qemuMigrationParty;
virBitmapPtr
qemuMigrationParamsGetAlwaysOnCaps(qemuMigrationParty party);
qemuMigrationParamsPtr qemuMigrationParamsPtr
qemuMigrationParamsFromFlags(virTypedParameterPtr params, qemuMigrationParamsFromFlags(virTypedParameterPtr params,
int nparams, int nparams,