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

Nikolay Shirokovskiy nshirokovskiy at parallels.com
Wed Aug 26 06:44:03 UTC 2015



On 25.08.2015 18:42, Dmitry Guryanov wrote:
> 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?
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);
> 




More information about the libvir-list mailing list