diff --git a/hmp.c b/hmp.c index 9c6d8966bf..619b8ba70e 100644 --- a/hmp.c +++ b/hmp.c @@ -114,6 +114,37 @@ void hmp_info_mice(Monitor *mon) qapi_free_MouseInfoList(mice_list); } +void hmp_info_migrate(Monitor *mon) +{ + MigrationInfo *info; + + info = qmp_query_migrate(NULL); + + if (info->has_status) { + monitor_printf(mon, "Migration status: %s\n", info->status); + } + + if (info->has_ram) { + monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", + info->ram->transferred >> 10); + monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", + info->ram->remaining >> 10); + monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", + info->ram->total >> 10); + } + + if (info->has_disk) { + monitor_printf(mon, "transferred disk: %" PRIu64 " kbytes\n", + info->disk->transferred >> 10); + monitor_printf(mon, "remaining disk: %" PRIu64 " kbytes\n", + info->disk->remaining >> 10); + monitor_printf(mon, "total disk: %" PRIu64 " kbytes\n", + info->disk->total >> 10); + } + + qapi_free_MigrationInfo(info); +} + void hmp_quit(Monitor *mon, const QDict *qdict) { monitor_suspend(mon); diff --git a/hmp.h b/hmp.h index 4e6697da67..49d9662626 100644 --- a/hmp.h +++ b/hmp.h @@ -24,6 +24,7 @@ void hmp_info_status(Monitor *mon); void hmp_info_uuid(Monitor *mon); void hmp_info_chardev(Monitor *mon); void hmp_info_mice(Monitor *mon); +void hmp_info_migrate(Monitor *mon); void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); diff --git a/migration.c b/migration.c index bdca72e008..6c70f72ce3 100644 --- a/migration.c +++ b/migration.c @@ -19,7 +19,7 @@ #include "block.h" #include "qemu_socket.h" #include "block-migration.h" -#include "qemu-objects.h" +#include "qmp-commands.h" //#define DEBUG_MIGRATION @@ -107,53 +107,9 @@ uint64_t migrate_max_downtime(void) return max_downtime; } -static void migrate_print_status(Monitor *mon, const char *name, - const QDict *status_dict) +MigrationInfo *qmp_query_migrate(Error **errp) { - QDict *qdict; - - qdict = qobject_to_qdict(qdict_get(status_dict, name)); - - monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name, - qdict_get_int(qdict, "transferred") >> 10); - monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name, - qdict_get_int(qdict, "remaining") >> 10); - monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name, - qdict_get_int(qdict, "total") >> 10); -} - -void do_info_migrate_print(Monitor *mon, const QObject *data) -{ - QDict *qdict; - - qdict = qobject_to_qdict(data); - - monitor_printf(mon, "Migration status: %s\n", - qdict_get_str(qdict, "status")); - - if (qdict_haskey(qdict, "ram")) { - migrate_print_status(mon, "ram", qdict); - } - - if (qdict_haskey(qdict, "disk")) { - migrate_print_status(mon, "disk", qdict); - } -} - -static void migrate_put_status(QDict *qdict, const char *name, - uint64_t trans, uint64_t rem, uint64_t total) -{ - QObject *obj; - - obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", " - "'remaining': %" PRId64 ", " - "'total': %" PRId64 " }", trans, rem, total); - qdict_put_obj(qdict, name, obj); -} - -void do_info_migrate(Monitor *mon, QObject **ret_data) -{ - QDict *qdict; + MigrationInfo *info = g_malloc0(sizeof(*info)); MigrationState *s = migrate_get_current(); switch (s->state) { @@ -161,30 +117,38 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) /* no migration has happened ever */ break; case MIG_STATE_ACTIVE: - qdict = qdict_new(); - qdict_put(qdict, "status", qstring_from_str("active")); + info->has_status = true; + info->status = g_strdup("active"); - migrate_put_status(qdict, "ram", ram_bytes_transferred(), - ram_bytes_remaining(), ram_bytes_total()); + info->has_ram = true; + info->ram = g_malloc0(sizeof(*info->ram)); + info->ram->transferred = ram_bytes_transferred(); + info->ram->remaining = ram_bytes_remaining(); + info->ram->total = ram_bytes_total(); if (blk_mig_active()) { - migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(), - blk_mig_bytes_remaining(), - blk_mig_bytes_total()); + info->has_disk = true; + info->disk = g_malloc0(sizeof(*info->disk)); + info->disk->transferred = blk_mig_bytes_transferred(); + info->disk->remaining = blk_mig_bytes_remaining(); + info->disk->total = blk_mig_bytes_total(); } - - *ret_data = QOBJECT(qdict); break; case MIG_STATE_COMPLETED: - *ret_data = qobject_from_jsonf("{ 'status': 'completed' }"); + info->has_status = true; + info->status = g_strdup("completed"); break; case MIG_STATE_ERROR: - *ret_data = qobject_from_jsonf("{ 'status': 'failed' }"); + info->has_status = true; + info->status = g_strdup("failed"); break; case MIG_STATE_CANCELLED: - *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }"); + info->has_status = true; + info->status = g_strdup("cancelled"); break; } + + return info; } /* shared migration helpers */ diff --git a/monitor.c b/monitor.c index d95abce223..ea5ccd8f3d 100644 --- a/monitor.c +++ b/monitor.c @@ -2999,8 +2999,7 @@ static const mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show migration status", - .user_print = do_info_migrate_print, - .mhandler.info_new = do_info_migrate, + .mhandler.info = hmp_info_migrate, }, { .name = "balloon", @@ -3109,14 +3108,6 @@ static const mon_cmd_t qmp_query_cmds[] = { .mhandler.info_new = do_info_spice, }, #endif - { - .name = "migrate", - .args_type = "", - .params = "", - .help = "show migration status", - .user_print = do_info_migrate_print, - .mhandler.info_new = do_info_migrate, - }, { .name = "balloon", .args_type = "", diff --git a/qapi-schema.json b/qapi-schema.json index 3175c82135..eb155b4d54 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -225,6 +225,56 @@ ## { 'command': 'query-commands', 'returns': ['CommandInfo'] } +## +# @MigrationStats +# +# Detailed migration status. +# +# @transferred: amount of bytes already transferred to the target VM +# +# @remaining: amount of bytes remaining to be transferred to the target VM +# +# @total: total amount of bytes involved in the migration process +# +# Since: 0.14.0. +## +{ 'type': 'MigrationStats', + 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' } } + +## +# @MigrationInfo +# +# Information about current migration process. +# +# @status: #optional string describing the current migration status. +# As of 0.14.0 this can be 'active', 'completed', 'failed' or +# 'cancelled'. If this field is not returned, no migration process +# has been initiated +# +# @ram: #optional @MigrationStats containing detailed migration status, +# only returned if status is 'active' +# +# @disk: #optional @MigrationStats containing detailed disk migration +# status, only returned if status is 'active' and it is a block +# migration +# +# Since: 0.14.0 +## +{ 'type': 'MigrationInfo', + 'data': {'*status': 'str', '*ram': 'MigrationStats', + '*disk': 'MigrationStats'} } + +## +# @query-migrate +# +# Returns information about current migration process. +# +# Returns: @MigrationInfo +# +# Since: 0.14.0 +## +{ 'command': 'query-migrate', 'returns': 'MigrationInfo' } + ## # @MouseInfo: # diff --git a/qmp-commands.hx b/qmp-commands.hx index c5355601cc..8efdb25d0a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1919,6 +1919,12 @@ Examples: EQMP + { + .name = "query-migrate", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_migrate, + }, + SQMP query-balloon -------------