[libvirt] [PATCH v3 2/5] vz: add migration backbone code

Dmitry Guryanov dguryanov at virtuozzo.com
Tue Aug 25 15:42:09 UTC 2015


On 08/25/2015 12:04 PM, nshirokovskiy at virtuozzo.com wrote:
> From: Nikolay Shirokovskiy <nshirokovskiy at 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 at 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?

> 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.

> + 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?

> +        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);




More information about the libvir-list mailing list