Markus Armbruster <arm...@redhat.com> writes:

> Fabiano Rosas <faro...@suse.de> writes:
>
>> Markus Armbruster <arm...@redhat.com> writes:
>>
>>> Fabiano Rosas <faro...@suse.de> writes:
>>>
>>>> The migration parameters tls_creds, tls_authz and tls_hostname
>>>> currently have a non-uniform handling. When used as arguments to
>>>> migrate-set-parameters, their type is StrOrNull and when used as
>>>> return value from query-migrate-parameters, their type is a plain
>>>> string.
>>>>
>>>> Not only having to convert between the types is cumbersome, but it
>>>> also creates the issue of requiring two different QAPI types to be
>>>> used, one for each command. MigrateSetParameters is used for
>>>> migrate-set-parameters with the TLS arguments as StrOrNull while
>>>> MigrationParameters is used for query-migrate-parameters with the TLS
>>>> arguments as str.
>>>>
>>>> Since StrOrNull could be considered a superset of str, change the type
>>>> of the TLS arguments in MigrationParameters to StrOrNull and add a
>>>> helper to ensure they're never actually used as QTYPE_QNULL.
>>>
>>> The type of @tls_creds, @tls-hostname, @tls-authz changes from str to
>>> StrOrNull in introspection query-migrate-parameters.  Loss of precision.
>>> Introspection is already imprecise: it shows the members optional even
>>> though they aren't.  We accept the loss of precision to enable
>>> de-duplication.
>>>
>>> This should be worked into the commit message.
>>>
>>
>> Ack.
>>
>>>> This will allow the type duplication to be removed in the next
>>>> patches.
>>>>
>>>> Signed-off-by: Fabiano Rosas <faro...@suse.de>
>>>> ---
>>>>  migration/migration-hmp-cmds.c |   8 +-
>>>>  migration/migration.c          |   2 +
>>>>  migration/options.c            | 149 ++++++++++++++++++++-------------
>>>>  migration/options.h            |   1 +
>>>>  migration/tls.c                |   2 +-
>>>>  qapi/migration.json            |   6 +-
>>>>  6 files changed, 99 insertions(+), 69 deletions(-)
>>>>
>>>> diff --git a/migration/migration-hmp-cmds.c 
>>>> b/migration/migration-hmp-cmds.c
>>>> index e8a563c7d8..bc8179c582 100644
>>>> --- a/migration/migration-hmp-cmds.c
>>>> +++ b/migration/migration-hmp-cmds.c
>>>> @@ -276,14 +276,12 @@ void hmp_info_migrate_parameters(Monitor *mon, const 
>>>> QDict *qdict)
>>>>          monitor_printf(mon, "%s: %u\n",
>>>>              MigrationParameter_str(MIGRATION_PARAMETER_MAX_CPU_THROTTLE),
>>>>              params->max_cpu_throttle);
>>>> -        assert(params->tls_creds);
>>>>          monitor_printf(mon, "%s: '%s'\n",
>>>>              MigrationParameter_str(MIGRATION_PARAMETER_TLS_CREDS),
>>>> -            params->tls_creds);
>>>> -        assert(params->tls_hostname);
>>>> +                       params->tls_creds ? params->tls_creds->u.s : "");
>>>>          monitor_printf(mon, "%s: '%s'\n",
>>>>              MigrationParameter_str(MIGRATION_PARAMETER_TLS_HOSTNAME),
>>>> -            params->tls_hostname);
>>>> +                       params->tls_hostname ? params->tls_hostname->u.s : 
>>>> "");
>>>>          assert(params->has_max_bandwidth);
>>>>          monitor_printf(mon, "%s: %" PRIu64 " bytes/second\n",
>>>>              MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH),
>>>> @@ -319,7 +317,7 @@ void hmp_info_migrate_parameters(Monitor *mon, const 
>>>> QDict *qdict)
>>>>              params->max_postcopy_bandwidth);
>>>>          monitor_printf(mon, "%s: '%s'\n",
>>>>              MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ),
>>>> -            params->tls_authz);
>>>> +                       params->tls_authz ? params->tls_authz->u.s : "");
>>>>  
>>>>          if (params->has_block_bitmap_mapping) {
>>>>              const BitmapMigrationNodeAliasList *bmnal;
>>>
>>> Before, the code assumes ->tls_creds, ->tls_hostname, and ->tls_authz
>>> are non-null.  It assert its assumption for the first two.
>>>
>>> Afterwards, it maps null to "".  Why is that necessary?  Hmm, see below.
>>>
>>
>> Maps NULL to "" because the intermediate type, MigrationParameters, has
>> been changed from str to StrOrNull. For the purposes of info
>> migrate_parameters and query-migrate-parameters the only valid values
>> are a non-empty string or an empty string.
>
> But is NULL possible?  If you just change the type from str to StrOrNull
> and no more, it isn't.
>

Since the TLS options don't have a qdev property anymore, they also
don't get set a default value. So s->parameters can indeed have the NULL
value in it.

I could initialize them in migrate_params_init. It's all about choosing
where to move the complexity. I'm leaning towards keeping it in the
interface: query-migrate converts them to whatever it needs to output
and set-migrate writes a normalized version into s->parameters.

>>>> diff --git a/migration/migration.c b/migration/migration.c
>>>> index 4697732bef..f65cb81b6d 100644
>>>> --- a/migration/migration.c
>>>> +++ b/migration/migration.c
>>>> @@ -4053,6 +4053,8 @@ static void migration_instance_finalize(Object *obj)
>>>>  {
>>>>      MigrationState *ms = MIGRATION_OBJ(obj);
>>>>  
>>>> +    migrate_tls_opts_free(&ms->parameters);
>>>
>>> Is this a bug fix?
>>>
>>
>> My new version is a little different, but I can make it a separate patch
>> if that happens to be the case.
>
> Yes, please.
>
>>> As far as I can tell, the object gets destroyed only on QEMU shutdown.
>>> Freeing resources then is unnecessary, except it may help leak detection
>>> tools.
>>>
>>
>> From a maintenance perspective I consider any leak as a bug because I
>> don't have control over what kinds of leak detection tools are ran on
>> the code. To avoid spending time looking at such bug reports I have ASAN
>> automated in my testing and I fix early any leaks that it founds.
>>
>>>> +
>>>>      qemu_mutex_destroy(&ms->error_mutex);
>>>>      qemu_mutex_destroy(&ms->qemu_file_lock);
>>>>      qemu_sem_destroy(&ms->wait_unplug_sem);
>>>> diff --git a/migration/options.c b/migration/options.c
>>>> index 162c72cda4..45a95dc6da 100644
>>>> --- a/migration/options.c
>>>> +++ b/migration/options.c
>>>> @@ -162,9 +162,11 @@ const Property migration_properties[] = {
>>>>      DEFINE_PROP_SIZE("announce-step", MigrationState,
>>>>                        parameters.announce_step,
>>>>                        DEFAULT_MIGRATE_ANNOUNCE_STEP),
>>>> -    DEFINE_PROP_STRING("tls-creds", MigrationState, parameters.tls_creds),
>>>> -    DEFINE_PROP_STRING("tls-hostname", MigrationState, 
>>>> parameters.tls_hostname),
>>>> -    DEFINE_PROP_STRING("tls-authz", MigrationState, parameters.tls_authz),
>>>> +    /*
>>>> +     * tls-creds, tls-hostname and tls-authz are of type StrOrNull,
>>>> +     * which can't be easily handled (if at all) by qdev. So these
>>>> +     * will not be exposed as global migration options (-global).
>>>> +     */
>>>
>>> This is a compatibility break.
>>>
>>> The orthodox way to break it is deprecate, let the grace period expire,
>>> break.  Record in docs/about/deprecated.rst at the beginning, move the
>>> record to docs/about/removed-features.rst at the end.
>>>
>>> An argument could be made that the interface in question is
>>> accidental[*], not actually used by anything, and therefore breaking it
>>> without a grace period is fine.  But even then we should record the
>>> breakage in docs/about/removed-features.rst.
>>>
>>
>> Ok. Alternatively I could try a little harder to keep these
>> options. I'll see what I can do.
>
> What do we think about this external interface?
>
> If we think it's accidental and unused, then putting in more work to
> keep it makes no sense.
>
> If we think it's deliberate and/or used, we should either keep it, or
> replace it the orthodox way.
>

There are two external interfaces actually.

-global migration.some_compat_option=on (stored in MigrationState):

seems intentional and I believe we'd lose the ability to get out of some
tricky situations if we ditched it.

-global migation.some_random_option=on (stored in MigrationParameters):

has become a debugging *feature*, which I personally don't use, but
others do. And worse: we don't know if anyone uses it in production.

We also arbitrarily put x- in front of options for some reason. There is
an argument to drop those because x- is scary and no one should be using
them.

I think it would be good to at least separate the responsibilities so
when the time comes we can deprecate/remove/replace the offending
interfaces. But I won't go into that now, there's already too much
change going on for this release.


Reply via email to