From caa17055f3f1b12be5b2d1baa48c1764e89a3b70 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Luiz Capitulino Date: Tue, 11 Dec 2012 15:26:25 +0100 Subject: [PATCH 3/5] Add 'query-events' command to QMP to query async events RH-Author: Luiz Capitulino Message-id: <1355239587-12473-3-git-send-email-lcapitulino@redhat.com> Patchwork-id: 44910 O-Subject: [RHEL6.4 qemu-kvm PATCH 2/4] Add 'query-events' command to QMP to query async events Bugzilla: 881732 RH-Acked-by: Paolo Bonzini RH-Acked-by: Kevin Wolf RH-Acked-by: Markus Armbruster From: "Daniel P. Berrange" Sometimes it is neccessary for an application to determine whether a particular QMP event is available, so they can decide whether to use compatibility code instead. This introduces a new 'query-events' command to QMP to do just that { "execute": "query-events" } {"return": [{"name": "WAKEUP"}, {"name": "SUSPEND"}, {"name": "DEVICE_TRAY_MOVED"}, {"name": "BLOCK_JOB_CANCELLED"}, {"name": "BLOCK_JOB_COMPLETED"}, ...snip... {"name": "SHUTDOWN"}]} * monitor.c: Turn MonitorEvent -> string conversion into a lookup from a static table of constant strings. Add impl of qmp_query_events monitor command handler * qapi-schema.json, qmp-commands.hx: Define contract of query-events command Signed-off-by: Daniel P. Berrange Signed-off-by: Luiz Capitulino (cherry picked from commit 4860853d60ecea44b65e9cdefce980de3a641dce) Conflicts: monitor.c monitor.h qapi-schema.json qmp-commands.hx Signed-off-by: Luiz Capitulino --- monitor.c | 123 ++++++++++++++++++++++--------------------------------- monitor.h | 4 ++ qapi-schema.json | 22 ++++++++++ qemu-monitor.hx | 39 ++++++++++++++++++ 4 files changed, 114 insertions(+), 74 deletions(-) Signed-off-by: Michal Novotny --- monitor.c | 123 ++++++++++++++++++++++--------------------------------- monitor.h | 4 ++ qapi-schema.json | 22 ++++++++++ qemu-monitor.hx | 39 ++++++++++++++++++ 4 files changed, 114 insertions(+), 74 deletions(-) diff --git a/monitor.c b/monitor.c index a2836bc..1c903b8 100644 --- a/monitor.c +++ b/monitor.c @@ -428,6 +428,34 @@ static void timestamp_put(QDict *qdict) qdict_put_obj(qdict, "timestamp", obj); } + +static const char *monitor_event_names[] = { + [QEVENT_SHUTDOWN] = "SHUTDOWN", + [QEVENT_RESET] = "RESET", + [QEVENT_POWERDOWN] = "POWERDOWN", + [QEVENT_STOP] = "STOP", + [QEVENT_RESUME] = "RESUME", + [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED", + [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED", + [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED", + [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR", + [QEVENT_RTC_CHANGE] = "RTC_CHANGE", + [QEVENT_WATCHDOG] = "WATCHDOG", + [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED", + [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED", + [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED", + [QEVENT_RH_SPICE_INITIALIZED] = RFQDN_REDHAT "SPICE_INITIALIZED", + [QEVENT_RH_SPICE_DISCONNECTED] = RFQDN_REDHAT "SPICE_DISCONNECTED", + [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED", + [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", + [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", + [QEVENT_SUSPEND] = "SUSPEND", + [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", + [QEVENT_WAKEUP] = "WAKEUP", + [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED", +}; +QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) + /** * monitor_protocol_event(): Generate a Monitor event * @@ -441,80 +469,8 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) assert(event < QEVENT_MAX); - switch (event) { - case QEVENT_SHUTDOWN: - event_name = "SHUTDOWN"; - break; - case QEVENT_RESET: - event_name = "RESET"; - break; - case QEVENT_POWERDOWN: - event_name = "POWERDOWN"; - break; - case QEVENT_STOP: - event_name = "STOP"; - break; - case QEVENT_RESUME: - event_name = "RESUME"; - break; - case QEVENT_VNC_CONNECTED: - event_name = "VNC_CONNECTED"; - break; - case QEVENT_VNC_INITIALIZED: - event_name = "VNC_INITIALIZED"; - break; - case QEVENT_VNC_DISCONNECTED: - event_name = "VNC_DISCONNECTED"; - break; - case QEVENT_BLOCK_IO_ERROR: - event_name = "BLOCK_IO_ERROR"; - break; - case QEVENT_RTC_CHANGE: - event_name = "RTC_CHANGE"; - break; - case QEVENT_WATCHDOG: - event_name = "WATCHDOG"; - break; - case QEVENT_SPICE_CONNECTED: - event_name = "SPICE_CONNECTED"; - break; - case QEVENT_SPICE_INITIALIZED: - event_name = "SPICE_INITIALIZED"; - break; - case QEVENT_SPICE_DISCONNECTED: - event_name = "SPICE_DISCONNECTED"; - break; - case QEVENT_SPICE_MIGRATE_COMPLETED: - event_name = "SPICE_MIGRATE_COMPLETED"; - break; - case QEVENT_DEVICE_TRAY_MOVED: - event_name = "DEVICE_TRAY_MOVED"; - break; - case QEVENT_BLOCK_JOB_COMPLETED: - event_name = "BLOCK_JOB_COMPLETED"; - break; - case QEVENT_BLOCK_JOB_CANCELLED: - event_name = "BLOCK_JOB_CANCELLED"; - break; - case QEVENT_RH_SPICE_INITIALIZED: - event_name = RFQDN_REDHAT "SPICE_INITIALIZED"; - break; - case QEVENT_RH_SPICE_DISCONNECTED: - event_name = RFQDN_REDHAT "SPICE_DISCONNECTED"; - break; - case QEVENT_SUSPEND: - event_name = "SUSPEND"; - break; - case QEVENT_SUSPEND_DISK: - event_name = "SUSPEND_DISK"; - break; - case QEVENT_WAKEUP: - event_name = "WAKEUP"; - break; - default: - abort(); - break; - } + event_name = monitor_event_names[event]; + assert(event_name != NULL); qmp = qdict_new(); timestamp_put(qmp); @@ -868,6 +824,25 @@ static void do_info_uuid_print(Monitor *mon, const QObject *data) monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID")); } +EventInfoList *qmp_query_events(Error **errp) +{ + EventInfoList *info, *ev_list = NULL; + MonitorEvent e; + + for (e = 0 ; e < QEVENT_MAX ; e++) { + const char *event_name = monitor_event_names[e]; + assert(event_name != NULL); + info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + info->value->name = g_strdup(event_name); + + info->next = ev_list; + ev_list = info; + } + + return ev_list; +} + static void do_info_uuid(Monitor *mon, QObject **ret_data) { char uuid[64]; diff --git a/monitor.h b/monitor.h index 60c7a90..ff3ff3e 100644 --- a/monitor.h +++ b/monitor.h @@ -48,6 +48,10 @@ typedef enum MonitorEvent { QEVENT_SUSPEND_DISK, QEVENT_WAKEUP, QEVENT_SPICE_MIGRATE_COMPLETED, + + /* Add to 'monitor_event_names' array in monitor.c when + * defining new events here */ + QEVENT_MAX, } MonitorEvent; diff --git a/qapi-schema.json b/qapi-schema.json index 07b84df..d6cbf05 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -224,6 +224,28 @@ #endif ## +# @EventInfo: +# +# Information about a QMP event +# +# @name: The event name +# +# Since: 1.2.0 +## +{ 'type': 'EventInfo', 'data': {'name': 'str'} } + +## +# @query-events: +# +# Return a list of supported QMP events by this server +# +# Returns: A list of @EventInfo for all supported events +# +# Since: 1.2.0 +## +{ 'command': 'query-events', 'returns': ['EventInfo'] } + +## # @dump-guest-memory # # Dump guest's memory to vmcore. It is a synchronous operation that can take diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 9689d4b..ea163bb 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -2452,6 +2452,45 @@ Note: This example has been shortened as the real response is too long. EQMP +SQMP +query-events +-------------- + +List QMP available events. + +Each event is represented by a json-object, the returned value is a json-array +of all events. + +Each json-object contains: + +- "name": event's name (json-string) + +Example: + +-> { "execute": "query-events" } +<- { + "return":[ + { + "name":"SHUTDOWN" + }, + { + "name":"RESET" + } + ] + } + +Note: This example has been shortened as the real response is too long. + +EQMP + + { + .name = "query-events", + .args_type = "", + .user_print = monitor_user_noop, + .mhandler.cmd_new = qmp_marshal_input_query_events, + .flags = MONITOR_CMD_QMP_ONLY + }, + STEXI @item info network show the various VLANs and the associated devices -- 1.7.11.7