On 25.08.2015 18:42, Dmitry Guryanov wrote:
On 08/25/2015 12:04 PM, nshirokovskiy(a)virtuozzo.com wrote:
> From: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
>
> This patch makes basic vz migration possible. For example by virsh:
> virsh -c vz:///system migrate --direct $NAME $STUB vz+ssh://$DST/system
>
> $STUB could be anything as it is required virsh argument but it is not
> used in direct migration.
>
> Vz migration is implemented as direct migration. The reason is that vz sdk do
> all the job. Prepare phase function is used to pass session uuid from
> destination to source so we don't introduce new rpc call.
>
> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
> ---
> src/libvirt-domain.c | 3 +-
> src/vz/vz_driver.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++
> src/vz/vz_sdk.c | 33 +++++++++
> src/vz/vz_sdk.h | 2 +
> 4 files changed, 230 insertions(+), 1 deletions(-)
>
> diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
> index cbf08fc..8577edd 100644
> --- a/src/libvirt-domain.c
> +++ b/src/libvirt-domain.c
> @@ -3425,7 +3425,8 @@ virDomainMigrateDirect(virDomainPtr domain,
> NULLSTR(xmlin), flags, NULLSTR(dname), NULLSTR(uri),
> bandwidth);
> - if (!domain->conn->driver->domainMigratePerform) {
> + if (!domain->conn->driver->domainMigratePerform &&
> + !domain->conn->driver->domainMigratePerform3) {
> virReportUnsupportedError();
> return -1;
> }
Could you, please, send this change in a separate patch, because it's a sort of
bugfix to common libvirt code and not related to our migration?
ok
> diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
> index 8fa7957..f82fff8 100644
> --- a/src/vz/vz_driver.c
> +++ b/src/vz/vz_driver.c
> @@ -1343,6 +1343,196 @@ vzDomainMemoryStats(virDomainPtr domain,
> return ret;
> }
> +static char*
> +vzFormatCookie(const unsigned char *session_uuid)
> +{
> + char uuidstr[VIR_UUID_STRING_BUFLEN];
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> +
> + virBufferAddLit(&buf, "<vz-migration1>\n");
> + virUUIDFormat(session_uuid, uuidstr);
> + virBufferAsprintf(&buf,
"<session_uuid>%s</session_uuid>\n", uuidstr);
> + virBufferAddLit(&buf, "</vz-migration1>\n");
.....
> +
> +static virURIPtr
> +vzMakeVzUri(const char *connuri_str)
> +{
> + virURIPtr connuri = NULL;
> + virURIPtr vzuri = NULL;
> + int ret = -1;
> +
> + if (!(connuri = virURIParse(connuri_str)))
> + goto cleanup;
> +
> + if (VIR_ALLOC(vzuri) < 0)
> + goto cleanup;
> + memset(vzuri, 0, sizeof(*vzuri));
> +
> + if (VIR_STRDUP(vzuri->server, connuri->server) < 0)
> + goto cleanup;
> + vzuri->port = connuri->port;
> + ret = 0;
> +
This is generally not correct, since you are passing the port of libvirt's connection
to vz connection, it works if you don't specify port in URI, port is 0 in this case,
and libprlsdk accepts it.
I'm not agree. This function is called with hypervisor
specific uri where port is hypervisor and not libvirtd port.
> + cleanup:
> +
> + virURIFree(connuri);
> + if (ret < 0) {
> + virURIFree(vzuri);
> + vzuri = NULL;
> + }
> +
> + return vzuri;
> +}
> +
> +#define VZ_MIGRATION_FLAGS (0)
> +
> +#define VZ_MIGRATION_PARAMETERS (NULL)
> +
> +static int
> +vzDomainMigratePerform3(virDomainPtr domain,
> + const char *xmlin ATTRIBUTE_UNUSED,
> + const char *cookiein ATTRIBUTE_UNUSED,
> + int cookieinlen ATTRIBUTE_UNUSED,
> + char **cookieout ATTRIBUTE_UNUSED,
> + int *cookieoutlen ATTRIBUTE_UNUSED,
> + const char *dconnuri ATTRIBUTE_UNUSED,
> + const char *uri,
> + unsigned long flags,
> + const char *dname ATTRIBUTE_UNUSED,
> + unsigned long bandwidth ATTRIBUTE_UNUSED)
> +{
> + int ret = -1;
> + virDomainObjPtr dom = NULL;
> + virConnectPtr dconn = NULL;
> + virURIPtr vzuri = NULL;
> + unsigned char session_uuid[VIR_UUID_BUFLEN];
> + vzConnPtr privconn = domain->conn->privateData;
> + char *cookie = NULL;
> + int cookielen = 0;
> +
> + virCheckFlags(VZ_MIGRATION_FLAGS, -1);
> +
> + if (!(vzuri = vzMakeVzUri(uri)))
> + goto cleanup;
> +
> + if (!(dom = vzDomObjFromDomain(domain)))
> + goto cleanup;
> +
> + dconn = virConnectOpen(uri);
> + if (dconn == NULL) {
> + virReportError(VIR_ERR_OPERATION_FAILED,
> + _("Failed to connect to remote libvirt URI %s:
%s"),
> + uri, virGetLastErrorMessage());
> + goto cleanup;
> + }
> +
> + /* NULL and zero elements are unused */
> + /* domxml is passed as "" or otherwise we will fail at rpc call */
> + if (virDomainMigratePrepare3(dconn, NULL, 0, &cookie, &cookielen, NULL,
NULL, 0, NULL, 0, "") < 0)
Could you split this line?
ok
> + goto cleanup;
> +
> + if (vzParseCookie(cookie, session_uuid) < 0)
> + goto cleanup;
> +
> + if (prlsdkMigrate(dom, vzuri, session_uuid) < 0)
> + goto cleanup;
> +
> + virDomainObjListRemove(privconn->domains, dom);
> + dom = NULL;
> +
> + ret = 0;
> +
> + cleanup:
> + if (dom)
> + virObjectUnlock(dom);
> + virObjectUnref(dconn);
> + virURIFree(vzuri);
> + VIR_FREE(cookie);
> +
> + return ret;
> +}
> +
> static virHypervisorDriver vzDriver = {
> .name = "vz",
> .connectOpen = vzConnectOpen, /* 0.10.0 */
> @@ -1396,6 +1586,9 @@ static virHypervisorDriver vzDriver = {
> .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
> .domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */
> .domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
> + .connectSupportsFeature = vzConnectSupportsFeature, /* 1.2.19 */
> + .domainMigratePrepare3 = vzDomainMigratePrepare3, /* 1.2.19 */
> + .domainMigratePerform3 = vzDomainMigratePerform3, /* 1.2.19 */
> };
> static virConnectDriver vzConnectDriver = {
> diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
> index f7253de..783438d 100644
> --- a/src/vz/vz_sdk.c
> +++ b/src/vz/vz_sdk.c
> @@ -4054,3 +4054,36 @@ prlsdkGetMemoryStats(virDomainObjPtr dom,
> return ret;
> }
> +
> +/* 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)
> +{
> + int ret = -1;
> + vzDomObjPtr privdom = dom->privateData;
> + PRL_HANDLE job = PRL_INVALID_HANDLE;
> + char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
> +
> + prlsdkUUIDFormat(session_uuid, uuidstr);
> + job = PrlVm_MigrateEx(privdom->sdkdom, uri->server, uri->port,
uuidstr,
> + "", /* use default dir for migrated instance
bundle */
> + PRLSDK_MIGRATION_FLAGS,
> + 0, /* reserved flags */
> + PRL_TRUE /* don't ask for confirmations */
> + );
> +
> + if (PRL_FAILED(waitJob(job)))
> + goto cleanup;
> +
> + ret = 0;
> +
> + cleanup:
> + return ret;
> +}
> diff --git a/src/vz/vz_sdk.h b/src/vz/vz_sdk.h
> index ebe4591..d3f0caf 100644
> --- a/src/vz/vz_sdk.h
> +++ b/src/vz/vz_sdk.h
> @@ -76,3 +76,5 @@ int
> prlsdkGetVcpuStats(virDomainObjPtr dom, int idx, unsigned long long *time);
> int
> prlsdkGetMemoryStats(virDomainObjPtr dom, virDomainMemoryStatPtr stats, unsigned
int nr_stats);
> +int
> +prlsdkMigrate(virDomainObjPtr dom, virURIPtr uri, const char unsigned
*session_uuid);