mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-09 17:24:53 +00:00
vz: implement managed migration
The newest version of migration protocol - version 3 with parameters is implemented. Supported flags is VIR_MIGRATE_PAUSED only. Supported parameters are VIR_MIGRATE_PARAM_URI and VIR_MIGRATE_PARAM_DEST_NAME. VIR_MIGRATE_PARAM_DEST_XML is in VZ_MIGRATION_PARAMETERS for technical onyl reasons. Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com> Signed-off-by: Maxim Nestratov <mnestratov@virtuozzo.com>
This commit is contained in:
parent
17c37031e5
commit
0eced74f34
@ -139,6 +139,9 @@ vzBuildCapabilities(void)
|
|||||||
|
|
||||||
caps->host.cpu = cpu;
|
caps->host.cpu = cpu;
|
||||||
|
|
||||||
|
if (virCapabilitiesAddHostMigrateTransport(caps, "vzmigr") < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (!(data = cpuNodeData(cpu->arch))
|
if (!(data = cpuNodeData(cpu->arch))
|
||||||
|| cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
|
|| cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2100,6 +2103,454 @@ vzDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _vzMigrationCookie vzMigrationCookie;
|
||||||
|
typedef vzMigrationCookie *vzMigrationCookiePtr;
|
||||||
|
struct _vzMigrationCookie {
|
||||||
|
unsigned char session_uuid[VIR_UUID_BUFLEN];
|
||||||
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
vzMigrationCookieFree(vzMigrationCookiePtr mig)
|
||||||
|
{
|
||||||
|
if (!mig)
|
||||||
|
return;
|
||||||
|
VIR_FREE(mig->name);
|
||||||
|
VIR_FREE(mig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vzBakeCookie(vzMigrationCookiePtr mig, char **cookieout, int *cookieoutlen)
|
||||||
|
{
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
if (!cookieout || !cookieoutlen) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Migration cookie parameters are not provided."));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cookieout = NULL;
|
||||||
|
*cookieoutlen = 0;
|
||||||
|
|
||||||
|
virBufferAddLit(&buf, "<vz-migration>\n");
|
||||||
|
virBufferAdjustIndent(&buf, 2);
|
||||||
|
virUUIDFormat(mig->session_uuid, uuidstr);
|
||||||
|
virBufferAsprintf(&buf, "<session-uuid>%s</session-uuid>\n", uuidstr);
|
||||||
|
virUUIDFormat(mig->uuid, uuidstr);
|
||||||
|
virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr);
|
||||||
|
virBufferAsprintf(&buf, "<name>%s</name>\n", mig->name);
|
||||||
|
virBufferAdjustIndent(&buf, -2);
|
||||||
|
virBufferAddLit(&buf, "</vz-migration>\n");
|
||||||
|
|
||||||
|
if (virBufferCheckError(&buf) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*cookieout = virBufferContentAndReset(&buf);
|
||||||
|
*cookieoutlen = strlen(*cookieout) + 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vzMigrationCookiePtr
|
||||||
|
vzEatCookie(const char *cookiein, int cookieinlen)
|
||||||
|
{
|
||||||
|
xmlDocPtr doc = NULL;
|
||||||
|
xmlXPathContextPtr ctx = NULL;
|
||||||
|
char *tmp;
|
||||||
|
vzMigrationCookiePtr mig = NULL;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(mig) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!cookiein || cookieinlen <= 0 || cookiein[cookieinlen - 1] != '\0') {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Invalid migration cookie"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(doc = virXMLParseStringCtxt(cookiein,
|
||||||
|
_("(_migration_cookie)"), &ctx)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(tmp = virXPathString("string(./session-uuid[1])", ctx))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("missing session-uuid element in migration data"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (virUUIDParse(tmp, mig->session_uuid) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("malformed session-uuid element in migration data"));
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
|
||||||
|
if (!(tmp = virXPathString("string(./uuid[1])", ctx))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("missing uuid element in migration data"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (virUUIDParse(tmp, mig->uuid) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("malformed uuid element in migration data"));
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
|
||||||
|
if (!(mig->name = virXPathString("string(./name[1])", ctx))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("missing name element in migration data"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
xmlXPathFreeContext(ctx);
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
return mig;
|
||||||
|
|
||||||
|
error:
|
||||||
|
vzMigrationCookieFree(mig);
|
||||||
|
mig = NULL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VZ_MIGRATION_FLAGS VIR_MIGRATE_PAUSED
|
||||||
|
|
||||||
|
#define VZ_MIGRATION_PARAMETERS \
|
||||||
|
VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \
|
||||||
|
VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \
|
||||||
|
VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \
|
||||||
|
NULL
|
||||||
|
|
||||||
|
static char *
|
||||||
|
vzDomainMigrateBegin3Params(virDomainPtr domain,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams,
|
||||||
|
char **cookieout,
|
||||||
|
int *cookieoutlen,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
char *xml = NULL;
|
||||||
|
virDomainObjPtr dom = NULL;
|
||||||
|
vzConnPtr privconn = domain->conn->privateData;
|
||||||
|
vzMigrationCookiePtr mig = NULL;
|
||||||
|
|
||||||
|
virCheckFlags(VZ_MIGRATION_FLAGS, NULL);
|
||||||
|
|
||||||
|
if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* we can't do this check via VZ_MIGRATION_PARAMETERS as on preparation
|
||||||
|
* step domain xml will be passed via this parameter and it is a common
|
||||||
|
* style to use single allowed parameter list definition in all steps */
|
||||||
|
if (virTypedParamsGet(params, nparams, VIR_MIGRATE_PARAM_DEST_XML)) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("Changing destination XML is not supported"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dom = vzDomObjFromDomain(domain)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(mig) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (VIR_STRDUP(mig->name, dom->def->name) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
memcpy(mig->uuid, dom->def->uuid, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
|
if (vzBakeCookie(mig, cookieout, cookieoutlen) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
xml = virDomainDefFormat(dom->def, privconn->driver->caps,
|
||||||
|
VIR_DOMAIN_XML_MIGRATABLE);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
vzMigrationCookieFree(mig);
|
||||||
|
if (dom)
|
||||||
|
virObjectUnlock(dom);
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
vzMigrationCreateURI(void)
|
||||||
|
{
|
||||||
|
char *hostname = NULL;
|
||||||
|
char *uri = NULL;
|
||||||
|
|
||||||
|
if (!(hostname = virGetHostname()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (STRPREFIX(hostname, "localhost")) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("hostname on destination resolved to localhost,"
|
||||||
|
" but migration requires an FQDN"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virAsprintf(&uri, "vzmigr://%s", hostname) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(hostname);
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vzDomainMigratePrepare3Params(virConnectPtr conn,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams,
|
||||||
|
const char *cookiein,
|
||||||
|
int cookieinlen,
|
||||||
|
char **cookieout,
|
||||||
|
int *cookieoutlen,
|
||||||
|
char **uri_out,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
vzConnPtr privconn = conn->privateData;
|
||||||
|
const char *miguri = NULL;
|
||||||
|
const char *dname = NULL;
|
||||||
|
virDomainObjPtr dom = NULL;
|
||||||
|
vzMigrationCookiePtr mig = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
virCheckFlags(VZ_MIGRATION_FLAGS, -1);
|
||||||
|
|
||||||
|
if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virTypedParamsGetString(params, nparams,
|
||||||
|
VIR_MIGRATE_PARAM_URI, &miguri) < 0 ||
|
||||||
|
virTypedParamsGetString(params, nparams,
|
||||||
|
VIR_MIGRATE_PARAM_DEST_NAME, &dname) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* We must set uri_out if miguri is not set. This is direct
|
||||||
|
* managed migration requirement */
|
||||||
|
if (!miguri && !(*uri_out = vzMigrationCreateURI()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(mig = vzEatCookie(cookiein, cookieinlen)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
memcpy(mig->session_uuid, privconn->driver->session_uuid, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
|
if (vzBakeCookie(mig, cookieout, cookieoutlen) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
virObjectLock(privconn->driver);
|
||||||
|
dom = virDomainObjListFindByUUID(privconn->driver->domains, mig->uuid);
|
||||||
|
if (dom) {
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
virUUIDFormat(mig->uuid, uuidstr);
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("A domain with uuid '%s' already exists"),
|
||||||
|
uuidstr);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dom = vzNewDomain(privconn->driver,
|
||||||
|
dname ? dname : mig->name, mig->uuid)))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
virObjectUnlock(privconn->driver);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
vzMigrationCookieFree(mig);
|
||||||
|
if (dom)
|
||||||
|
virObjectUnlock(dom);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
|
||||||
|
{
|
||||||
|
switch (feature) {
|
||||||
|
case VIR_DRV_FEATURE_MIGRATION_PARAMS:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static virURIPtr
|
||||||
|
vzParseVzURI(const char *uri_str)
|
||||||
|
{
|
||||||
|
virURIPtr uri = NULL;
|
||||||
|
|
||||||
|
if (!(uri = virURIParse(uri_str)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!uri->scheme || !uri->server) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("scheme and host are mandatory vz migration URI: %s"),
|
||||||
|
uri_str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri->user || uri->path || uri->query || uri->fragment) {
|
||||||
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("only scheme, host and port are supported in "
|
||||||
|
"vz migration URI: %s"), uri_str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STRNEQ(uri->scheme, "vzmigr")) {
|
||||||
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
||||||
|
_("unsupported scheme %s in migration URI %s"),
|
||||||
|
uri->scheme, uri_str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virURIFree(uri);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vzDomainMigratePerform3Params(virDomainPtr domain,
|
||||||
|
const char *dconnuri ATTRIBUTE_UNUSED,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams,
|
||||||
|
const char *cookiein,
|
||||||
|
int cookieinlen,
|
||||||
|
char **cookieout ATTRIBUTE_UNUSED,
|
||||||
|
int *cookieoutlen ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
virDomainObjPtr dom = NULL;
|
||||||
|
virURIPtr vzuri = NULL;
|
||||||
|
vzConnPtr privconn = domain->conn->privateData;
|
||||||
|
const char *miguri = NULL;
|
||||||
|
const char *dname = NULL;
|
||||||
|
vzMigrationCookiePtr mig = NULL;
|
||||||
|
|
||||||
|
virCheckFlags(VZ_MIGRATION_FLAGS, -1);
|
||||||
|
|
||||||
|
if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virTypedParamsGetString(params, nparams,
|
||||||
|
VIR_MIGRATE_PARAM_URI, &miguri) < 0 ||
|
||||||
|
virTypedParamsGetString(params, nparams,
|
||||||
|
VIR_MIGRATE_PARAM_DEST_NAME, &dname) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!miguri) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("migrate uri is not set"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(mig = vzEatCookie(cookiein, cookieinlen)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(dom = vzDomObjFromDomain(domain)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(vzuri = vzParseVzURI(miguri)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (prlsdkMigrate(dom, vzuri, mig->session_uuid, dname, flags) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
virDomainObjListRemove(privconn->driver->domains, dom);
|
||||||
|
dom = NULL;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (dom)
|
||||||
|
virObjectUnlock(dom);
|
||||||
|
virURIFree(vzuri);
|
||||||
|
vzMigrationCookieFree(mig);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virDomainPtr
|
||||||
|
vzDomainMigrateFinish3Params(virConnectPtr dconn,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams,
|
||||||
|
const char *cookiein ATTRIBUTE_UNUSED,
|
||||||
|
int cookieinlen ATTRIBUTE_UNUSED,
|
||||||
|
char **cookieout ATTRIBUTE_UNUSED,
|
||||||
|
int *cookieoutlen ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int flags,
|
||||||
|
int cancelled)
|
||||||
|
{
|
||||||
|
virDomainObjPtr dom = NULL;
|
||||||
|
virDomainPtr domain = NULL;
|
||||||
|
vzConnPtr privconn = dconn->privateData;
|
||||||
|
vzDriverPtr driver = privconn->driver;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
virCheckFlags(VZ_MIGRATION_FLAGS, NULL);
|
||||||
|
|
||||||
|
if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virTypedParamsGetString(params, nparams,
|
||||||
|
VIR_MIGRATE_PARAM_DEST_NAME, &name) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(dom = virDomainObjListFindByName(driver->domains, name))) {
|
||||||
|
virReportError(VIR_ERR_NO_DOMAIN,
|
||||||
|
_("no domain with matching name '%s'"), name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
virDomainObjListRemove(driver->domains, dom);
|
||||||
|
dom = NULL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prlsdkLoadDomain(driver, dom))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
domain = virGetDomain(dconn, dom->def->name, dom->def->uuid);
|
||||||
|
if (domain)
|
||||||
|
domain->id = dom->def->id;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
/* In this situation we have to restore domain on source. But the migration
|
||||||
|
* is already finished. */
|
||||||
|
if (!cancelled && !domain)
|
||||||
|
VIR_WARN("Can't provide domain '%s' after successfull migration.", name);
|
||||||
|
virDomainObjEndAPI(&dom);
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vzDomainMigrateConfirm3Params(virDomainPtr domain ATTRIBUTE_UNUSED,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams,
|
||||||
|
const char *cookiein ATTRIBUTE_UNUSED,
|
||||||
|
int cookieinlen ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int flags,
|
||||||
|
int cancelled ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virCheckFlags(VZ_MIGRATION_FLAGS, -1);
|
||||||
|
|
||||||
|
if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static virHypervisorDriver vzHypervisorDriver = {
|
static virHypervisorDriver vzHypervisorDriver = {
|
||||||
.name = "vz",
|
.name = "vz",
|
||||||
.connectOpen = vzConnectOpen, /* 0.10.0 */
|
.connectOpen = vzConnectOpen, /* 0.10.0 */
|
||||||
@ -2183,6 +2634,12 @@ static virHypervisorDriver vzHypervisorDriver = {
|
|||||||
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */
|
.domainSnapshotCreateXML = vzDomainSnapshotCreateXML, /* 1.3.5 */
|
||||||
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
|
.domainSnapshotDelete = vzDomainSnapshotDelete, /* 1.3.5 */
|
||||||
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */
|
.domainRevertToSnapshot = vzDomainRevertToSnapshot, /* 1.3.5 */
|
||||||
|
.connectSupportsFeature = vzConnectSupportsFeature, /* 1.3.5 */
|
||||||
|
.domainMigrateBegin3Params = vzDomainMigrateBegin3Params, /* 1.3.5 */
|
||||||
|
.domainMigratePrepare3Params = vzDomainMigratePrepare3Params, /* 1.3.5 */
|
||||||
|
.domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.3.5 */
|
||||||
|
.domainMigrateFinish3Params = vzDomainMigrateFinish3Params, /* 1.3.5 */
|
||||||
|
.domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static virConnectDriver vzConnectDriver = {
|
static virConnectDriver vzConnectDriver = {
|
||||||
|
@ -4461,3 +4461,45 @@ int prlsdkSwitchToSnapshot(virDomainObjPtr dom, const char *uuid, bool paused)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* high security is default choice for 2 reasons:
|
||||||
|
* 1. as this is the highest set security we can't get
|
||||||
|
* reject from server with high security settings
|
||||||
|
* 2. this is on par with security level of driver
|
||||||
|
* connection to dispatcher
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PRLSDK_MIGRATION_FLAGS (PSL_HIGH_SECURITY)
|
||||||
|
|
||||||
|
int prlsdkMigrate(virDomainObjPtr dom, virURIPtr uri,
|
||||||
|
const unsigned char *session_uuid,
|
||||||
|
const char *dname,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
vzDomObjPtr privdom = dom->privateData;
|
||||||
|
PRL_HANDLE job = PRL_INVALID_HANDLE;
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
|
||||||
|
PRL_UINT32 vzflags = PRLSDK_MIGRATION_FLAGS;
|
||||||
|
|
||||||
|
if (flags & VIR_MIGRATE_PAUSED)
|
||||||
|
vzflags |= PVMT_DONT_RESUME_VM;
|
||||||
|
|
||||||
|
prlsdkUUIDFormat(session_uuid, uuidstr);
|
||||||
|
job = PrlVm_MigrateWithRenameEx(privdom->sdkdom, uri->server,
|
||||||
|
uri->port, uuidstr,
|
||||||
|
dname == NULL ? "" : dname,
|
||||||
|
"",
|
||||||
|
vzflags,
|
||||||
|
0,
|
||||||
|
PRL_TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (PRL_FAILED(waitJob(job)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -87,3 +87,9 @@ virDomainSnapshotObjListPtr prlsdkLoadSnapshots(virDomainObjPtr dom);
|
|||||||
int prlsdkCreateSnapshot(virDomainObjPtr dom, const char *description);
|
int prlsdkCreateSnapshot(virDomainObjPtr dom, const char *description);
|
||||||
int prlsdkDeleteSnapshot(virDomainObjPtr dom, const char *uuid, bool children);
|
int prlsdkDeleteSnapshot(virDomainObjPtr dom, const char *uuid, bool children);
|
||||||
int prlsdkSwitchToSnapshot(virDomainObjPtr dom, const char *uuid, bool paused);
|
int prlsdkSwitchToSnapshot(virDomainObjPtr dom, const char *uuid, bool paused);
|
||||||
|
int
|
||||||
|
prlsdkMigrate(virDomainObjPtr dom,
|
||||||
|
virURIPtr uri,
|
||||||
|
const char unsigned *session_uuid,
|
||||||
|
const char *dname,
|
||||||
|
unsigned int flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user