The migration protocol has support for a 'cookie' parameter which
is an opaque array of bytes as far as libvirt is concerned. Drivers
may use this for passing around arbitrary extra data they might
need during migration. The QEMU driver needs todo a few things:
- Pass hostname/uuid to allow strict protection against localhost
migration attempts
- Pass SPICE/VNC server port from the target back to the source to
allow seemless relocation of client sessions
- Pass lock driver state from source to destination
This patch introduces the basic glue for handling cookies
but only includes the host/guest UUID & name.
* src/libvirt_private.syms: Export virXMLParseStrHelper
* src/qemu/qemu_migration.c, src/qemu/qemu_migration.h: Parsing
and formatting of migration cookies
* src/qemu/qemu_driver.c: Pass in cookie parameters where possible
* src/remote/remote_protocol.h, src/remote/remote_protocol.x: Change
cookie max length to 16384 bytes
---
cfg.mk | 1 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 20 ++-
src/qemu/qemu_migration.c | 351 +++++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_migration.h | 16 ++
src/remote/remote_protocol.h | 2 +-
src/remote/remote_protocol.x | 2 +-
7 files changed, 378 insertions(+), 15 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index 72dd69c..92974a9 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -72,6 +72,7 @@ VC_LIST_ALWAYS_EXCLUDE_REGEX = ^(HACKING|docs/news\.html\.in)$$
useless_free_options = \
--name=VIR_FREE \
--name=qemuCapsFree \
+ --name=qemuMigrationCookieFree \
--name=sexpr_free \
--name=virBitmapFree \
--name=virCPUDefFree \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7471e25..b787811 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -994,6 +994,7 @@ virStrerror;
# xml.h
+virXMLParseStrHelper;
virXMLPropString;
virXPathBoolean;
virXPathInt;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e6c7599..f382a24 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5452,8 +5452,9 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
}
qemuDriverLock(driver);
- ret = qemuMigrationPrepareTunnel(driver, dconn, st,
- dname, dom_xml);
+ ret = qemuMigrationPrepareTunnel(driver, dconn,
+ NULL, 0, NULL, NULL, /* No cookies in v2 */
+ st, dname, dom_xml);
qemuDriverUnlock(driver);
cleanup:
@@ -5466,8 +5467,8 @@ cleanup:
*/
static int ATTRIBUTE_NONNULL (5)
qemudDomainMigratePrepare2 (virConnectPtr dconn,
- char **cookie ATTRIBUTE_UNUSED,
- int *cookielen ATTRIBUTE_UNUSED,
+ char **cookie,
+ int *cookielen,
const char *uri_in,
char **uri_out,
unsigned long flags,
@@ -5506,6 +5507,8 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
}
ret = qemuMigrationPrepareDirect(driver, dconn,
+ NULL, 0, /* No input cookies in v2 */
+ cookie, cookielen,
uri_in, uri_out,
dname, dom_xml);
@@ -5549,8 +5552,9 @@ qemudDomainMigratePerform (virDomainPtr dom,
}
ret = qemuMigrationPerform(driver, dom->conn, vm,
- uri, flags,
- dname, resource);
+ uri, cookie, cookielen,
+ NULL, NULL, /* No output cookies in v2 */
+ flags, dname, resource);
cleanup:
qemuDriverUnlock(driver);
@@ -5593,7 +5597,9 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
goto cleanup;
}
- dom = qemuMigrationFinish(driver, dconn, vm, flags, retcode);
+ dom = qemuMigrationFinish(driver, dconn, vm,
+ NULL, 0, NULL, NULL, /* No cookies in v2 */
+ flags, retcode);
cleanup:
if (orig_err) {
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 7f4b111..98773c0 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -22,6 +22,8 @@
#include <config.h>
#include <sys/time.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
#include "qemu_migration.h"
#include "qemu_monitor.h"
@@ -38,11 +40,271 @@
#include "files.h"
#include "datatypes.h"
#include "fdstream.h"
+#include "uuid.h"
+
#define VIR_FROM_THIS VIR_FROM_QEMU
#define timeval_to_ms(tv) (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000))
+typedef struct _qemuMigrationCookie qemuMigrationCookie;
+typedef qemuMigrationCookie *qemuMigrationCookiePtr;
+struct _qemuMigrationCookie {
+ int flags;
+
+ /* Host properties */
+ unsigned char hostuuid[VIR_UUID_BUFLEN];
+ char *hostname;
+
+ /* Guest properties */
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ char *name;
+};
+
+
+static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
+{
+ if (!mig)
+ return;
+
+ VIR_FREE(mig->hostname);
+ VIR_FREE(mig->name);
+ VIR_FREE(mig);
+}
+
+
+static qemuMigrationCookiePtr
+qemuMigrationCookieNew(virDomainObjPtr dom)
+{
+ qemuMigrationCookiePtr mig = NULL;
+
+ if (VIR_ALLOC(mig) < 0)
+ goto no_memory;
+
+ if (!(mig->name = strdup(dom->def->name)))
+ goto no_memory;
+ memcpy(mig->uuid, dom->def->uuid, VIR_UUID_BUFLEN);
+
+ if (!(mig->hostname = virGetHostname(NULL)))
+ goto no_memory;
+ if (virGetHostUUID(mig->hostuuid) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to obtain host UUID"));
+ goto error;
+ }
+
+ return mig;
+
+no_memory:
+ virReportOOMError();
+error:
+ qemuMigrationCookieFree(mig);
+ return NULL;
+}
+
+
+static void qemuMigrationCookieXMLFormat(virBufferPtr buf,
+ qemuMigrationCookiePtr mig)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char hostuuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(mig->uuid, uuidstr);
+ virUUIDFormat(mig->hostuuid, hostuuidstr);
+
+ virBufferVSprintf(buf, "<qemu-migration>\n");
+ virBufferEscapeString(buf, " <name>%s</name>\n",
mig->name);
+ virBufferVSprintf(buf, " <uuid>%s</uuid>\n", uuidstr);
+ virBufferEscapeString(buf, " <hostname>%s</hostname>\n",
mig->hostname);
+ virBufferVSprintf(buf, " <hostuuid>%s</hostuuid>\n",
hostuuidstr);
+ virBufferAddLit(buf, "</qemu-migration>\n");
+}
+
+
+static char *qemuMigrationCookieXMLFormatStr(qemuMigrationCookiePtr mig)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ qemuMigrationCookieXMLFormat(&buf, mig);
+
+ if (virBufferError(&buf)) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return virBufferContentAndReset(&buf);
+}
+
+
+static int
+qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
+ xmlXPathContextPtr ctxt,
+ int flags ATTRIBUTE_UNUSED)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *tmp;
+
+ /* We don't store the uuid, name, hostname, or hostuuid
+ * values. We just compare them to local data todo some
+ * sanity checking on migration operation
+ */
+
+ /* Extract domain name */
+ if (!(tmp = virXPathString("string(./name[1])", ctxt))) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing name element in migration
data"));
+ goto error;
+ }
+ if (STRNEQ(tmp, mig->name)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Incoming cookie data had unexpected name %s vs
%s"),
+ tmp, mig->name);
+ goto error;
+ }
+ VIR_FREE(tmp);
+
+ /* Extract domain uuid */
+ tmp = virXPathString("string(./uuid[1])", ctxt);
+ if (!tmp) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing uuid element in migration
data"));
+ goto error;
+ }
+ virUUIDFormat(mig->uuid, uuidstr);
+ if (STRNEQ(tmp, uuidstr)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Incoming cookie data had unexpected UUID %s vs
%s"),
+ tmp, uuidstr);
+ }
+ VIR_FREE(tmp);
+
+ /* Check & forbid "localhost" migration */
+ if (!(tmp = virXPathString("string(./hostname[1])", ctxt))) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing hostname element in migration
data"));
+ goto error;
+ }
+ if (STREQ(tmp, mig->hostname)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Attempt to migrate guest to the same host %s"),
+ tmp);
+ goto error;
+ }
+ VIR_FREE(tmp);
+
+ if (!(tmp = virXPathString("string(./hostuuid[1])", ctxt))) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing hostuuid element in migration
data"));
+ goto error;
+ }
+ virUUIDFormat(mig->hostuuid, uuidstr);
+ if (STREQ(tmp, uuidstr)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Attempt to migrate guest to the same host %s"),
+ tmp);
+ goto error;
+ }
+ VIR_FREE(tmp);
+
+ return 0;
+
+error:
+ VIR_FREE(tmp);
+ return -1;
+}
+
+
+static int
+qemuMigrationCookieXMLParseStr(qemuMigrationCookiePtr mig,
+ const char *xml,
+ int flags)
+{
+ xmlDocPtr doc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ int ret;
+
+ VIR_DEBUG("xml=%s", NULLSTR(xml));
+
+ if (!(doc = virXMLParseString(xml, "qemumigration.xml")))
+ goto cleanup;
+
+ if ((ctxt = xmlXPathNewContext(doc)) == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ctxt->node = xmlDocGetRootElement(doc);
+
+ ret = qemuMigrationCookieXMLParse(mig, ctxt, flags);
+
+cleanup:
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(doc);
+
+ return ret;
+}
+
+
+static int
+qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
+ struct qemud_driver *driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr dom ATTRIBUTE_UNUSED,
+ char **cookieout,
+ int *cookieoutlen,
+ int flags ATTRIBUTE_UNUSED)
+{
+ if (!cookieout || !cookieoutlen) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("missing migration cookie data"));
+ return -1;
+ }
+
+ *cookieoutlen = 0;
+
+ if (!(*cookieout = qemuMigrationCookieXMLFormatStr(mig)))
+ return -1;
+
+ *cookieoutlen = strlen(*cookieout) + 1;
+
+ VIR_DEBUG("cookielen=%d cookie=%s", *cookieoutlen, *cookieout);
+
+ return 0;
+}
+
+
+static qemuMigrationCookiePtr
+qemuMigrationEatCookie(virDomainObjPtr dom,
+ const char *cookiein,
+ int cookieinlen,
+ int flags)
+{
+ qemuMigrationCookiePtr mig = NULL;
+
+ /* Parse & validate incoming cookie (if any) */
+ if (cookiein && cookieinlen &&
+ cookiein[cookieinlen-1] != '\0') {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Migration cookie was not NULL terminated"));
+ goto error;
+ }
+
+ VIR_DEBUG("cookielen=%d cookie='%s'", cookieinlen,
NULLSTR(cookiein));
+
+ if (!(mig = qemuMigrationCookieNew(dom)))
+ return NULL;
+
+ if (cookiein && cookieinlen &&
+ qemuMigrationCookieXMLParseStr(mig,
+ cookiein,
+ flags) < 0)
+ goto error;
+
+ return mig;
+
+error:
+ qemuMigrationCookieFree(mig);
+ return NULL;
+}
bool
qemuMigrationIsAllowed(virDomainDefPtr def)
@@ -245,6 +507,10 @@ cleanup:
int
qemuMigrationPrepareTunnel(struct qemud_driver *driver,
virConnectPtr dconn,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
virStreamPtr st,
const char *dname,
const char *dom_xml)
@@ -258,6 +524,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver,
virBitmapPtr qemuCaps = NULL;
qemuDomainObjPrivatePtr priv = NULL;
struct timeval now;
+ qemuMigrationCookiePtr mig = NULL;
if (gettimeofday(&now, NULL) < 0) {
virReportSystemError(errno, "%s",
@@ -293,6 +560,9 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver,
def = NULL;
priv = vm->privateData;
+ if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0)))
+ goto cleanup;
+
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup;
priv->jobActive = QEMU_JOB_MIGRATION_OUT;
@@ -351,6 +621,15 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver,
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_MIGRATED);
+
+ if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) {
+ /* We could tear down the whole guest here, but
+ * cookie data is (so far) non-critical, so that
+ * seems a little harsh. We'll just warn for now..
+ */
+ VIR_WARN0("Unable to encode migration cookie");
+ }
+
ret = 0;
endjob:
@@ -379,7 +658,7 @@ cleanup:
virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
- qemuDriverUnlock(driver);
+ qemuMigrationCookieFree(mig);
return ret;
}
@@ -387,6 +666,10 @@ cleanup:
int
qemuMigrationPrepareDirect(struct qemud_driver *driver,
virConnectPtr dconn,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
const char *uri_in,
char **uri_out,
const char *dname,
@@ -404,6 +687,7 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver,
int internalret;
qemuDomainObjPrivatePtr priv = NULL;
struct timeval now;
+ qemuMigrationCookiePtr mig = NULL;
if (gettimeofday(&now, NULL) < 0) {
virReportSystemError(errno, "%s",
@@ -513,6 +797,9 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver,
def = NULL;
priv = vm->privateData;
+ if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0)))
+ goto cleanup;
+
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup;
priv->jobActive = QEMU_JOB_MIGRATION_OUT;
@@ -538,6 +825,14 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver,
goto endjob;
}
+ if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0) {
+ /* We could tear down the whole guest here, but
+ * cookie data is (so far) non-critical, so that
+ * seems a little harsh. We'll just warn for now..
+ */
+ VIR_WARN0("Unable to encode migration cookie");
+ }
+
qemuAuditDomainStart(vm, "migrated", true);
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED,
@@ -570,6 +865,7 @@ cleanup:
virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
+ qemuMigrationCookieFree(mig);
return ret;
}
@@ -580,6 +876,10 @@ cleanup:
static int doNativeMigrate(struct qemud_driver *driver,
virDomainObjPtr vm,
const char *uri,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
unsigned int flags,
const char *dname ATTRIBUTE_UNUSED,
unsigned long resource)
@@ -588,6 +888,10 @@ static int doNativeMigrate(struct qemud_driver *driver,
xmlURIPtr uribits = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
unsigned int background_flags = QEMU_MONITOR_MIGRATE_BACKGROUND;
+ qemuMigrationCookiePtr mig = NULL;
+
+ if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0)))
+ goto cleanup;
/* Issue the migrate command. */
if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://"))
{
@@ -631,9 +935,13 @@ static int doNativeMigrate(struct qemud_driver *driver,
if (qemuMigrationWaitForCompletion(driver, vm) < 0)
goto cleanup;
+ if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
+ VIR_WARN0("Unable to encode migration cookie");
+
ret = 0;
cleanup:
+ qemuMigrationCookieFree(mig);
xmlFreeURI(uribits);
return ret;
}
@@ -921,14 +1229,16 @@ static int doNonTunnelMigrate(struct qemud_driver *driver,
virDomainPtr ddomain = NULL;
int retval = -1;
char *uri_out = NULL;
+ char *cookie = NULL;
+ int cookielen = 0;
int rc;
qemuDomainObjEnterRemoteWithDriver(driver, vm);
/* NB we don't pass 'uri' into this, since that's the libvirtd
* URI in this context - so we let dest pick it */
rc = dconn->driver->domainMigratePrepare2(dconn,
- NULL, /* cookie */
- 0, /* cookielen */
+ &cookie,
+ &cookielen,
NULL, /* uri */
&uri_out,
flags, dname,
@@ -953,7 +1263,10 @@ static int doNonTunnelMigrate(struct qemud_driver *driver,
goto cleanup;
}
- if (doNativeMigrate(driver, vm, uri_out, flags, dname, resource) < 0)
+ if (doNativeMigrate(driver, vm, uri_out,
+ cookie, cookielen,
+ NULL, NULL, /* No out cookie with v2 migration */
+ flags, dname, resource) < 0)
goto finish;
retval = 0;
@@ -962,13 +1275,14 @@ finish:
dname = dname ? dname : vm->def->name;
qemuDomainObjEnterRemoteWithDriver(driver, vm);
ddomain = dconn->driver->domainMigrateFinish2
- (dconn, dname, NULL, 0, uri_out, flags, retval);
+ (dconn, dname, cookie, cookielen, uri_out, flags, retval);
qemuDomainObjExitRemoteWithDriver(driver, vm);
if (ddomain)
virUnrefDomain(ddomain);
cleanup:
+ VIR_FREE(cookie);
return retval;
}
@@ -1044,6 +1358,10 @@ int qemuMigrationPerform(struct qemud_driver *driver,
virConnectPtr conn,
virDomainObjPtr vm,
const char *uri,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
unsigned long flags,
const char *dname,
unsigned long resource)
@@ -1073,11 +1391,19 @@ int qemuMigrationPerform(struct qemud_driver *driver,
}
if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
+ if (cookieinlen) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("received unexpected cookie with P2P
migration"));
+ goto endjob;
+ }
+
if (doPeer2PeerMigrate(driver, vm, uri, flags, dname, resource) < 0)
/* doPeer2PeerMigrate already set the error, so just get out */
goto endjob;
} else {
- if (doNativeMigrate(driver, vm, uri, flags, dname, resource) < 0)
+ if (doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, dname, resource) < 0)
goto endjob;
}
@@ -1095,6 +1421,7 @@ int qemuMigrationPerform(struct qemud_driver *driver,
virDomainRemoveInactive(&driver->domains, vm);
vm = NULL;
}
+
ret = 0;
endjob:
@@ -1171,6 +1498,10 @@ virDomainPtr
qemuMigrationFinish(struct qemud_driver *driver,
virConnectPtr dconn,
virDomainObjPtr vm,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
unsigned long flags,
int retcode)
{
@@ -1178,6 +1509,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
virDomainEventPtr event = NULL;
int newVM = 1;
qemuDomainObjPrivatePtr priv = NULL;
+ qemuMigrationCookiePtr mig = NULL;
priv = vm->privateData;
if (priv->jobActive != QEMU_JOB_MIGRATION_IN) {
@@ -1188,6 +1520,9 @@ qemuMigrationFinish(struct qemud_driver *driver,
priv->jobActive = QEMU_JOB_NONE;
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
+ if (!(mig = qemuMigrationEatCookie(vm, cookiein, cookieinlen, 0)))
+ goto cleanup;
+
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup;
@@ -1273,6 +1608,9 @@ qemuMigrationFinish(struct qemud_driver *driver,
}
}
+ if (qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen, 0) < 0)
+ VIR_WARN0("Unable to encode migration cookie");
+
endjob:
if (vm &&
qemuDomainObjEndJob(vm) == 0)
@@ -1283,6 +1621,7 @@ cleanup:
virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
+ qemuMigrationCookieFree(mig);
return dom;
}
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index db16ce4..11571e7 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -34,12 +34,20 @@ int qemuMigrationWaitForCompletion(struct qemud_driver *driver,
virDomainObjPtr
int qemuMigrationPrepareTunnel(struct qemud_driver *driver,
virConnectPtr dconn,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
virStreamPtr st,
const char *dname,
const char *dom_xml);
int qemuMigrationPrepareDirect(struct qemud_driver *driver,
virConnectPtr dconn,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
const char *uri_in,
char **uri_out,
const char *dname,
@@ -49,6 +57,10 @@ int qemuMigrationPerform(struct qemud_driver *driver,
virConnectPtr conn,
virDomainObjPtr vm,
const char *uri,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
unsigned long flags,
const char *dname,
unsigned long resource);
@@ -56,6 +68,10 @@ int qemuMigrationPerform(struct qemud_driver *driver,
virDomainPtr qemuMigrationFinish(struct qemud_driver *driver,
virConnectPtr dconn,
virDomainObjPtr vm,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
unsigned long flags,
int retcode);
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index 385d431..0cd8601 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -43,7 +43,7 @@ typedef remote_nonnull_string *remote_string;
#define REMOTE_CPUMAP_MAX 256
#define REMOTE_VCPUINFO_MAX 2048
#define REMOTE_CPUMAPS_MAX 16384
-#define REMOTE_MIGRATE_COOKIE_MAX 256
+#define REMOTE_MIGRATE_COOKIE_MAX 16384
#define REMOTE_NETWORK_NAME_LIST_MAX 256
#define REMOTE_INTERFACE_NAME_LIST_MAX 256
#define REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX 256
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index a5d6fb2..2d7487e 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -99,7 +99,7 @@ const REMOTE_VCPUINFO_MAX = 2048;
const REMOTE_CPUMAPS_MAX = 16384;
/* Upper limit on migrate cookie. */
-const REMOTE_MIGRATE_COOKIE_MAX = 256;
+const REMOTE_MIGRATE_COOKIE_MAX = 16384;
/* Upper limit on lists of network names. */
const REMOTE_NETWORK_NAME_LIST_MAX = 256;
--
1.7.4.4