virQEMUDriverPtr driver = dconn->privateData;
virDomainDefPtr def = NULL;
char *origname = NULL;
+ qemuMigrationCompressionPtr compression = NULL;
int ret = -1;
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
goto cleanup;
}
+ if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+ goto cleanup;
+
if (virLockManagerPluginUsesState(driver->lockManager)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot use migrate v2 protocol with lock manager %s"),
ret = qemuMigrationPrepareDirect(driver, dconn,
NULL, 0, NULL, NULL, /* No cookies */
uri_in, uri_out,
- &def, origname, NULL, 0, NULL, 0, flags);
+ &def, origname, NULL, 0, NULL, 0,
+ compression, flags);
cleanup:
+ VIR_FREE(compression);
VIR_FREE(origname);
virDomainDefFree(def);
return ret;
virDomainObjPtr vm;
int ret = -1;
const char *dconnuri = NULL;
+ qemuMigrationCompressionPtr compression = NULL;
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
goto cleanup;
}
+ if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+ goto cleanup;
+
if (!(vm = qemuDomObjFromDomain(dom)))
goto cleanup;
*/
ret = qemuMigrationPerform(driver, dom->conn, vm,
NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0,
- cookie, cookielen,
+ compression, cookie, cookielen,
NULL, NULL, /* No output cookies in v2 */
flags, dname, resource, false);
cleanup:
+ VIR_FREE(compression);
return ret;
}
virQEMUDriverPtr driver = dconn->privateData;
virDomainDefPtr def = NULL;
char *origname = NULL;
+ qemuMigrationCompressionPtr compression = NULL;
int ret = -1;
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
goto cleanup;
}
+ if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+ goto cleanup;
+
if (!(def = qemuMigrationPrepareDef(driver, dom_xml, dname, &origname)))
goto cleanup;
cookiein, cookieinlen,
cookieout, cookieoutlen,
uri_in, uri_out,
- &def, origname, NULL, 0, NULL, 0, flags);
+ &def, origname, NULL, 0, NULL, 0,
+ compression, flags);
cleanup:
+ VIR_FREE(compression);
VIR_FREE(origname);
virDomainDefFree(def);
return ret;
int nmigrate_disks;
const char **migrate_disks = NULL;
char *origname = NULL;
+ qemuMigrationCompressionPtr compression = NULL;
int ret = -1;
virCheckFlagsGoto(QEMU_MIGRATION_FLAGS, cleanup);
if (nmigrate_disks < 0)
goto cleanup;
+ if (!(compression = qemuMigrationCompressionParse(params, nparams, flags)))
+ goto cleanup;
+
if (flags & VIR_MIGRATE_TUNNELLED) {
/* this is a logical error; we never should have gotten here with
* VIR_MIGRATE_TUNNELLED set
cookieout, cookieoutlen,
uri_in, uri_out,
&def, origname, listenAddress,
- nmigrate_disks, migrate_disks,
- nbdPort, flags);
+ nmigrate_disks, migrate_disks, nbdPort,
+ compression, flags);
cleanup:
+ VIR_FREE(compression);
VIR_FREE(migrate_disks);
VIR_FREE(origname);
virDomainDefFree(def);
{
virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm;
+ qemuMigrationCompressionPtr compression = NULL;
+ int ret = -1;
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
- if (!(vm = qemuDomObjFromDomain(dom)))
+ if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
return -1;
+ if (!(vm = qemuDomObjFromDomain(dom)))
+ goto cleanup;
+
if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0) {
virDomainObjEndAPI(&vm);
- return -1;
+ goto cleanup;
}
- return qemuMigrationPerform(driver, dom->conn, vm, xmlin,
- dconnuri, uri, NULL, NULL, 0, NULL, 0,
- cookiein, cookieinlen,
- cookieout, cookieoutlen,
- flags, dname, resource, true);
+ ret = qemuMigrationPerform(driver, dom->conn, vm, xmlin,
+ dconnuri, uri, NULL, NULL, 0, NULL, 0,
+ compression,
+ cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, dname, resource, true);
+
+ cleanup:
+ VIR_FREE(compression);
+ return ret;
}
static int
const char **migrate_disks = NULL;
unsigned long long bandwidth = 0;
int nbdPort = 0;
+ qemuMigrationCompressionPtr compression = NULL;
int ret = -1;
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
if (nmigrate_disks < 0)
goto cleanup;
+ if (!(compression = qemuMigrationCompressionParse(params, nparams, flags)))
+ goto cleanup;
+
if (!(vm = qemuDomObjFromDomain(dom)))
goto cleanup;
ret = qemuMigrationPerform(driver, dom->conn, vm, dom_xml,
dconnuri, uri, graphicsuri, listenAddress,
nmigrate_disks, migrate_disks, nbdPort,
+ compression,
cookiein, cookieinlen, cookieout, cookieoutlen,
flags, dname, bandwidth, true);
cleanup:
+ VIR_FREE(compression);
VIR_FREE(migrate_disks);
return ret;
}
"finish3",
);
+VIR_ENUM_IMPL(qemuMigrationCompressMethod, QEMU_MIGRATION_COMPRESS_LAST,
+ "xbzrle",
+ "mt",
+);
+
enum qemuMigrationCookieFlags {
QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
return inc;
}
+static int
+qemuMigrationSetCompression(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob job,
+ qemuMigrationCompressionPtr compression)
+{
+ if (qemuMigrationSetOption(driver, vm,
+ QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
+ compression->methods &
+ (1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE),
+ job) < 0)
+ return -1;
+
+ if (qemuMigrationSetOption(driver, vm,
+ QEMU_MONITOR_MIGRATION_CAPS_COMPRESS,
+ compression->methods &
+ (1ULL << QEMU_MIGRATION_COMPRESS_MT),
+ job) < 0)
+ return -1;
+
+ return 0;
+}
+
static int
qemuMigrationPrepareAny(virQEMUDriverPtr driver,
virConnectPtr dconn,
size_t nmigrate_disks,
const char **migrate_disks,
int nbdPort,
+ qemuMigrationCompressionPtr compression,
unsigned long flags)
{
virDomainObjPtr vm = NULL;
dataFD[1] = -1; /* 'st' owns the FD now & will close it */
}
- if (qemuMigrationSetOption(driver, vm,
- QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
- flags & VIR_MIGRATE_COMPRESSED,
- QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
+ if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN,
+ compression) < 0)
goto stopjob;
if (STREQ_NULLABLE(protocol, "rdma") &&
const char *origname,
unsigned long flags)
{
+ qemuMigrationCompressionPtr compression = NULL;
int ret;
VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
return -1;
}
+ if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+ return -1;
+
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
cookieout, cookieoutlen, def, origname,
- st, NULL, 0, false, NULL, 0, NULL, 0, flags);
+ st, NULL, 0, false, NULL, 0, NULL, 0,
+ compression, flags);
+ VIR_FREE(compression);
return ret;
}
size_t nmigrate_disks,
const char **migrate_disks,
int nbdPort,
+ qemuMigrationCompressionPtr compression,
unsigned long flags)
{
unsigned short port = 0;
cookieout, cookieoutlen, def, origname,
NULL, uri ? uri->scheme : "tcp",
port, autoPort, listenAddress,
- nmigrate_disks, migrate_disks, nbdPort, flags);
+ nmigrate_disks, migrate_disks, nbdPort,
+ compression, flags);
cleanup:
virURIFree(uri);
VIR_FREE(hostname);
virConnectPtr dconn,
const char *graphicsuri,
size_t nmigrate_disks,
- const char **migrate_disks)
+ const char **migrate_disks,
+ qemuMigrationCompressionPtr compression)
{
int ret = -1;
unsigned int migrate_flags = QEMU_MONITOR_MIGRATE_BACKGROUND;
goto cleanup;
}
- if (qemuMigrationSetOption(driver, vm,
- QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
- flags & VIR_MIGRATE_COMPRESSED,
- QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+ if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
+ compression) < 0)
goto cleanup;
if (qemuMigrationSetOption(driver, vm,
virConnectPtr dconn,
const char *graphicsuri,
size_t nmigrate_disks,
- const char **migrate_disks)
+ const char **migrate_disks,
+ qemuMigrationCompressionPtr compression)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virURIPtr uribits = NULL;
ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
cookieoutlen, flags, resource, &spec, dconn,
- graphicsuri, nmigrate_disks, migrate_disks);
+ graphicsuri, nmigrate_disks, migrate_disks,
+ compression);
if (spec.destType == MIGRATION_DEST_FD)
VIR_FORCE_CLOSE(spec.dest.fd.qemu);
virConnectPtr dconn,
const char *graphicsuri,
size_t nmigrate_disks,
- const char **migrate_disks)
+ const char **migrate_disks,
+ qemuMigrationCompressionPtr compression)
{
virNetSocketPtr sock = NULL;
int ret = -1;
ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
cookieoutlen, flags, resource, &spec, dconn,
- graphicsuri, nmigrate_disks, migrate_disks);
+ graphicsuri, nmigrate_disks, migrate_disks,
+ compression);
cleanup:
if (spec.destType == MIGRATION_DEST_FD) {
bool cancelled;
virStreamPtr st = NULL;
unsigned long destflags;
+ qemuMigrationCompressionPtr compression = NULL;
VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, vm=%p, dconnuri=%s, "
"flags=%lx, dname=%s, resource=%lu",
destflags = flags & ~(VIR_MIGRATE_ABORT_ON_ERROR |
VIR_MIGRATE_AUTO_CONVERGE);
+ if (!(compression = qemuMigrationCompressionParse(NULL, 0, flags)))
+ goto cleanup;
+
VIR_DEBUG("Prepare2 %p", dconn);
if (flags & VIR_MIGRATE_TUNNELLED) {
/*
ret = doTunnelMigrate(driver, vm, st,
NULL, 0, NULL, NULL,
flags, resource, dconn,
- NULL, 0, NULL);
+ NULL, 0, NULL, compression);
else
ret = doNativeMigrate(driver, vm, uri_out,
cookie, cookielen,
NULL, NULL, /* No out cookie with v2 migration */
- flags, resource, dconn, NULL, 0, NULL);
+ flags, resource, dconn, NULL, 0, NULL, compression);
/* Perform failed. Make sure Finish doesn't overwrite the error */
if (ret < 0)
}
VIR_FREE(uri_out);
VIR_FREE(cookie);
+ VIR_FREE(compression);
return ret;
}
size_t nmigrate_disks,
const char **migrate_disks,
int nbdPort,
+ qemuMigrationCompressionPtr compression,
unsigned long long bandwidth,
bool useParams,
unsigned long flags)
VIR_MIGRATE_PARAM_DISKS_PORT,
nbdPort) < 0)
goto cleanup;
+
+ if (qemuMigrationCompressionDump(compression, ¶ms, &nparams,
+ &maxparams, &flags) < 0)
+ goto cleanup;
}
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
cookiein, cookieinlen,
&cookieout, &cookieoutlen,
flags, bandwidth, dconn, graphicsuri,
- nmigrate_disks, migrate_disks);
+ nmigrate_disks, migrate_disks, compression);
} else {
ret = doNativeMigrate(driver, vm, uri,
cookiein, cookieinlen,
&cookieout, &cookieoutlen,
flags, bandwidth, dconn, graphicsuri,
- nmigrate_disks, migrate_disks);
+ nmigrate_disks, migrate_disks, compression);
}
/* Perform failed. Make sure Finish doesn't overwrite the error */
size_t nmigrate_disks,
const char **migrate_disks,
int nbdPort,
+ qemuMigrationCompressionPtr compression,
unsigned long flags,
const char *dname,
unsigned long resource,
ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin,
dname, uri, graphicsuri, listenAddress,
nmigrate_disks, migrate_disks, nbdPort,
- resource, useParams, flags);
+ compression, resource, useParams, flags);
} else {
ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
dconnuri, flags, dname, resource);
size_t nmigrate_disks,
const char **migrate_disks,
int nbdPort,
+ qemuMigrationCompressionPtr compression,
const char *cookiein,
int cookieinlen,
char **cookieout,
ret = doPeer2PeerMigrate(driver, conn, vm, xmlin,
dconnuri, uri, graphicsuri, listenAddress,
nmigrate_disks, migrate_disks, nbdPort,
- flags, dname, resource, &v3proto);
+ compression, flags, dname, resource, &v3proto);
} else {
qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2);
ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
cookieout, cookieoutlen,
- flags, resource, NULL, NULL, 0, NULL);
+ flags, resource, NULL, NULL, 0, NULL,
+ compression);
}
if (ret < 0)
goto endjob;
const char *graphicsuri,
size_t nmigrate_disks,
const char **migrate_disks,
+ qemuMigrationCompressionPtr compression,
const char *cookiein,
int cookieinlen,
char **cookieout,
ret = doNativeMigrate(driver, vm, uri, cookiein, cookieinlen,
cookieout, cookieoutlen,
flags, resource, NULL, graphicsuri,
- nmigrate_disks, migrate_disks);
+ nmigrate_disks, migrate_disks, compression);
if (ret < 0) {
if (qemuMigrationRestoreDomainState(conn, vm)) {
size_t nmigrate_disks,
const char **migrate_disks,
int nbdPort,
+ qemuMigrationCompressionPtr compression,
const char *cookiein,
int cookieinlen,
char **cookieout,
return qemuMigrationPerformJob(driver, conn, vm, xmlin, dconnuri, uri,
graphicsuri, listenAddress,
nmigrate_disks, migrate_disks, nbdPort,
- cookiein, cookieinlen,
+ compression, cookiein, cookieinlen,
cookieout, cookieoutlen,
flags, dname, resource, v3proto);
} else {
return qemuMigrationPerformPhase(driver, conn, vm, uri,
graphicsuri,
nmigrate_disks, migrate_disks,
- cookiein, cookieinlen,
+ compression, cookiein, cookieinlen,
cookieout, cookieoutlen,
flags, resource);
} else {
return qemuMigrationPerformJob(driver, conn, vm, xmlin, NULL,
uri, graphicsuri, listenAddress,
nmigrate_disks, migrate_disks, nbdPort,
- cookiein, cookieinlen,
+ compression, cookiein, cookieinlen,
cookieout, cookieoutlen, flags,
dname, resource, v3proto);
}
virSetError(err);
virFreeError(err);
}
+
+
+/* don't ever pass NULL params with non zero nparams */
+qemuMigrationCompressionPtr
+qemuMigrationCompressionParse(virTypedParameterPtr params,
+ int nparams,
+ unsigned long flags)
+{
+ size_t i;
+ qemuMigrationCompressionPtr compression = NULL;
+
+ if (VIR_ALLOC(compression) < 0)
+ return NULL;
+
+ for (i = 0; i < nparams; i++) {
+ int method;
+
+ if (STRNEQ(params[i].field, VIR_MIGRATE_PARAM_COMPRESSION))
+ continue;
+
+ method = qemuMigrationCompressMethodTypeFromString(params[i].value.s);
+ if (method < 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Unsupported compression method '%s'"),
+ params[i].value.s);
+ goto error;
+ }
+
+ if (compression->methods & (1ULL << method)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Compression method '%s' is specified twice"),
+ params[i].value.s);
+ goto error;
+ }
+
+ compression->methods |= 1ULL << method;
+ }
+
+ if (!compression->methods && (flags & VIR_MIGRATE_COMPRESSED))
+ compression->methods = 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE;
+
+ return compression;
+
+ error:
+ VIR_FREE(compression);
+ return NULL;
+}
+
+int
+qemuMigrationCompressionDump(qemuMigrationCompressionPtr compression,
+ virTypedParameterPtr *params,
+ int *nparams,
+ int *maxparams,
+ unsigned long *flags)
+{
+ size_t i;
+
+ if (compression->methods == 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE) {
+ *flags |= VIR_MIGRATE_COMPRESSED;
+ return 0;
+ }
+
+ for (i = 0; i < QEMU_MIGRATION_COMPRESS_LAST; ++i) {
+ if ((compression->methods & (1ULL << i)) &&
+ virTypedParamsAddString(params, nparams, maxparams,
+ VIR_MIGRATE_PARAM_COMPRESSION,
+ qemuMigrationCompressMethodTypeToString(i)) < 0)
+ return -1;
+ }
+
+ return 0;
+}