[libvirt] [PATCH 4/5] qemu_agent: add helper for getting guest users

Jonathon Jongsma jjongsma at redhat.com
Wed Jul 10 20:07:46 UTC 2019


This function fetches the list of logged-in users from the qemu agent
and converts them into a form that can be used internally in libvirt.

Also add some basic tests for the function.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 src/qemu/qemu_agent.c |  92 +++++++++++++++++++++++++++++++
 src/qemu/qemu_agent.h |   2 +
 tests/qemuagenttest.c | 125 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 361db299a5..b70d6806cd 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2240,3 +2240,95 @@ qemuAgentSetUserPassword(qemuAgentPtr mon,
     VIR_FREE(password64);
     return ret;
 }
+
+int
+qemuAgentGetUsers(qemuAgentPtr mon,
+                  virDomainUserInfoPtr **info)
+{
+    int ret = -1;
+    size_t i;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr data = NULL;
+    size_t ndata;
+    const char *result;
+    virDomainUserInfoPtr *users = NULL;
+
+    if (!(cmd = qemuAgentMakeCommand("guest-get-users", NULL)))
+        return -1;
+
+    if (qemuAgentCommand(mon, cmd, &reply, true,
+                         VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
+        goto cleanup;
+
+    if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("guest-get-users reply was missing return data"));
+        goto cleanup;
+    }
+
+    if (!virJSONValueIsArray(data)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Malformed guest-get-users data array"));
+        goto cleanup;
+    }
+
+    ndata = virJSONValueArraySize(data);
+
+    if (VIR_ALLOC_N(users, ndata) < 0)
+        goto cleanup;
+
+    for (i = 0; i < ndata; i++) {
+        virJSONValuePtr entry = virJSONValueArrayGet(data, i);
+        if (VIR_ALLOC(users[i]) < 0)
+            goto cleanup;
+
+        if (!entry) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("array element missing in guest-get-users return "
+                             "value"));
+            goto cleanup;
+        }
+
+        if (!(result = virJSONValueObjectGetString(entry, "user"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("'user' missing in reply of guest-get-users"));
+            goto cleanup;
+        }
+
+        if (VIR_STRDUP(users[i]->user, result) < 0) {
+            goto cleanup;
+        }
+
+        /* 'domain' is only present for windows guests */
+        if ((result = virJSONValueObjectGetString(entry, "domain"))) {
+            if (VIR_STRDUP(users[i]->domain, result) < 0) {
+                goto cleanup;
+            }
+        }
+
+        double loginseconds;
+        if (virJSONValueObjectGetNumberDouble(entry, "login-time", &loginseconds) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("'login-time' missing in reply of guest-get-users"));
+            goto cleanup;
+        }
+        /* convert to milliseconds */
+        users[i]->loginTime = loginseconds * 1000;
+    }
+
+    *info = users;
+    users = NULL;
+    ret = ndata;
+
+ cleanup:
+    if (users) {
+        for (i = 0; i < ndata; i++) {
+            virDomainUserInfoFree(users[i]);
+        }
+        VIR_FREE(users);
+    }
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 6ae9fe54da..70797dc894 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -120,3 +120,5 @@ int qemuAgentSetUserPassword(qemuAgentPtr mon,
                              const char *user,
                              const char *password,
                              bool crypted);
+
+int qemuAgentGetUsers(qemuAgentPtr mon, virDomainUserInfoPtr **info);
diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
index 2f79986207..d97f05102e 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -902,6 +902,130 @@ testQemuAgentGetInterfaces(const void *data)
     return ret;
 }
 
+static const char testQemuAgentUsersResponse[] =
+    "{\"return\": "
+    "   ["
+    "       {\"user\": \"test\","
+    "        \"login-time\": 1561739203.584038"
+    "       },"
+    "       {\"user\": \"test2\","
+    "        \"login-time\": 1561739229.190697"
+    "       }"
+    "   ]"
+    "}";
+
+static const char testQemuAgentUsersResponse2[] =
+    "{\"return\": "
+    "   ["
+    "       {\"user\": \"test\","
+    "        \"domain\": \"DOMAIN\","
+    "        \"login-time\": 1561739203.584038"
+    "       }"
+    "   ]"
+    "}";
+
+static int
+testQemuAgentUsers(const void *data)
+{
+    virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
+    qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
+    virDomainUserInfoPtr *userinfo = NULL;
+    int nusers;
+    int ret = -1;
+    int i;
+
+    if (!test)
+        return -1;
+
+    if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
+        goto cleanup;
+
+    if (qemuMonitorTestAddItem(test, "guest-get-users",
+                               testQemuAgentUsersResponse) < 0)
+        goto cleanup;
+
+    /* get users */
+    if ((nusers = qemuAgentGetUsers(qemuMonitorTestGetAgent(test),
+                                    &userinfo)) < 0)
+        goto cleanup;
+
+    if (nusers != 2) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected '2' users, got '%d'", nusers);
+        goto cleanup;
+    }
+    if (STRNEQ(userinfo[0]->user, "test")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected user name 'test', got '%s'", userinfo[0]->user);
+        goto cleanup;
+    }
+    if (userinfo[0]->loginTime != 1561739203.584038) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected login time of '1561739203584', got '%llu'",
+                       userinfo[0]->loginTime);
+        goto cleanup;
+    }
+
+    if (STRNEQ(userinfo[1]->user, "test2")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected user name 'test2', got '%s'", userinfo[1]->user);
+        goto cleanup;
+    }
+    if (userinfo[1]->loginTime != 1561739229.190697) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected login time of '1561739229190', got '%llu'",
+                       userinfo[1]->loginTime);
+        goto cleanup;
+    }
+
+    if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
+        goto cleanup;
+
+    if (qemuMonitorTestAddItem(test, "guest-get-users",
+                               testQemuAgentUsersResponse2) < 0)
+        goto cleanup;
+
+    VIR_FREE(userinfo);
+    /* get users with domain */
+    if ((nusers = qemuAgentGetUsers(qemuMonitorTestGetAgent(test),
+                                    &userinfo)) < 0)
+        goto cleanup;
+
+    if (nusers != 1) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected '1' user, got '%d'", nusers);
+        goto cleanup;
+    }
+
+    if (STRNEQ(userinfo[0]->user, "test")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected user name 'test', got '%s'", userinfo[0]->user);
+        goto cleanup;
+    }
+    if (userinfo[0]->loginTime != 1561739203.584038) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected login time of '1561739203584', got '%llu'",
+                       userinfo[0]->loginTime);
+        goto cleanup;
+    }
+    if (STRNEQ(userinfo[0]->domain, "DOMAIN")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "Expected domain 'DOMAIN', got '%s'", userinfo[0]->domain);
+        goto cleanup;
+    }
+    ret = 0;
+
+ cleanup:
+    if (nusers >= 0) {
+        for (i = 0; i < nusers; i++)
+            virDomainUserInfoFree(userinfo[i]);
+    }
+    VIR_FREE(userinfo);
+    qemuMonitorTestFree(test);
+    return ret;
+}
+
+
 static int
 mymain(void)
 {
@@ -931,6 +1055,7 @@ mymain(void)
     DO_TEST(CPU);
     DO_TEST(ArbitraryCommand);
     DO_TEST(GetInterfaces);
+    DO_TEST(Users);
 
     DO_TEST(Timeout); /* Timeout should always be called last */
 
-- 
2.20.1




More information about the libvir-list mailing list