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(a)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