[libvirt] [PATCH v4 2/6] vz: add migration backbone code

Nikolay Shirokovskiy nshirokovskiy at parallels.com
Fri Sep 4 07:56:52 UTC 2015



On 03.09.2015 19:45, Daniel P. Berrange wrote:
> On Wed, Sep 02, 2015 at 03:09:23PM +0300, Nikolay Shirokovskiy wrote:
>> From: nshirokovskiy at virtuozzo.com <nshirokovskiy at virtuozzo.com>
>>
>> This patch makes basic vz migration possible. For example by virsh:
>>
>> virsh -c vz:///system migrate $NAME vz+ssh://$DST/system --p2p
>>
>> Vz migration is implemented as p2p migration. The reason
>> is that vz sdk do all the job. The question may arise then
>> why don't implement it as a direct migration. The reason
>> is that we want to leverage rich libvirt authentication abilities
>> we lack in vz sdk. We can do it because vz sdk can use tokens to
>> factor out authentication from migration command.
>>
>> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
>> ---
>>  src/vz/vz_driver.c |  192 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  src/vz/vz_sdk.c    |   33 +++++++++
>>  src/vz/vz_sdk.h    |    2 +
>>  3 files changed, 227 insertions(+), 0 deletions(-)
>>
> 
>> +static int
>> +vzDomainMigratePrepare3Params(virConnectPtr conn,
>> +                                virTypedParameterPtr params ATTRIBUTE_UNUSED,
>> +                                int nparams ATTRIBUTE_UNUSED,
>> +                                const char *cookiein ATTRIBUTE_UNUSED,
>> +                                int cookieinlen ATTRIBUTE_UNUSED,
>> +                                char **cookieout,
>> +                                int *cookieoutlen,
>> +                                char **uri_out ATTRIBUTE_UNUSED,
>> +                                unsigned int flags)
>> +{
>> +    vzConnPtr privconn = conn->privateData;
>> +    int ret = -1;
>> +
>> +    virCheckFlags(0, -1);
>> +
>> +    if (!(*cookieout = vzFormatCookie(privconn->session_uuid)))
>> +        goto cleanup;
>> +    *cookieoutlen = strlen(*cookieout) + 1;
> 
> As mentioned before, you should fill in uri_out here with the
> hypervisor URI to use for migration, by filling in the URI of
> the current host (ie dest host). eg
> 
>      char *thishost = virGetHostname();
>      virAsprintf(uri_out, "tcp://%s", thishost);
>      VIR_FREE(thishost);
> 
>> +    ret = 0;
>> +
>> + cleanup:
>> +    if (ret != 0) {
>> +        VIR_FREE(*cookieout);
>> +        *cookieoutlen = 0;
>> +    }
>> +
>> +    return ret;
>> +}
>> +
> 
>> +static int
>> +vzDomainMigratePerform3Params(virDomainPtr domain,
>> +                              const char *dconnuri,
>> +                              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 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 (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
>> +        goto cleanup;
>> +
>> +    if (!(vzuri = vzMakeVzUri(dconnuri)))
>> +        goto cleanup;
> 
> This is not right - you can't use the libvirt URI to form the
> hypervisor migration URI, since the libvirt URI may not in
> fact refer to the hypervisor host.
> 
> eg people may be accessing libvirt(d) via a SSH tunnel in
> which case the dconnuri would include 'localhost' and not
> the actual target host. This is why you must fill in the
> uri_out parameter in the Prepare() method and use that,
> if the "migrateuri" parameter is not provided in the
> virTypedParams array.
> 
>> +
>> +    if (!(dom = vzDomObjFromDomain(domain)))
>> +        goto cleanup;
>> +
>> +    dconn = virConnectOpen(dconnuri);
>> +    if (dconn == NULL) {
>> +        virReportError(VIR_ERR_OPERATION_FAILED,
>> +                       _("Failed to connect to remote libvirt URI %s: %s"),
>> +                       dconnuri, virGetLastErrorMessage());
>> +        goto cleanup;
>> +    }
>> +
>> +    /* NULL and zero elements are unused */
>> +    if (virDomainMigratePrepare3Params(dconn, NULL, 0, NULL, 0,
>> +                                       &cookie, &cookielen, NULL, 0) < 0)
>> +        goto cleanup;
> 
> Since this is implementing v3, I'd prefer to see you provide the
> full set of 5 callbacks, even though they will currently be no-ops.
> This provides better future proofing for the migration impl in case
> those become neccessary later.
> 
> You can also then trivially implement the non-p2p plain migration
> in this method, by checking whether or not the PEER2PEER flag
> is set or not. If it is not set, you can just skip the connect
> open & prepare calls on the basis that libvirt will have done
> them for you.
Ok.
> 
>> +
>> +    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 +1585,9 @@ static virHypervisorDriver vzDriver = {
>>      .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
>>      .domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */
>>      .domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
>> +    .connectSupportsFeature = vzConnectSupportsFeature, /* 1.2.20 */
>> +    .domainMigratePrepare3Params = vzDomainMigratePrepare3Params, /* 1.2.20 */
>> +    .domainMigratePerform3Params = vzDomainMigratePerform3Params, /* 1.2.20 */
> 
> Somewhat annoyingly you also need to implement the callbacks for
> .domainMigratePrepare3 and .domainMigratePerform3, as we don't
> automatically convert non-params usage to the params based
> method AFAICT.
> 
> Your impl of .domainMigratePerform3 could pack the values into a
> virTypedParams array and then call .domainMigratePerform3Params,
> or do the reverse.
Yes, without plain(non-params) callbacks we get working only toURI3
API function and I create a patch not included in this patchset
to make toURI{1,2} work too. I take this approach of converting
parameters and use one common worker function but patch a different
place - API implementaion itself. So I'll include this patch
in next version of the set.

As in this case I need to patch 2 different sets of API implementation
*migrate{N} and *migrateURI{N} I'd rather put direct managed support
to a different patchset. Is it ok?


> 
> Regards,
> Daniel
> 




More information about the libvir-list mailing list