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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list