Add 'query-events' command to QMP to query async events
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 <berrange@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									5f96415527
								
							
						
					
					
						commit
						4860853d60
					
				
							
								
								
									
										107
									
								
								monitor.c
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								monitor.c
									
									
									
									
									
								
							| @ -422,6 +422,30 @@ 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_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED", | ||||
|     [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", | ||||
|     [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", | ||||
|     [QEVENT_SUSPEND] = "SUSPEND", | ||||
|     [QEVENT_WAKEUP] = "WAKEUP", | ||||
| }; | ||||
| QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) | ||||
| 
 | ||||
| /**
 | ||||
|  * monitor_protocol_event(): Generate a Monitor event | ||||
|  * | ||||
| @ -435,68 +459,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_BLOCK_JOB_COMPLETED: | ||||
|             event_name = "BLOCK_JOB_COMPLETED"; | ||||
|             break; | ||||
|         case QEVENT_BLOCK_JOB_CANCELLED: | ||||
|             event_name = "BLOCK_JOB_CANCELLED"; | ||||
|             break; | ||||
|         case QEVENT_DEVICE_TRAY_MOVED: | ||||
|              event_name = "DEVICE_TRAY_MOVED"; | ||||
|             break; | ||||
|         case QEVENT_SUSPEND: | ||||
|             event_name = "SUSPEND"; | ||||
|             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); | ||||
| @ -738,6 +702,25 @@ CommandInfoList *qmp_query_commands(Error **errp) | ||||
|     return cmd_list; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| /* set the current CPU defined by the user */ | ||||
| int monitor_set_cpu(int cpu_index) | ||||
| { | ||||
|  | ||||
| @ -41,6 +41,10 @@ typedef enum MonitorEvent { | ||||
|     QEVENT_DEVICE_TRAY_MOVED, | ||||
|     QEVENT_SUSPEND, | ||||
|     QEVENT_WAKEUP, | ||||
| 
 | ||||
|     /* Add to 'monitor_event_names' array in monitor.c when
 | ||||
|      * defining new events here */ | ||||
| 
 | ||||
|     QEVENT_MAX, | ||||
| } MonitorEvent; | ||||
| 
 | ||||
|  | ||||
| @ -227,6 +227,28 @@ | ||||
| ## | ||||
| { 'command': 'query-commands', 'returns': ['CommandInfo'] } | ||||
| 
 | ||||
| ## | ||||
| # @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'] } | ||||
| 
 | ||||
| ## | ||||
| # @MigrationStats | ||||
| # | ||||
|  | ||||
| @ -1208,6 +1208,43 @@ EQMP | ||||
|         .mhandler.cmd_new = qmp_marshal_input_query_commands, | ||||
|     }, | ||||
| 
 | ||||
| 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  = "", | ||||
|         .mhandler.cmd_new = qmp_marshal_input_query_events, | ||||
|     }, | ||||
| 
 | ||||
| SQMP | ||||
| query-chardev | ||||
| ------------- | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Daniel P. Berrange
						Daniel P. Berrange