mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 09:17:52 +03:00
qemu_agent: add qemuAgentGetDisks
guest-get-disks is available since QEMU 5.2: https://wiki.qemu.org/ChangeLog/5.2#Guest_agent Note that the test response was manually edited based on a reply on my bare-metal computer. It shows partial results due to pcieport driver not being currently supported by QGA. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Tested-by: Han Han <hhan@redhat.com>
This commit is contained in:
parent
3169db81f6
commit
8401a586a2
@ -1827,6 +1827,21 @@ qemuAgentDiskAddressFree(qemuAgentDiskAddressPtr info)
|
||||
g_free(info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
qemuAgentDiskInfoFree(qemuAgentDiskInfoPtr info)
|
||||
{
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
g_free(info->name);
|
||||
g_strfreev(info->dependencies);
|
||||
qemuAgentDiskAddressFree(info->address);
|
||||
g_free(info->alias);
|
||||
g_free(info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
qemuAgentFSInfoFree(qemuAgentFSInfoPtr info)
|
||||
{
|
||||
@ -2639,3 +2654,80 @@ qemuAgentSSHRemoveAuthorizedKeys(qemuAgentPtr agent,
|
||||
|
||||
return qemuAgentCommand(agent, cmd, &reply, agent->timeout);
|
||||
}
|
||||
|
||||
|
||||
int qemuAgentGetDisks(qemuAgentPtr agent,
|
||||
qemuAgentDiskInfoPtr **disks,
|
||||
bool report_unsupported)
|
||||
{
|
||||
g_autoptr(virJSONValue) cmd = NULL;
|
||||
g_autoptr(virJSONValue) reply = NULL;
|
||||
virJSONValuePtr data = NULL;
|
||||
size_t ndata;
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
if (!(cmd = qemuAgentMakeCommand("guest-get-disks", NULL)))
|
||||
return -1;
|
||||
|
||||
if ((rc = qemuAgentCommandFull(agent, cmd, &reply, agent->timeout,
|
||||
report_unsupported)) < 0)
|
||||
return rc;
|
||||
|
||||
if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("qemu agent didn't return an array of disks"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ndata = virJSONValueArraySize(data);
|
||||
|
||||
*disks = g_new0(qemuAgentDiskInfoPtr, ndata);
|
||||
|
||||
for (i = 0; i < ndata; i++) {
|
||||
virJSONValuePtr addr;
|
||||
virJSONValuePtr entry = virJSONValueArrayGet(data, i);
|
||||
qemuAgentDiskInfoPtr disk;
|
||||
|
||||
if (!entry) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("array element missing in guest-get-disks return "
|
||||
"value"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
disk = g_new0(qemuAgentDiskInfo, 1);
|
||||
(*disks)[i] = disk;
|
||||
|
||||
disk->name = g_strdup(virJSONValueObjectGetString(entry, "name"));
|
||||
if (!disk->name) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("'name' missing in reply of guest-get-disks"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetBoolean(entry, "partition", &disk->partition) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("'partition' missing in reply of guest-get-disks"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
disk->dependencies = virJSONValueObjectGetStringArray(entry, "dependencies");
|
||||
disk->alias = g_strdup(virJSONValueObjectGetString(entry, "alias"));
|
||||
addr = virJSONValueObjectGetObject(entry, "address");
|
||||
if (addr) {
|
||||
disk->address = qemuAgentGetDiskAddress(addr);
|
||||
if (!disk->address)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return ndata;
|
||||
|
||||
error:
|
||||
for (i = 0; i < ndata; i++) {
|
||||
qemuAgentDiskInfoFree((*disks)[i]);
|
||||
}
|
||||
g_free(*disks);
|
||||
return -1;
|
||||
}
|
||||
|
@ -81,6 +81,17 @@ struct _qemuAgentDiskAddress {
|
||||
void qemuAgentDiskAddressFree(qemuAgentDiskAddressPtr addr);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuAgentDiskAddress, qemuAgentDiskAddressFree);
|
||||
|
||||
typedef struct _qemuAgentDiskInfo qemuAgentDiskInfo;
|
||||
typedef qemuAgentDiskInfo *qemuAgentDiskInfoPtr;
|
||||
struct _qemuAgentDiskInfo {
|
||||
char *name;
|
||||
bool partition;
|
||||
char **dependencies;
|
||||
qemuAgentDiskAddressPtr address;
|
||||
char *alias;
|
||||
};
|
||||
void qemuAgentDiskInfoFree(qemuAgentDiskInfoPtr info);
|
||||
|
||||
typedef struct _qemuAgentFSInfo qemuAgentFSInfo;
|
||||
typedef qemuAgentFSInfo *qemuAgentFSInfoPtr;
|
||||
struct _qemuAgentFSInfo {
|
||||
@ -187,3 +198,7 @@ int qemuAgentSSHRemoveAuthorizedKeys(qemuAgentPtr agent,
|
||||
const char *user,
|
||||
const char **keys,
|
||||
size_t nkeys);
|
||||
|
||||
int qemuAgentGetDisks(qemuAgentPtr mon,
|
||||
qemuAgentDiskInfoPtr **disks,
|
||||
bool report_unsupported);
|
||||
|
@ -1022,6 +1022,116 @@ testQemuAgentGetInterfaces(const void *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* this is a bit of a pathological response on a real hw */
|
||||
static const char testQemuAgentGetDisksResponse[] =
|
||||
"{\"return\": "
|
||||
" ["
|
||||
" {\"alias\" : \"fedora_localhost--live-home\","
|
||||
" \"dependencies\" : "
|
||||
" ["
|
||||
" \"/dev/dm-0\""
|
||||
" ],"
|
||||
" \"name\" : \"/dev/dm-3\","
|
||||
" \"partition\" : false"
|
||||
" },"
|
||||
" {\"address\" : "
|
||||
" {\"bus\" : 0,"
|
||||
" \"bus-type\" : \"unknown\","
|
||||
" \"dev\" : \"/dev/nvme0n1\","
|
||||
" \"pci-controller\" : "
|
||||
" {\"bus\" : -1,"
|
||||
" \"domain\" : -1,"
|
||||
" \"function\" : -1,"
|
||||
" \"slot\" : -1"
|
||||
" },"
|
||||
" \"serial\" : \"GIGABYTE GP-ASM2NE6100TTTD_SN202208900567\","
|
||||
" \"target\" : 0,"
|
||||
" \"unit\" : 0"
|
||||
" },"
|
||||
" \"dependencies\" : [],"
|
||||
" \"name\" : \"/dev/nvme0n1\","
|
||||
" \"partition\" : false"
|
||||
" }"
|
||||
" ]"
|
||||
"}";
|
||||
|
||||
static int
|
||||
testQemuAgentGetDisks(const void *data)
|
||||
{
|
||||
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
|
||||
qemuMonitorTestPtr test = qemuMonitorTestNewAgent(xmlopt);
|
||||
size_t i;
|
||||
int ret = -1;
|
||||
int disks_count = 0;
|
||||
qemuAgentDiskInfoPtr *disks = NULL;
|
||||
|
||||
if (!test)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (qemuMonitorTestAddItem(test, "guest-get-disks",
|
||||
testQemuAgentGetDisksResponse) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((disks_count = qemuAgentGetDisks(qemuMonitorTestGetAgent(test),
|
||||
&disks, true)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (disks_count != 2) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"expected 2 disks, got %d", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (STRNEQ(disks[0]->name, "/dev/dm-3") ||
|
||||
STRNEQ(disks[1]->name, "/dev/nvme0n1")) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"unexpected return values for disks names");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (STRNEQ(disks[0]->alias, "fedora_localhost--live-home") ||
|
||||
disks[1]->alias != NULL) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"unexpected return values for disks aliases");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (STRNEQ(disks[0]->dependencies[0], "/dev/dm-0") ||
|
||||
disks[0]->dependencies[1] != NULL ||
|
||||
disks[1]->dependencies[0] != NULL) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"unexpected return values for disks dependencies");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (disks[0]->address != NULL ||
|
||||
disks[1]->address->bus != 0 ||
|
||||
disks[1]->address->target != 0 ||
|
||||
disks[1]->address->unit != 0 ||
|
||||
STRNEQ(disks[1]->address->serial, "GIGABYTE GP-ASM2NE6100TTTD_SN202208900567") ||
|
||||
STRNEQ(disks[1]->address->bus_type, "unknown")) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"unexpected return values for disks addresses");
|
||||
goto cleanup;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
qemuMonitorTestFree(test);
|
||||
if (disks) {
|
||||
for (i = 0; i < disks_count; i++)
|
||||
qemuAgentDiskInfoFree(disks[i]);
|
||||
}
|
||||
VIR_FREE(disks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const char testQemuAgentUsersResponse[] =
|
||||
"{\"return\": "
|
||||
" ["
|
||||
@ -1394,6 +1504,7 @@ mymain(void)
|
||||
DO_TEST(OSInfo);
|
||||
DO_TEST(Timezone);
|
||||
DO_TEST(SSHKeys);
|
||||
DO_TEST(GetDisks);
|
||||
|
||||
DO_TEST(Timeout); /* Timeout should always be called last */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user