From: "Dr. David Alan Gilbert" <dgilb...@redhat.com> Add somewhere for the various migration parameters to be set with one command;
As suggested in the thread: http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg00243.html There are many existing migration parameters that are scattered over many individual commands; moving those to this scheme would probably break things for others, so I've left them be. Preserve the migration tunable values across the reinit of the migration status in the same way that the capability flags are preserved. Add completion routine for it. Use the postcopy time out setting as the first parameter. Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com> --- hmp-commands.hx | 17 ++++++++++ hmp.c | 54 ++++++++++++++++++++++++++++++ hmp.h | 4 +++ include/migration/migration.h | 4 +++ migration.c | 78 ++++++++++++++++++++++++++++++++++--------- monitor.c | 25 ++++++++++++++ qapi-schema.json | 50 +++++++++++++++++++++++++++ qmp-commands.hx | 23 +++++++++++++ 8 files changed, 239 insertions(+), 16 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index d0943b1..4098a52 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -987,6 +987,21 @@ Enable/Disable the usage of a capability @var{capability} for migration. ETEXI { + .name = "migrate_set_parameter", + .args_type = "parameter:s,value:l", + .params = "parameter value", + .help = "Change the value of the given parameter", + .mhandler.cmd = hmp_migrate_set_parameter, + .command_completion = migrate_set_parameter_completion, + }, + +STEXI +@item migrate_set_parameter @var{parameter} @var{value} +@findex migrate_set_parameter +Change the value of a migration parameter @var{parameter}. +ETEXI + + { .name = "client_migrate_info", .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?", .params = "protocol hostname port tls-port cert-subject", @@ -1770,6 +1785,8 @@ show migration status show current migration capabilities @item info migrate_cache_size show current migration XBZRLE cache size +@item info migrate_parameters +show current migration parameters @item info balloon show balloon information @item info qtree diff --git a/hmp.c b/hmp.c index 4d1838e..1d14aa4 100644 --- a/hmp.c +++ b/hmp.c @@ -156,6 +156,9 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) monitor_printf(mon, "\n"); } + if (info->has_status) + hmp_info_migrate_parameters(mon, NULL); + if (info->has_status) { monitor_printf(mon, "Migration status: %s\n", info->status); monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", @@ -252,6 +255,25 @@ void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict) qmp_query_migrate_cache_size(NULL) >> 10); } +void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) +{ + MigrationParameterList *params, *param; + + params = qmp_query_migrate_parameters(NULL); + + if (params) { + monitor_printf(mon, "parameters: "); + for (param = params; param; param = param->next) { + monitor_printf(mon, "%s: %" PRIu64 " ", + MigrationParameterName_lookup[param->value->parameter], + param->value->value); + } + monitor_printf(mon, "\n"); + } + + qapi_free_MigrationParameterList(params); +} + void hmp_info_cpus(Monitor *mon, const QDict *qdict) { CpuInfoList *cpu_list, *cpu; @@ -1077,6 +1099,38 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict) } } +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) +{ + const char *param_name = qdict_get_str(qdict, "parameter"); + int64_t value = qdict_get_int(qdict, "value"); + Error *err = NULL; + MigrationParameterList *params = g_malloc0(sizeof(*params)); + int i; + + for (i = 0; i < MIGRATION_PARAMETER_NAME_MAX; i++) { + if (strcmp(param_name, MigrationParameterName_lookup[i]) == 0) { + params->value = g_malloc0(sizeof(*params->value)); + params->value->parameter = i; + params->value->value = value; + params->next = NULL; + qmp_migrate_set_parameters(params, &err); + break; + } + } + + if (i == MIGRATION_PARAMETER_NAME_MAX) { + error_set(&err, QERR_INVALID_PARAMETER, param_name); + } + + qapi_free_MigrationParameterList(params); + + if (err) { + monitor_printf(mon, "migrate_set_parameter: %s\n", + error_get_pretty(err)); + error_free(err); + } +} + void hmp_set_password(Monitor *mon, const QDict *qdict) { const char *protocol = qdict_get_str(qdict, "protocol"); diff --git a/hmp.h b/hmp.h index 4fd3c4a..609241c 100644 --- a/hmp.h +++ b/hmp.h @@ -29,6 +29,7 @@ void hmp_info_mice(Monitor *mon, const QDict *qdict); void hmp_info_migrate(Monitor *mon, const QDict *qdict); void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict); void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict); +void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict); void hmp_info_cpus(Monitor *mon, const QDict *qdict); void hmp_info_block(Monitor *mon, const QDict *qdict); void hmp_info_blockstats(Monitor *mon, const QDict *qdict); @@ -64,6 +65,7 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict); void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict); +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict); void hmp_set_password(Monitor *mon, const QDict *qdict); void hmp_expire_password(Monitor *mon, const QDict *qdict); void hmp_eject(Monitor *mon, const QDict *qdict); @@ -110,6 +112,8 @@ void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str); void migrate_set_capability_completion(ReadLineState *rs, int nb_args, const char *str); +void migrate_set_parameter_completion(ReadLineState *rs, int nb_args, + const char *str); void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str); void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str); diff --git a/include/migration/migration.h b/include/migration/migration.h index cf66921..d2754f7 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -35,6 +35,7 @@ #define QEMU_VM_SUBSECTION 0x05 #define QEMU_VM_COMMAND 0x06 +/* This is state currently only used by block */ struct MigrationParams { bool blk; bool shared; @@ -75,6 +76,7 @@ struct MigrationIncomingState { MigrationIncomingState *migration_incoming_state_init(QEMUFile *f); void migration_incoming_state_destroy(MigrationIncomingState *mis); +/* State for the outgoing migration */ struct MigrationState { int64_t bandwidth_limit; @@ -95,6 +97,8 @@ struct MigrationState int64_t dirty_pages_rate; int64_t dirty_bytes_rate; bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; + /* For migrate_set_parameters command */ + int64_t tunables[MIGRATION_PARAMETER_NAME_MAX]; int64_t xbzrle_cache_size; int64_t setup_time; int64_t dirty_sync_count; diff --git a/migration.c b/migration.c index 8343679..20ed6fa 100644 --- a/migration.c +++ b/migration.c @@ -226,6 +226,64 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) return head; } +void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, + Error **errp) +{ + MigrationState *s = migrate_get_current(); + MigrationCapabilityStatusList *cap; + + if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { + error_set(errp, QERR_MIGRATION_ACTIVE); + return; + } + + for (cap = params; cap; cap = cap->next) { + s->enabled_capabilities[cap->value->capability] = cap->value->state; + } +} + +void qmp_migrate_set_parameters(MigrationParameterList *params, + Error **errp) +{ + MigrationState *s = migrate_get_current(); + MigrationParameterList *parm; + + if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { + error_set(errp, QERR_MIGRATION_ACTIVE); + return; + } + + for (parm = params; parm; parm = parm->next) { + s->tunables[parm->value->parameter] = parm->value->value; + } +} + +MigrationParameterList *qmp_query_migrate_parameters(Error **errp) +{ + MigrationParameterList *head = NULL; + MigrationParameterList *parms; + MigrationState *s = migrate_get_current(); + int i; + + parms = NULL; + for (i = 0; i < MIGRATION_PARAMETER_NAME_MAX; i++) { + if (head == NULL) { + head = g_malloc0(sizeof(*parms)); + parms = head; + } else { + parms->next = g_malloc0(sizeof(*parms)); + parms = parms->next; + } + parms->value = + g_malloc(sizeof(*parms->value)); + parms->value->parameter = i; + parms->value->value = s->tunables[i]; + } + + return head; +} + + static void get_xbzrle_cache_stats(MigrationInfo *info) { if (migrate_use_xbzrle()) { @@ -326,22 +384,6 @@ MigrationInfo *qmp_query_migrate(Error **errp) return info; } -void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, - Error **errp) -{ - MigrationState *s = migrate_get_current(); - MigrationCapabilityStatusList *cap; - - if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { - error_set(errp, QERR_MIGRATION_ACTIVE); - return; - } - - for (cap = params; cap; cap = cap->next) { - s->enabled_capabilities[cap->value->capability] = cap->value->state; - } -} - /* shared migration helpers */ static void migrate_set_state(MigrationState *s, int old_state, int new_state) @@ -447,15 +489,19 @@ MigrationState *migrate_init(const MigrationParams *params) MigrationState *s = migrate_get_current(); int64_t bandwidth_limit = s->bandwidth_limit; bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; + int64_t tunables[MIGRATION_PARAMETER_NAME_MAX]; int64_t xbzrle_cache_size = s->xbzrle_cache_size; + /* Preserve user settings across this clear */ memcpy(enabled_capabilities, s->enabled_capabilities, sizeof(enabled_capabilities)); + memcpy(tunables, s->tunables, sizeof(tunables)); memset(s, 0, sizeof(*s)); s->params = *params; memcpy(s->enabled_capabilities, enabled_capabilities, sizeof(enabled_capabilities)); + memcpy(s->tunables, tunables, sizeof(tunables)); s->xbzrle_cache_size = xbzrle_cache_size; s->bandwidth_limit = bandwidth_limit; diff --git a/monitor.c b/monitor.c index 5bc70a6..f354b7b 100644 --- a/monitor.c +++ b/monitor.c @@ -2869,6 +2869,13 @@ static mon_cmd_t info_cmds[] = { .mhandler.cmd = hmp_info_migrate_cache_size, }, { + .name = "migrate_parameters", + .args_type = "", + .params = "", + .help = "show current migration parameters", + .mhandler.cmd = hmp_info_migrate_parameters, + }, + { .name = "balloon", .args_type = "", .params = "", @@ -4553,6 +4560,24 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args, } } +void migrate_set_parameter_completion(ReadLineState *rs, int nb_args, + const char *str) +{ + size_t len; + + len = strlen(str); + readline_set_completion_index(rs, len); + if (nb_args == 2) { + int i; + for (i = 0; i < MIGRATION_PARAMETER_NAME_MAX; i++) { + const char *name = MigrationParameterName_lookup[i]; + if (!strncmp(str, name, len)) { + readline_add_completion(rs, name); + } + } + } +} + void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str) { int i; diff --git a/qapi-schema.json b/qapi-schema.json index eac3739..678ad26 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -538,6 +538,56 @@ { 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']} ## +# @MigrationParameterName +# +# Migration parameter enumeration +# Most existing parameters have separate commands/entries but it seems +# better to group them in the same way as the capability flags +# +# @x-postcopy-start-time: Time (in ms) after the start of migration to consider +# switching to postcopy mode +# +# Since: 2.0 +## +{ 'enum': 'MigrationParameterName', + 'data': ['x-postcopy-start-time'] } + +## +# @MigrationParameter +# @parameter: parameter enum +# +# @value: value int +# +# Since: 2.0 +## +{ 'type': 'MigrationParameter', + 'data': {'parameter': 'MigrationParameterName', 'value': 'int' } } + +## +# @migrate-set-parameters +# +# Change the given migration parameter +# +# @parameters: json array of parameters to be changed +# +# Since: 2.0 +## +{ 'command': 'migrate-set-parameters', + 'data': { 'parameters': ['MigrationParameter']}} + +## +# @query-migrate-parameters +# +# Returns the current settings of the migration parameters +# +# Returns: @MigrationParameter +# +# Since: 2.0 +## +{ 'command': 'query-migrate-parameters', + 'returns': ['MigrationParameter']} + +## # @MouseInfo: # # Information about a mouse device. diff --git a/qmp-commands.hx b/qmp-commands.hx index 4be4765..7931c6a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3202,6 +3202,29 @@ EQMP .mhandler.cmd_new = qmp_marshal_input_migrate_set_capabilities, }, SQMP +migrate-set-parameters +------------------------ + +Set migration parameters + +- "x-postcopy-start-time": Postcopy start time + +Arguments: + +Example: + +-> { "execute": "migrate-set-parameters" , "arguments": + { "parameters": [ { "parameter": "x-postcopy-start-time", "value": 30 } ] } } + +EQMP + + { + .name = "migrate-set-parameters", + .args_type = "parameters:O", + .params = "parameter:s,value:i", + .mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters, + }, +SQMP query-migrate-capabilities -------------------------- -- 1.9.3