render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
9119d9
From ec6edfd4fa89b918348318eeb3bca982a9f39ba2 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <ec6edfd4fa89b918348318eeb3bca982a9f39ba2@dist-git>
9119d9
From: Peter Krempa <pkrempa@redhat.com>
9119d9
Date: Mon, 24 Nov 2014 17:51:16 +0100
9119d9
Subject: [PATCH] qemu: chardev: Extract more information about character
9119d9
 devices
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1146944
9119d9
9119d9
Improve the monitor function to also retrieve the guest state of
9119d9
character device (if provided) so that we can refresh the state of
9119d9
virtio-serial channels and perhaps react to changes in the state in
9119d9
future patches.
9119d9
9119d9
This patch changes the returned data from qemuMonitorGetChardevInfo to
9119d9
return a structure containing the pty path and the state for all the
9119d9
character devices.
9119d9
9119d9
The change to the testsuite makes sure that the data is parsed
9119d9
correctly.
9119d9
9119d9
(cherry picked from commit 4d7eb903119ef61b58ced29432f4933b372e00ab)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_monitor.c      | 13 ++++++++++-
9119d9
 src/qemu/qemu_monitor.h      |  6 ++++++
9119d9
 src/qemu/qemu_monitor_json.c | 51 +++++++++++++++++++++++++++++---------------
9119d9
 src/qemu/qemu_monitor_text.c | 17 ++++++++++-----
9119d9
 src/qemu/qemu_process.c      |  8 +++----
9119d9
 tests/qemumonitorjsontest.c  | 41 +++++++++++++++++++++++++++++------
9119d9
 6 files changed, 103 insertions(+), 33 deletions(-)
9119d9
9119d9
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
9119d9
index 55a0542..38399ba 100644
9119d9
--- a/src/qemu/qemu_monitor.c
9119d9
+++ b/src/qemu/qemu_monitor.c
9119d9
@@ -2986,6 +2986,17 @@ qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static void
9119d9
+qemuMonitorChardevInfoFree(void *data,
9119d9
+                           const void *name ATTRIBUTE_UNUSED)
9119d9
+{
9119d9
+    qemuMonitorChardevInfoPtr info = data;
9119d9
+
9119d9
+    VIR_FREE(info->ptyPath);
9119d9
+    VIR_FREE(info);
9119d9
+}
9119d9
+
9119d9
+
9119d9
 int
9119d9
 qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
9119d9
                           virHashTablePtr *retinfo)
9119d9
@@ -3001,7 +3012,7 @@ qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
9119d9
         goto error;
9119d9
     }
9119d9
 
9119d9
-    if (!(info = virHashCreate(10, virHashValueFree)))
9119d9
+    if (!(info = virHashCreate(10, qemuMonitorChardevInfoFree)))
9119d9
         goto error;
9119d9
 
9119d9
     if (mon->json)
9119d9
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
9119d9
index 8ae0dbe..d1dc242 100644
9119d9
--- a/src/qemu/qemu_monitor.h
9119d9
+++ b/src/qemu/qemu_monitor.h
9119d9
@@ -649,6 +649,12 @@ int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
9119d9
 int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
                              virNetDevRxFilterPtr *filter);
9119d9
 
9119d9
+typedef struct _qemuMonitorChardevInfo qemuMonitorChardevInfo;
9119d9
+typedef qemuMonitorChardevInfo *qemuMonitorChardevInfoPtr;
9119d9
+struct _qemuMonitorChardevInfo {
9119d9
+    char *ptyPath;
9119d9
+    virDomainChrDeviceState state;
9119d9
+};
9119d9
 int qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
9119d9
                               virHashTablePtr *retinfo);
9119d9
 
9119d9
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
9119d9
index e5f49ef..34fb91f 100644
9119d9
--- a/src/qemu/qemu_monitor_json.c
9119d9
+++ b/src/qemu/qemu_monitor_json.c
9119d9
@@ -3557,7 +3557,7 @@ qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
9119d9
  *
9119d9
  * {"return": [
9119d9
  *      {"filename": "stdio", "label": "monitor"},
9119d9
- *      {"filename": "pty:/dev/pts/6", "label": "serial0"},
9119d9
+ *      {"filename": "pty:/dev/pts/6", "label": "serial0", "frontend-open": true},
9119d9
  *      {"filename": "pty:/dev/pts/7", "label": "parallel0"}
9119d9
  * ]}
9119d9
  *
9119d9
@@ -3569,6 +3569,7 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
9119d9
     virJSONValuePtr data;
9119d9
     int ret = -1;
9119d9
     size_t i;
9119d9
+    qemuMonitorChardevInfoPtr entry = NULL;
9119d9
 
9119d9
     if (!(data = virJSONValueObjectGet(reply, "return"))) {
9119d9
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
@@ -3583,44 +3584,60 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
9119d9
     }
9119d9
 
9119d9
     for (i = 0; i < virJSONValueArraySize(data); i++) {
9119d9
-        virJSONValuePtr entry = virJSONValueArrayGet(data, i);
9119d9
+        virJSONValuePtr chardev = virJSONValueArrayGet(data, i);
9119d9
         const char *type;
9119d9
-        const char *id;
9119d9
-        if (!entry) {
9119d9
+        const char *alias;
9119d9
+        bool connected;
9119d9
+
9119d9
+        if (!chardev) {
9119d9
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
                            _("character device information was missing array element"));
9119d9
             goto cleanup;
9119d9
         }
9119d9
 
9119d9
-        if (!(type = virJSONValueObjectGetString(entry, "filename"))) {
9119d9
+        if (!(alias = virJSONValueObjectGetString(chardev, "label"))) {
9119d9
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
-                           _("character device information was missing filename"));
9119d9
+                           _("character device information was missing label"));
9119d9
             goto cleanup;
9119d9
         }
9119d9
 
9119d9
-        if (!(id = virJSONValueObjectGetString(entry, "label"))) {
9119d9
+        if (!(type = virJSONValueObjectGetString(chardev, "filename"))) {
9119d9
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
                            _("character device information was missing filename"));
9119d9
             goto cleanup;
9119d9
         }
9119d9
 
9119d9
-        if (STRPREFIX(type, "pty:")) {
9119d9
-            char *path;
9119d9
-            if (VIR_STRDUP(path, type + strlen("pty:")) < 0)
9119d9
-                goto cleanup;
9119d9
+        if (VIR_ALLOC(entry) < 0)
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        if (STRPREFIX(type, "pty:") &&
9119d9
+            VIR_STRDUP(entry->ptyPath, type + strlen("pty:")) < 0)
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) {
9119d9
+            if (connected)
9119d9
+                entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
9119d9
+            else
9119d9
+                entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
9119d9
+        }
9119d9
 
9119d9
-            if (virHashAddEntry(info, id, path) < 0) {
9119d9
-                virReportError(VIR_ERR_OPERATION_FAILED,
9119d9
-                               _("failed to save chardev path '%s'"), path);
9119d9
-                VIR_FREE(path);
9119d9
-                goto cleanup;
9119d9
-            }
9119d9
+        if (virHashAddEntry(info, alias, entry) < 0) {
9119d9
+            virReportError(VIR_ERR_OPERATION_FAILED,
9119d9
+                           _("failed to add chardev '%s' info"), alias);
9119d9
+            goto cleanup;
9119d9
         }
9119d9
+
9119d9
+        entry = NULL;
9119d9
     }
9119d9
 
9119d9
     ret = 0;
9119d9
 
9119d9
  cleanup:
9119d9
+    if (entry) {
9119d9
+        VIR_FREE(entry->ptyPath);
9119d9
+        VIR_FREE(entry);
9119d9
+    }
9119d9
+
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
9119d9
index 634f9f3..aee9f35 100644
9119d9
--- a/src/qemu/qemu_monitor_text.c
9119d9
+++ b/src/qemu/qemu_monitor_text.c
9119d9
@@ -2176,6 +2176,7 @@ int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
9119d9
                                   virHashTablePtr info)
9119d9
 {
9119d9
     char *reply = NULL;
9119d9
+    qemuMonitorChardevInfoPtr entry = NULL;
9119d9
     int ret = -1;
9119d9
 
9119d9
     if (qemuMonitorHMPCommand(mon, "info chardev", &reply) < 0)
9119d9
@@ -2220,17 +2221,22 @@ int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
9119d9
 
9119d9
         /* Path is everything after needle to the end of the line */
9119d9
         *eol = '\0';
9119d9
-        char *path;
9119d9
-        if (VIR_STRDUP(path, needle + strlen(NEEDLE)) < 0)
9119d9
+
9119d9
+        if (VIR_ALLOC(entry) < 0)
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        if (VIR_STRDUP(entry->ptyPath, needle + strlen(NEEDLE)) < 0)
9119d9
             goto cleanup;
9119d9
 
9119d9
-        if (virHashAddEntry(info, id, path) < 0) {
9119d9
+        if (virHashAddEntry(info, id, entry) < 0) {
9119d9
             virReportError(VIR_ERR_OPERATION_FAILED,
9119d9
                            _("failed to save chardev path '%s'"),
9119d9
-                           path);
9119d9
-            VIR_FREE(path);
9119d9
+                           entry->ptyPath);
9119d9
+            VIR_FREE(entry->ptyPath);
9119d9
             goto cleanup;
9119d9
         }
9119d9
+
9119d9
+        entry = NULL;
9119d9
 #undef NEEDLE
9119d9
     }
9119d9
 
9119d9
@@ -2238,6 +2244,7 @@ int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
9119d9
 
9119d9
  cleanup:
9119d9
     VIR_FREE(reply);
9119d9
+    VIR_FREE(entry);
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
9119d9
index 7e1b9a2..ebcd5e8 100644
9119d9
--- a/src/qemu/qemu_process.c
9119d9
+++ b/src/qemu/qemu_process.c
9119d9
@@ -1919,15 +1919,15 @@ qemuProcessLookupPTYs(virDomainDefPtr def,
9119d9
 
9119d9
         if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
9119d9
             char id[32];
9119d9
-            const char *path;
9119d9
+            qemuMonitorChardevInfoPtr entry;
9119d9
 
9119d9
             if (snprintf(id, sizeof(id), "%s%s",
9119d9
                          chardevfmt ? "char" : "",
9119d9
                          chr->info.alias) >= sizeof(id))
9119d9
                 return -1;
9119d9
 
9119d9
-            path = (const char *) virHashLookup(info, id);
9119d9
-            if (path == NULL) {
9119d9
+            entry = virHashLookup(info, id);
9119d9
+            if (!entry || !entry->ptyPath) {
9119d9
                 if (chr->source.data.file.path == NULL) {
9119d9
                     /* neither the log output nor 'info chardev' had a
9119d9
                      * pty path for this chardev, report an error
9119d9
@@ -1944,7 +1944,7 @@ qemuProcessLookupPTYs(virDomainDefPtr def,
9119d9
             }
9119d9
 
9119d9
             VIR_FREE(chr->source.data.file.path);
9119d9
-            if (VIR_STRDUP(chr->source.data.file.path, path) < 0)
9119d9
+            if (VIR_STRDUP(chr->source.data.file.path, entry->ptyPath) < 0)
9119d9
                 return -1;
9119d9
         }
9119d9
     }
9119d9
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
9119d9
index afa2561..46c5f40 100644
9119d9
--- a/tests/qemumonitorjsontest.c
9119d9
+++ b/tests/qemumonitorjsontest.c
9119d9
@@ -1759,11 +1759,28 @@ testQemuMonitorJSONqemuMonitorJSONGetSpiceMigrationStatus(const void *data)
9119d9
 }
9119d9
 
9119d9
 static int
9119d9
-testHashEqualString(const void *value1, const void *value2)
9119d9
+testHashEqualChardevInfo(const void *value1, const void *value2)
9119d9
 {
9119d9
-    return strcmp(value1, value2);
9119d9
+    const qemuMonitorChardevInfo *info1 = value1;
9119d9
+    const qemuMonitorChardevInfo *info2 = value2;
9119d9
+
9119d9
+    if (info1->state != info2->state)
9119d9
+        goto error;
9119d9
+
9119d9
+    if (STRNEQ_NULLABLE(info1->ptyPath, info2->ptyPath))
9119d9
+        goto error;
9119d9
+
9119d9
+    return 0;
9119d9
+
9119d9
+ error:
9119d9
+    fprintf(stderr, "\n"
9119d9
+            "info1->state: %d info2->state: %d\n"
9119d9
+            "info1->ptyPath: %s info2->ptyPath: %s\n",
9119d9
+            info1->state, info2->state, info1->ptyPath, info2->ptyPath);
9119d9
+    return -1;
9119d9
 }
9119d9
 
9119d9
+
9119d9
 static int
9119d9
 testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
9119d9
 {
9119d9
@@ -1771,6 +1788,10 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
9119d9
     qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
9119d9
     int ret = -1;
9119d9
     virHashTablePtr info = NULL, expectedInfo = NULL;
9119d9
+    qemuMonitorChardevInfo info0 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
9119d9
+    qemuMonitorChardevInfo info1 = { (char *) "/dev/pts/21", VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED };
9119d9
+    qemuMonitorChardevInfo info2 = { (char *) "/dev/pts/20", VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
9119d9
+    qemuMonitorChardevInfo info3 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED };
9119d9
 
9119d9
     if (!test)
9119d9
         return -1;
9119d9
@@ -1779,8 +1800,10 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
9119d9
         !(expectedInfo = virHashCreate(32, NULL)))
9119d9
         goto cleanup;
9119d9
 
9119d9
-    if (virHashAddEntry(expectedInfo, "charserial1", (void *) "/dev/pts/21") < 0 ||
9119d9
-        virHashAddEntry(expectedInfo, "charserial0", (void *) "/dev/pts/20") < 0) {
9119d9
+    if (virHashAddEntry(expectedInfo, "charserial1", &info1) < 0 ||
9119d9
+        virHashAddEntry(expectedInfo, "charserial0", &info2) < 0 ||
9119d9
+        virHashAddEntry(expectedInfo, "charmonitor", &info0) < 0 ||
9119d9
+        virHashAddEntry(expectedInfo, "charserial2", &info3) < 0) {
9119d9
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
                        "Unable to create expectedInfo hash table");
9119d9
         goto cleanup;
9119d9
@@ -1791,7 +1814,8 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
9119d9
                                "    \"return\": ["
9119d9
                                "        {"
9119d9
                                "            \"filename\": \"pty:/dev/pts/21\","
9119d9
-                               "            \"label\": \"charserial1\""
9119d9
+                               "            \"label\": \"charserial1\","
9119d9
+                               "            \"frontend-open\": true"
9119d9
                                "        },"
9119d9
                                "        {"
9119d9
                                "            \"filename\": \"pty:/dev/pts/20\","
9119d9
@@ -1800,6 +1824,11 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
9119d9
                                "        {"
9119d9
                                "            \"filename\": \"unix:/var/lib/libvirt/qemu/gentoo.monitor,server\","
9119d9
                                "            \"label\": \"charmonitor\""
9119d9
+                               "        },"
9119d9
+                               "        {"
9119d9
+                               "            \"filename\": \"unix:/path/to/socket,server\","
9119d9
+                               "            \"label\": \"charserial2\","
9119d9
+                               "            \"frontend-open\": false"
9119d9
                                "        }"
9119d9
                                "    ],"
9119d9
                                "    \"id\": \"libvirt-15\""
9119d9
@@ -1810,7 +1839,7 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
9119d9
                                       info) < 0)
9119d9
         goto cleanup;
9119d9
 
9119d9
-    if (!virHashEqual(info, expectedInfo, testHashEqualString)) {
9119d9
+    if (!virHashEqual(info, expectedInfo, testHashEqualChardevInfo)) {
9119d9
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
                        "Hashtable is different to the expected one");
9119d9
         goto cleanup;
9119d9
-- 
9119d9
2.1.3
9119d9