
On Wed, Nov 19, 2014 at 11:23:20 +0100, Peter Krempa wrote:
Improve the monitor function to also retrieve the guest state of character device (if provided) so that we can refresh the state of virtio-serial channels and perhaps react to changes in the state in future patches.
This patch changes the returned data from qemuMonitorGetChardevInfo to return a structure containing the pty path and the state if the info is relevant.
The change to the testsuite makes sure that the data is parsed correctly. --- src/qemu/qemu_monitor.c | 13 +++++++++++- src/qemu/qemu_monitor.h | 6 ++++++ src/qemu/qemu_monitor_json.c | 48 +++++++++++++++++++++++++++++++++----------- src/qemu/qemu_monitor_text.c | 17 +++++++++++----- src/qemu/qemu_process.c | 8 ++++---- tests/qemumonitorjsontest.c | 39 +++++++++++++++++++++++++++++------ 6 files changed, 103 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 926619f..c9c84f9 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2982,6 +2982,17 @@ qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias, }
+static void +qemuMonitorChardevInfoFree(void *data, + const void *name ATTRIBUTE_UNUSED) +{ + qemuMonitorChardevInfoPtr info = data; + + VIR_FREE(info->ptyPath); + VIR_FREE(info); +} + + int qemuMonitorGetChardevInfo(qemuMonitorPtr mon, virHashTablePtr *retinfo) @@ -2997,7 +3008,7 @@ qemuMonitorGetChardevInfo(qemuMonitorPtr mon, goto error; }
- if (!(info = virHashCreate(10, virHashValueFree))) + if (!(info = virHashCreate(10, qemuMonitorChardevInfoFree))) goto error;
if (mon->json) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 3078be0..21533a4 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -649,6 +649,12 @@ int qemuMonitorRemoveNetdev(qemuMonitorPtr mon, int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias, virNetDevRxFilterPtr *filter);
+typedef struct _qemuMonitorChardevInfo qemuMonitorChardevInfo; +typedef qemuMonitorChardevInfo *qemuMonitorChardevInfoPtr; +struct _qemuMonitorChardevInfo { + char *ptyPath; + virDomainChrDeviceState state; +}; int qemuMonitorGetChardevInfo(qemuMonitorPtr mon, virHashTablePtr *retinfo);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 9c8a6fb..5429382 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3426,6 +3426,9 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply, virJSONValuePtr data; int ret = -1; size_t i; + char *ptyPath = NULL; + virDomainChrDeviceState state; + qemuMonitorChardevInfoPtr entry = NULL;
if (!(data = virJSONValueObjectGet(reply, "return"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -3440,44 +3443,65 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply, }
for (i = 0; i < virJSONValueArraySize(data); i++) { - virJSONValuePtr entry = virJSONValueArrayGet(data, i); + virJSONValuePtr chardev = virJSONValueArrayGet(data, i); const char *type; - const char *id; - if (!entry) { + const char *alias; + bool connected; + + if (!chardev) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("character device information was missing array element")); goto cleanup; }
- if (!(type = virJSONValueObjectGetString(entry, "filename"))) { + if (!(alias = virJSONValueObjectGetString(chardev, "label"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("character device information was missing filename")); + _("character device information was missing alias"));
Shouldn't we report that device information was missing label rather than alias as we are referring to a field in the QMP event?
goto cleanup; }
- if (!(id = virJSONValueObjectGetString(entry, "label"))) { + if (!(type = virJSONValueObjectGetString(chardev, "filename"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("character device information was missing filename")); goto cleanup; }
- if (STRPREFIX(type, "pty:")) { - char *path; - if (VIR_STRDUP(path, type + strlen("pty:")) < 0) + if (STRPREFIX(type, "pty:") && + VIR_STRDUP(ptyPath, type + strlen("pty:")) < 0) + goto cleanup; + + if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) { + if (connected) + state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED; + else + state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED; + } + + if (ptyPath || state != VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT) {
It took me a while to understand what you want to do here :-) So you want store only "pty:" char devices or char devices with "frontend-open" field, right? Any reason for this filtering (apart from the fact we don't care about other devices now)? I guess storing all devices would work too and the code would be a bit simpler. Or am I wrong?
+ if (VIR_ALLOC(entry) < 0) goto cleanup;
- if (virHashAddEntry(info, id, path) < 0) { + entry->ptyPath = ptyPath; + entry->state = state; + + if (virHashAddEntry(info, alias, entry) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, - _("failed to save chardev path '%s'"), path); - VIR_FREE(path); + _("failed to add chardev '%s' info"), alias); goto cleanup; } + + entry = NULL; + ptyPath = NULL; + state = VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT;
Ah, you managed to confuse me again :-) I'd prefer if you moved the "virDomainChrDeviceState state;" declaration inside the for loop and initialized state to VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT there. However, if you follow my suggestion to remove the condition above, you can avoid state variable completely and rather assign to entry->state directly (after moving the allocation of entry before checking for frontend-open, of course).
} }
ret = 0;
cleanup: + VIR_FREE(entry); + VIR_FREE(ptyPath); + return ret; }
... Jirka