qemu: add helper for getting guest users

This function fetches the list of logged-in users from the qemu agent
and adds them to a list of typed parameters so that they can be used
internally in libvirt.

Also add some basic tests for the function.

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
This commit is contained in:
Jonathon Jongsma 2019-08-23 11:31:17 -05:00 committed by Michal Privoznik
parent e8b83b2aac
commit 1c8113f9c8
3 changed files with 238 additions and 0 deletions

View File

@ -2240,3 +2240,88 @@ qemuAgentSetUserPassword(qemuAgentPtr mon,
VIR_FREE(password64);
return ret;
}
int
qemuAgentGetUsers(qemuAgentPtr mon,
virTypedParameterPtr *params,
int *nparams,
int *maxparams)
{
VIR_AUTOPTR(virJSONValue) cmd = NULL;
VIR_AUTOPTR(virJSONValue) reply = NULL;
virJSONValuePtr data = NULL;
size_t ndata;
size_t i;
if (!(cmd = qemuAgentMakeCommand("guest-get-users", NULL)))
return -1;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
return -1;
if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest-get-users reply was missing return data"));
return -1;
}
if (!virJSONValueIsArray(data)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Malformed guest-get-users data array"));
return -1;
}
ndata = virJSONValueArraySize(data);
if (virTypedParamsAddUInt(params, nparams, maxparams,
"user.count", ndata) < 0)
return -1;
for (i = 0; i < ndata; i++) {
virJSONValuePtr entry = virJSONValueArrayGet(data, i);
char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
const char *strvalue;
double logintime;
if (!entry) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("array element missing in guest-get-users return "
"value"));
return -1;
}
if (!(strvalue = virJSONValueObjectGetString(entry, "user"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("'user' missing in reply of guest-get-users"));
return -1;
}
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "user.%zu.name", i);
if (virTypedParamsAddString(params, nparams, maxparams,
param_name, strvalue) < 0)
return -1;
/* 'domain' is only present for windows guests */
if ((strvalue = virJSONValueObjectGetString(entry, "domain"))) {
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
"user.%zu.domain", i);
if (virTypedParamsAddString(params, nparams, maxparams,
param_name, strvalue) < 0)
return -1;
}
if (virJSONValueObjectGetNumberDouble(entry, "login-time", &logintime) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("'login-time' missing in reply of guest-get-users"));
return -1;
}
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
"user.%zu.login-time", i);
if (virTypedParamsAddULLong(params, nparams, maxparams,
param_name, logintime * 1000) < 0)
return -1;
}
return ndata;
}

View File

@ -120,3 +120,8 @@ int qemuAgentSetUserPassword(qemuAgentPtr mon,
const char *user,
const char *password,
bool crypted);
int qemuAgentGetUsers(qemuAgentPtr mon,
virTypedParameterPtr *params,
int *nparams,
int *maxparams);

View File

@ -902,6 +902,153 @@ 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
checkUserInfo(virTypedParameterPtr params,
int nparams,
size_t nth,
const char *expUsername,
const char *expDomain,
unsigned long long expLogintime)
{
char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
const char *username = NULL;
const char *domain = NULL;
unsigned long long logintime = 0;
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
"user.%zu.name", nth);
if (virTypedParamsGetString(params, nparams, param_name, &username) < 0)
return -1;
if (STRNEQ_NULLABLE(expUsername, username)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Expected user name '%s', got '%s'",
expUsername, username);
return -1;
}
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
"user.%zu.domain", nth);
virTypedParamsGetString(params, nparams, param_name, &domain);
if (STRNEQ_NULLABLE(expDomain, domain)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Expected domain '%s', got '%s'",
NULLSTR(expDomain), NULLSTR(domain));
return -1;
}
snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
"user.%zu.login-time", nth);
if (virTypedParamsGetULLong(params, nparams, param_name, &logintime) < 0)
return -1;
if (expLogintime != logintime) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Expected login time of '%llu', got '%llu'",
expLogintime, logintime);
return -1;
}
return 0;
}
static int
testQemuAgentUsers(const void *data)
{
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
virTypedParameterPtr params = NULL;
int nparams = 0;
int maxparams = 0;
int ret = -1;
unsigned int count;
if (!test)
return -1;
if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
goto cleanup;
if (qemuMonitorTestAddItem(test, "guest-get-users",
testQemuAgentUsersResponse) < 0)
goto cleanup;
/* get users */
if (qemuAgentGetUsers(qemuMonitorTestGetAgent(test),
&params, &nparams, &maxparams) < 0)
goto cleanup;
if (virTypedParamsGetUInt(params, nparams, "user.count", &count) < 0)
goto cleanup;
if (count != 2) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Expected '2' users, got '%u'", count);
goto cleanup;
}
if (checkUserInfo(params, nparams, 0, "test", NULL, 1561739203584) < 0 ||
checkUserInfo(params, nparams, 1, "test2", NULL, 1561739229190) < 0)
goto cleanup;
if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
goto cleanup;
if (qemuMonitorTestAddItem(test, "guest-get-users",
testQemuAgentUsersResponse2) < 0)
goto cleanup;
virTypedParamsFree(params, nparams);
params = NULL;
nparams = 0;
maxparams = 0;
/* get users with domain */
if (qemuAgentGetUsers(qemuMonitorTestGetAgent(test),
&params, &nparams, &maxparams) < 0)
goto cleanup;
if (virTypedParamsGetUInt(params, nparams, "user.count", &count) < 0)
goto cleanup;
if (count != 1) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Expected '1' user, got '%u'", count);
goto cleanup;
}
if (checkUserInfo(params, nparams, 0, "test", "DOMAIN", 1561739203584) < 0)
goto cleanup;
ret = 0;
cleanup:
virTypedParamsFree(params, nparams);
qemuMonitorTestFree(test);
return ret;
}
static int
mymain(void)
{
@ -931,6 +1078,7 @@ mymain(void)
DO_TEST(CPU);
DO_TEST(ArbitraryCommand);
DO_TEST(GetInterfaces);
DO_TEST(Users);
DO_TEST(Timeout); /* Timeout should always be called last */