[libvirt PATCH 0/9] qemu: report guest disks informations

From: Marc-André Lureau <marcandre.lureau@redhat.com> Hi, The following series extends virDomainGetGuestInfo to report disk informations provided by the new QGA "guest-get-disks" command in QEMU 5.2. Please review, Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1899527 Marc-André Lureau (9): qemu_agent: rename qemuAgentDiskInfo->qemuAgentDiskAddress qemu_agent: export qemuAgentDiskAddressFree & add g_auto qemu_agent: factor out qemuAgentGetDiskAddress util: json: add virJSONValueObjectGetStringArray convenience qemu: use virJSONValueObjectGetStringArray qemu_agent: add qemuAgentGetDisks domain: add disk informations to virDomainGetGuestInfo qemu_driver: report guest disk informations virsh: add --disk informations to guestinfo command include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 17 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_agent.c | 182 +++++++++++++++++++++++-------- src/qemu/qemu_agent.h | 25 ++++- src/qemu/qemu_driver.c | 103 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 34 +----- src/util/virjson.c | 30 +++++ src/util/virjson.h | 1 + tests/qemuagenttest.c | 111 +++++++++++++++++++ tools/virsh-domain.c | 6 + 11 files changed, 430 insertions(+), 81 deletions(-) -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> To match the QGA schema name (we are introducing a qemuAgentDiskInfo struct again for different purpose). Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_agent.c | 10 +++++----- src/qemu/qemu_agent.h | 8 ++++---- src/qemu/qemu_driver.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 230253d404..beb42449ce 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1816,7 +1816,7 @@ qemuAgentSetTime(qemuAgentPtr agent, } static void -qemuAgentDiskInfoFree(qemuAgentDiskInfoPtr info) +qemuAgentDiskAddressFree(qemuAgentDiskAddressPtr info) { if (!info) return; @@ -1840,7 +1840,7 @@ qemuAgentFSInfoFree(qemuAgentFSInfoPtr info) g_free(info->fstype); for (i = 0; i < info->ndisks; i++) - qemuAgentDiskInfoFree(info->disks[i]); + qemuAgentDiskAddressFree(info->disks[i]); g_free(info->disks); g_free(info); @@ -1862,13 +1862,13 @@ qemuAgentGetFSInfoFillDisks(virJSONValuePtr jsondisks, ndisks = virJSONValueArraySize(jsondisks); if (ndisks) - fsinfo->disks = g_new0(qemuAgentDiskInfoPtr, ndisks); + fsinfo->disks = g_new0(qemuAgentDiskAddressPtr, ndisks); fsinfo->ndisks = ndisks; for (i = 0; i < fsinfo->ndisks; i++) { virJSONValuePtr jsondisk = virJSONValueArrayGet(jsondisks, i); virJSONValuePtr pci; - qemuAgentDiskInfoPtr disk; + qemuAgentDiskAddressPtr disk; const char *val; if (!jsondisk) { @@ -1879,7 +1879,7 @@ qemuAgentGetFSInfoFillDisks(virJSONValuePtr jsondisks, return -1; } - fsinfo->disks[i] = g_new0(qemuAgentDiskInfo, 1); + fsinfo->disks[i] = g_new0(qemuAgentDiskAddress, 1); disk = fsinfo->disks[i]; if ((val = virJSONValueObjectGetString(jsondisk, "bus-type"))) diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 7cbab489ec..185d09aeca 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -67,9 +67,9 @@ typedef enum { QEMU_AGENT_SHUTDOWN_LAST, } qemuAgentShutdownMode; -typedef struct _qemuAgentDiskInfo qemuAgentDiskInfo; -typedef qemuAgentDiskInfo *qemuAgentDiskInfoPtr; -struct _qemuAgentDiskInfo { +typedef struct _qemuAgentDiskAddress qemuAgentDiskAddress; +typedef qemuAgentDiskAddress *qemuAgentDiskAddressPtr; +struct _qemuAgentDiskAddress { char *serial; virPCIDeviceAddress pci_controller; char *bus_type; @@ -88,7 +88,7 @@ struct _qemuAgentFSInfo { long long total_bytes; long long used_bytes; size_t ndisks; - qemuAgentDiskInfoPtr *disks; + qemuAgentDiskAddressPtr *disks; }; void qemuAgentFSInfoFree(qemuAgentFSInfoPtr info); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b69be1bedc..a8760f82b1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18847,7 +18847,7 @@ qemuAgentFSInfoToPublic(qemuAgentFSInfoPtr agent, ret->ndevAlias = agent->ndisks; for (i = 0; i < ret->ndevAlias; i++) { - qemuAgentDiskInfoPtr agentdisk = agent->disks[i]; + qemuAgentDiskAddressPtr agentdisk = agent->disks[i]; virDomainDiskDefPtr diskDef; diskDef = virDomainDiskByAddress(vmdef, @@ -19899,7 +19899,7 @@ qemuAgentFSInfoFormatParams(qemuAgentFSInfoPtr *fsinfo, return; for (j = 0; j < fsinfo[i]->ndisks; j++) { virDomainDiskDefPtr diskdef = NULL; - qemuAgentDiskInfoPtr d = fsinfo[i]->disks[j]; + qemuAgentDiskAddressPtr d = fsinfo[i]->disks[j]; /* match the disk to the target in the vm definition */ diskdef = virDomainDiskByAddress(vmdef, &d->pci_controller, -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_agent.c | 2 +- src/qemu/qemu_agent.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index beb42449ce..ba07d6bfdf 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1815,7 +1815,7 @@ qemuAgentSetTime(qemuAgentPtr agent, return ret; } -static void +void qemuAgentDiskAddressFree(qemuAgentDiskAddressPtr info) { if (!info) diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 185d09aeca..62d68b165a 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -78,6 +78,8 @@ struct _qemuAgentDiskAddress { unsigned int unit; char *devnode; }; +void qemuAgentDiskAddressFree(qemuAgentDiskAddressPtr addr); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuAgentDiskAddress, qemuAgentDiskAddressFree); typedef struct _qemuAgentFSInfo qemuAgentFSInfo; typedef qemuAgentFSInfo *qemuAgentFSInfoPtr; -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_agent.c | 83 ++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index ba07d6bfdf..31f26eedd1 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1846,6 +1846,47 @@ qemuAgentFSInfoFree(qemuAgentFSInfoPtr info) g_free(info); } + +static qemuAgentDiskAddressPtr +qemuAgentGetDiskAddress(virJSONValuePtr json) +{ + virJSONValuePtr pci; + g_autoptr(qemuAgentDiskAddress) addr = NULL; + + addr = g_new0(qemuAgentDiskAddress, 1); + addr->bus_type = g_strdup(virJSONValueObjectGetString(json, "bus-type")); + addr->serial = g_strdup(virJSONValueObjectGetString(json, "serial")); + addr->devnode = g_strdup(virJSONValueObjectGetString(json, "dev")); + +#define GET_DISK_ADDR(jsonObject, var, name) \ + do { \ + if (virJSONValueObjectGetNumberUint(jsonObject, name, var) < 0) { \ + virReportError(VIR_ERR_INTERNAL_ERROR, \ + _("'%s' missing"), name); \ + return NULL; \ + } \ + } while (0) + + GET_DISK_ADDR(json, &addr->bus, "bus"); + GET_DISK_ADDR(json, &addr->target, "target"); + GET_DISK_ADDR(json, &addr->unit, "unit"); + + if (!(pci = virJSONValueObjectGet(json, "pci-controller"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("'pci-controller' missing")); + return NULL; + } + + GET_DISK_ADDR(pci, &addr->pci_controller.domain, "domain"); + GET_DISK_ADDR(pci, &addr->pci_controller.bus, "bus"); + GET_DISK_ADDR(pci, &addr->pci_controller.slot, "slot"); + GET_DISK_ADDR(pci, &addr->pci_controller.function, "function"); +#undef GET_DISK_ADDR + + return g_steal_pointer(&addr); +} + + static int qemuAgentGetFSInfoFillDisks(virJSONValuePtr jsondisks, qemuAgentFSInfoPtr fsinfo) @@ -1867,9 +1908,6 @@ qemuAgentGetFSInfoFillDisks(virJSONValuePtr jsondisks, for (i = 0; i < fsinfo->ndisks; i++) { virJSONValuePtr jsondisk = virJSONValueArrayGet(jsondisks, i); - virJSONValuePtr pci; - qemuAgentDiskAddressPtr disk; - const char *val; if (!jsondisk) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1879,44 +1917,9 @@ qemuAgentGetFSInfoFillDisks(virJSONValuePtr jsondisks, return -1; } - fsinfo->disks[i] = g_new0(qemuAgentDiskAddress, 1); - disk = fsinfo->disks[i]; - - if ((val = virJSONValueObjectGetString(jsondisk, "bus-type"))) - disk->bus_type = g_strdup(val); - - if ((val = virJSONValueObjectGetString(jsondisk, "serial"))) - disk->serial = g_strdup(val); - - if ((val = virJSONValueObjectGetString(jsondisk, "dev"))) - disk->devnode = g_strdup(val); - -#define GET_DISK_ADDR(jsonObject, var, name) \ - do { \ - if (virJSONValueObjectGetNumberUint(jsonObject, name, var) < 0) { \ - virReportError(VIR_ERR_INTERNAL_ERROR, \ - _("'%s' missing in guest-get-fsinfo " \ - "'disk' data"), name); \ - return -1; \ - } \ - } while (0) - - GET_DISK_ADDR(jsondisk, &disk->bus, "bus"); - GET_DISK_ADDR(jsondisk, &disk->target, "target"); - GET_DISK_ADDR(jsondisk, &disk->unit, "unit"); - - if (!(pci = virJSONValueObjectGet(jsondisk, "pci-controller"))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("'pci-controller' missing in guest-get-fsinfo " - "'disk' data")); + fsinfo->disks[i] = qemuAgentGetDiskAddress(jsondisk); + if (!fsinfo->disks[i]) return -1; - } - - GET_DISK_ADDR(pci, &disk->pci_controller.domain, "domain"); - GET_DISK_ADDR(pci, &disk->pci_controller.bus, "bus"); - GET_DISK_ADDR(pci, &disk->pci_controller.slot, "slot"); - GET_DISK_ADDR(pci, &disk->pci_controller.function, "function"); -#undef GET_DISK_ADDR } return 0; -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virjson.c | 30 ++++++++++++++++++++++++++++++ src/util/virjson.h | 1 + 3 files changed, 32 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 79a23f34cb..0f8447cfbb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2408,6 +2408,7 @@ virJSONValueObjectGetNumberUint; virJSONValueObjectGetNumberUlong; virJSONValueObjectGetObject; virJSONValueObjectGetString; +virJSONValueObjectGetStringArray; virJSONValueObjectGetValue; virJSONValueObjectHasKey; virJSONValueObjectIsNull; diff --git a/src/util/virjson.c b/src/util/virjson.c index 3fa9a9ca24..05c4804410 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -1463,6 +1463,36 @@ virJSONValueObjectIsNull(virJSONValuePtr object, return virJSONValueIsNull(val); } +char ** +virJSONValueObjectGetStringArray(virJSONValuePtr object, const char *key) +{ + g_auto(GStrv) ret = NULL; + virJSONValuePtr data; + size_t n; + size_t i; + + data = virJSONValueObjectGetArray(object, key); + if (!data) + return NULL; + + n = virJSONValueArraySize(data); + ret = g_new0(char *, n + 1); + for (i = 0; i < n; i++) { + virJSONValuePtr child = virJSONValueArrayGet(data, i); + const char *tmp; + + if (!(tmp = virJSONValueGetString(child))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("%s array element does not contain a string"), + key); + return NULL; + } + + ret[i] = g_strdup(tmp); + } + + return g_steal_pointer(&ret); +} /** * virJSONValueObjectForeachKeyValue: diff --git a/src/util/virjson.h b/src/util/virjson.h index 588c977650..4dc7ed1a2d 100644 --- a/src/util/virjson.h +++ b/src/util/virjson.h @@ -117,6 +117,7 @@ virJSONValuePtr virJSONValueObjectStealObject(virJSONValuePtr object, const char *key); const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key); +char **virJSONValueObjectGetStringArray(virJSONValuePtr object, const char *key); const char *virJSONValueObjectGetStringOrNumber(virJSONValuePtr object, const char *key); int virJSONValueObjectGetNumberInt(virJSONValuePtr object, const char *key, int *value); int virJSONValueObjectGetNumberUint(virJSONValuePtr object, const char *key, unsigned int *value); -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> There might be more potential users around, I haven't looked thoroughly. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_monitor_json.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 723bdb4426..3588a0c426 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7533,10 +7533,7 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, int ret = -1; virJSONValuePtr cmd; virJSONValuePtr reply = NULL; - virJSONValuePtr data; - char **list = NULL; - size_t n = 0; - size_t i; + g_auto(GStrv) list = NULL; *array = NULL; @@ -7554,32 +7551,13 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) goto cleanup; - data = virJSONValueObjectGetArray(reply, "return"); - n = virJSONValueArraySize(data); - - /* null-terminated list */ - list = g_new0(char *, n + 1); - - for (i = 0; i < n; i++) { - virJSONValuePtr child = virJSONValueArrayGet(data, i); - const char *tmp; - - if (!(tmp = virJSONValueGetString(child))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("%s array element does not contain data"), - qmpCmd); - goto cleanup; - } - - list[i] = g_strdup(tmp); - } - - ret = n; - *array = list; - list = NULL; + list = virJSONValueObjectGetStringArray(reply, "return"); + if (!list) + goto cleanup; + ret = g_strv_length(list); + *array = g_steal_pointer(&list); cleanup: - g_strfreev(list); virJSONValueFree(cmd); virJSONValueFree(reply); return ret; -- 2.29.0

On 11/20/20 7:09 PM, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
There might be more potential users around, I haven't looked thoroughly.
Quick git grep showed two more: qemuAgentSSHGetAuthorizedKeys() and qemuMonitorJSONGetStringListProperty(). But that can be done in a separate patch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_monitor_json.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 723bdb4426..3588a0c426 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7533,10 +7533,7 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, int ret = -1; virJSONValuePtr cmd; virJSONValuePtr reply = NULL; - virJSONValuePtr data; - char **list = NULL; - size_t n = 0; - size_t i; + g_auto(GStrv) list = NULL;
*array = NULL;
@@ -7554,32 +7551,13 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) goto cleanup;
- data = virJSONValueObjectGetArray(reply, "return"); - n = virJSONValueArraySize(data); - - /* null-terminated list */ - list = g_new0(char *, n + 1); - - for (i = 0; i < n; i++) { - virJSONValuePtr child = virJSONValueArrayGet(data, i); - const char *tmp; - - if (!(tmp = virJSONValueGetString(child))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("%s array element does not contain data"), - qmpCmd); - goto cleanup; - } - - list[i] = g_strdup(tmp); - } - - ret = n; - *array = list; - list = NULL; + list = virJSONValueObjectGetStringArray(reply, "return");
We can ditch the @list variable and assign to *array directly.
+ if (!list) + goto cleanup; + ret = g_strv_length(list); + *array = g_steal_pointer(&list);
cleanup: - g_strfreev(list); virJSONValueFree(cmd); virJSONValueFree(reply); return ret;
How about this squashed in: diff --git c/src/qemu/qemu_monitor_json.c i/src/qemu/qemu_monitor_json.c index 3588a0c426..e7aa6b6ffd 100644 --- c/src/qemu/qemu_monitor_json.c +++ i/src/qemu/qemu_monitor_json.c @@ -7533,7 +7533,6 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, int ret = -1; virJSONValuePtr cmd; virJSONValuePtr reply = NULL; - g_auto(GStrv) list = NULL; *array = NULL; @@ -7551,11 +7550,10 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) goto cleanup; - list = virJSONValueObjectGetStringArray(reply, "return"); - if (!list) + if (!(*array = virJSONValueObjectGetStringArray(reply, "return"))) goto cleanup; - ret = g_strv_length(list); - *array = g_steal_pointer(&list); + + ret = g_strv_length(*array); cleanup: virJSONValueFree(cmd); Michal

On Mon, Nov 30, 2020 at 11:16 PM Michal Privoznik <mprivozn@redhat.com> wrote:
On 11/20/20 7:09 PM, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
There might be more potential users around, I haven't looked thoroughly.
Quick git grep showed two more: qemuAgentSSHGetAuthorizedKeys() and qemuMonitorJSONGetStringListProperty(). But that can be done in a separate patch.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_monitor_json.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 723bdb4426..3588a0c426 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -7533,10 +7533,7 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, int ret = -1; virJSONValuePtr cmd; virJSONValuePtr reply = NULL; - virJSONValuePtr data; - char **list = NULL; - size_t n = 0; - size_t i; + g_auto(GStrv) list = NULL;
*array = NULL;
@@ -7554,32 +7551,13 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) goto cleanup;
- data = virJSONValueObjectGetArray(reply, "return"); - n = virJSONValueArraySize(data); - - /* null-terminated list */ - list = g_new0(char *, n + 1); - - for (i = 0; i < n; i++) { - virJSONValuePtr child = virJSONValueArrayGet(data, i); - const char *tmp; - - if (!(tmp = virJSONValueGetString(child))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("%s array element does not contain data"), - qmpCmd); - goto cleanup; - } - - list[i] = g_strdup(tmp); - } - - ret = n; - *array = list; - list = NULL; + list = virJSONValueObjectGetStringArray(reply, "return");
We can ditch the @list variable and assign to *array directly.
+ if (!list) + goto cleanup; + ret = g_strv_length(list); + *array = g_steal_pointer(&list);
cleanup: - g_strfreev(list); virJSONValueFree(cmd); virJSONValueFree(reply); return ret;
How about this squashed in:
diff --git c/src/qemu/qemu_monitor_json.c i/src/qemu/qemu_monitor_json.c index 3588a0c426..e7aa6b6ffd 100644 --- c/src/qemu/qemu_monitor_json.c +++ i/src/qemu/qemu_monitor_json.c @@ -7533,7 +7533,6 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, int ret = -1; virJSONValuePtr cmd; virJSONValuePtr reply = NULL; - g_auto(GStrv) list = NULL;
*array = NULL;
@@ -7551,11 +7550,10 @@ qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd, if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) goto cleanup;
- list = virJSONValueObjectGetStringArray(reply, "return"); - if (!list) + if (!(*array = virJSONValueObjectGetStringArray(reply, "return"))) goto cleanup; - ret = g_strv_length(list); - *array = g_steal_pointer(&list); + + ret = g_strv_length(*array);
cleanup: virJSONValueFree(cmd);
Looks good to me, thanks

From: Marc-André Lureau <marcandre.lureau@redhat.com> 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> --- src/qemu/qemu_agent.c | 91 ++++++++++++++++++++++++++++++++++ src/qemu/qemu_agent.h | 15 ++++++ tests/qemuagenttest.c | 111 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 31f26eedd1..8698e5cfaf 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -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) { @@ -2640,3 +2655,79 @@ 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; + + if (!(cmd = qemuAgentMakeCommand("guest-get-disks", NULL))) + return -1; + + if (qemuAgentCommandFull(agent, cmd, &reply, agent->timeout, + report_unsupported) < 0) + return -1; + + 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; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 62d68b165a..74f1410760 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -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); diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c index 47ff92733a..bf295496e1 100644 --- a/tests/qemuagenttest.c +++ b/tests/qemuagenttest.c @@ -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 */ -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index d81157ccaf..60fa8c6719 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5070,6 +5070,7 @@ typedef enum { VIR_DOMAIN_GUEST_INFO_TIMEZONE = (1 << 2), /* return timezone information */ VIR_DOMAIN_GUEST_INFO_HOSTNAME = (1 << 3), /* return hostname information */ VIR_DOMAIN_GUEST_INFO_FILESYSTEM = (1 << 4), /* return filesystem information */ + VIR_DOMAIN_GUEST_INFO_DISKS = (1 << 5), /* return disks information */ } virDomainGuestInfoTypes; int virDomainGetGuestInfo(virDomainPtr domain, diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 63d4954e68..c837ecbcc3 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -12341,6 +12341,23 @@ virDomainSetVcpu(virDomainPtr domain, * "fs.<num>.disk.<num>.serial" - the serial number of the disk * "fs.<num>.disk.<num>.device" - the device node of the disk * + * VIR_DOMAIN_GUEST_INFO_DISKS: + * Returns information about the disks within the domain. The typed + * parameter keys are in this format: + * + * "disks.count" - the number of disks defined on this domain + * as an unsigned int + * "disks.<num>.name" - device node (Linux) or device UNC (Windows) + * "disks.<num>.partition" - whether this is a partition or disk + * "disks.<num>.dependencies.count" - the number of device dependencies + * e.g. for LVs of the LVM this will + * hold the list of PVs, for LUKS encrypted volume this will + * contain the disk where the volume is placed. (Linux) + * "disks.<num>.dependencies.<num>.name" - a dependency + * "disks.<num>.alias" - the device alias of the disk (e.g. sda) + * "disks.<num>.guest_alias" - optional alias assigned to the disk, on Linux + * this is a name assigned by device mapper + * * VIR_DOMAIN_GUEST_INFO_HOSTNAME: * Returns information about the hostname of the domain. The typed * parameter keys are in this format: -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- src/qemu/qemu_driver.c | 99 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a8760f82b1..8d3e09da69 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19820,7 +19820,8 @@ static const unsigned int qemuDomainGetGuestInfoSupportedTypes = VIR_DOMAIN_GUEST_INFO_OS | VIR_DOMAIN_GUEST_INFO_TIMEZONE | VIR_DOMAIN_GUEST_INFO_HOSTNAME | - VIR_DOMAIN_GUEST_INFO_FILESYSTEM; + VIR_DOMAIN_GUEST_INFO_FILESYSTEM | + VIR_DOMAIN_GUEST_INFO_DISKS; static int qemuDomainGetGuestInfoCheckSupport(unsigned int types, @@ -19843,6 +19844,80 @@ qemuDomainGetGuestInfoCheckSupport(unsigned int types, return 0; } + +static void +qemuAgentDiskInfoFormatParams(qemuAgentDiskInfoPtr *info, + int ndisks, + virDomainDefPtr vmdef, + virTypedParameterPtr *params, + int *nparams, int *maxparams) +{ + size_t i, j, ndeps; + + if (virTypedParamsAddUInt(params, nparams, maxparams, + "disks.count", ndisks) < 0) + return; + + for (i = 0; i < ndisks; i++) { + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "disks.%zu.name", i); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, info[i]->name) < 0) + return; + + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "disks.%zu.partition", i); + if (virTypedParamsAddBoolean(params, nparams, maxparams, + param_name, info[i]->partition) < 0) + return; + + ndeps = g_strv_length(info[i]->dependencies); + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "disks.%zu.dependencies.count", i); + if (ndeps && + virTypedParamsAddUInt(params, nparams, maxparams, + param_name, ndeps) < 0) + return; + for (j = 0; j < ndeps; j++) { + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "disks.%zu.dependencies.%zu.name", i, j); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, info[i]->dependencies[j]) < 0) + return; + } + + if (info[i]->address) { + virDomainDiskDefPtr diskdef = NULL; + + /* match the disk to the target in the vm definition */ + diskdef = virDomainDiskByAddress(vmdef, + &info[i]->address->pci_controller, + info[i]->address->bus, + info[i]->address->target, + info[i]->address->unit); + if (diskdef) { + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "disks.%zu.alias", i); + if (diskdef->dst && + virTypedParamsAddString(params, nparams, maxparams, + param_name, diskdef->dst) < 0) + return; + } + } + + if (info[i]->alias) { + g_snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "disks.%zu.guest_alias", i); + if (virTypedParamsAddString(params, nparams, maxparams, + param_name, info[i]->alias) < 0) + return; + } + } +} + + static void qemuAgentFSInfoFormatParams(qemuAgentFSInfoPtr *fsinfo, int nfs, @@ -19951,6 +20026,8 @@ qemuDomainGetGuestInfo(virDomainPtr dom, int rc; size_t nfs = 0; qemuAgentFSInfoPtr *agentfsinfo = NULL; + size_t ndisks = 0; + qemuAgentDiskInfoPtr *agentdiskinfo = NULL; size_t i; virCheckFlags(0, -1); @@ -20007,6 +20084,15 @@ qemuDomainGetGuestInfo(virDomainPtr dom, } } + if (supportedTypes & VIR_DOMAIN_GUEST_INFO_DISKS) { + rc = qemuAgentGetDisks(agent, &agentdiskinfo, report_unsupported); + if (rc == -1) { + goto exitagent; + } else if (rc >= 0) { + ndisks = rc; + } + } + ret = 0; exitagent: @@ -20015,7 +20101,7 @@ qemuDomainGetGuestInfo(virDomainPtr dom, endagentjob: qemuDomainObjEndAgentJob(vm); - if (nfs > 0) { + if (nfs > 0 || ndisks > 0) { if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) goto cleanup; @@ -20024,7 +20110,11 @@ qemuDomainGetGuestInfo(virDomainPtr dom, /* we need to convert the agent fsinfo struct to parameters and match * it to the vm disk target */ - qemuAgentFSInfoFormatParams(agentfsinfo, nfs, vm->def, params, nparams, &maxparams); + if (nfs) + qemuAgentFSInfoFormatParams(agentfsinfo, nfs, vm->def, params, nparams, &maxparams); + + if (ndisks > 0) + qemuAgentDiskInfoFormatParams(agentdiskinfo, ndisks, vm->def, params, nparams, &maxparams); endjob: qemuDomainObjEndJob(driver, vm); @@ -20034,6 +20124,9 @@ qemuDomainGetGuestInfo(virDomainPtr dom, for (i = 0; i < nfs; i++) qemuAgentFSInfoFree(agentfsinfo[i]); g_free(agentfsinfo); + for (i = 0; i < ndisks; i++) + qemuAgentDiskInfoFree(agentdiskinfo[i]); + g_free(agentdiskinfo); virDomainObjEndAPI(&vm); return ret; -- 2.29.0

From: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- tools/virsh-domain.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index c999458d72..070b8d21fd 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -14219,6 +14219,10 @@ static const vshCmdOptDef opts_guestinfo[] = { .type = VSH_OT_BOOL, .help = N_("report filesystem information"), }, + {.name = "disks", + .type = VSH_OT_BOOL, + .help = N_("report disks information"), + }, {.name = NULL} }; @@ -14242,6 +14246,8 @@ cmdGuestInfo(vshControl *ctl, const vshCmd *cmd) types |= VIR_DOMAIN_GUEST_INFO_HOSTNAME; if (vshCommandOptBool(cmd, "filesystem")) types |= VIR_DOMAIN_GUEST_INFO_FILESYSTEM; + if (vshCommandOptBool(cmd, "disks")) + types |= VIR_DOMAIN_GUEST_INFO_DISKS; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; -- 2.29.0

On 11/20/20 7:09 PM, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- tools/virsh-domain.c | 6 ++++++ 1 file changed, 6 insertions(+)
Missing manpage addition. How about: diff --git i/docs/manpages/virsh.rst w/docs/manpages/virsh.rst index 86deaa486d..9ef6b68422 100644 --- i/docs/manpages/virsh.rst +++ w/docs/manpages/virsh.rst @@ -2679,6 +2679,7 @@ guestinfo :: guestinfo domain [--user] [--os] [--timezone] [--hostname] [--filesystem] + [--disks] Print information about the guest from the point of view of the guest agent. Note that this command requires a guest agent to be configured and running in @@ -2689,7 +2690,7 @@ are supported by the guest agent. You can limit the types of information that are returned by specifying one or more flags. If a requested information type is not supported, the processes will provide an exit code of 1. Available information types flags are *--user*, *--os*, -*--timezone*, *--hostname*, and *--filesystem*. +*--timezone*, *--hostname*, *--filesystem* and *--disks*. Note that depending on the hypervisor type and the version of the guest agent running within the domain, not all of the following information may be @@ -2746,6 +2747,16 @@ returned: * ``fs.<num>.disk.<num>.serial`` - the serial number of disk <num> * ``fs.<num>.disk.<num>.device`` - the device node of disk <num> +*--disks* returns: + +* ``disks.count`` - the number of disks defined on this domain +* ``disks.<num>.name`` - device node (Linux) or device UNC (Windows) +* ``disks.<num>.partition`` - whether this is a partition or disk +* ``disks.<num>.dependencies.count`` - the number of device dependencies +* ``disks.<num>.dependencies.<num>.name`` - a dependency name +* ``disks.<num>.alias`` - the device alias of the disk (e.g. sda) +* ``disks.<num>.guest_alias`` - optional alias assigned to the disk + guestvcpus ---------- Michal

Hi On Mon, Nov 30, 2020 at 11:16 PM Michal Privoznik <mprivozn@redhat.com> wrote:
On 11/20/20 7:09 PM, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- tools/virsh-domain.c | 6 ++++++ 1 file changed, 6 insertions(+)
Missing manpage addition. How about:
diff --git i/docs/manpages/virsh.rst w/docs/manpages/virsh.rst index 86deaa486d..9ef6b68422 100644 --- i/docs/manpages/virsh.rst +++ w/docs/manpages/virsh.rst @@ -2679,6 +2679,7 @@ guestinfo ::
guestinfo domain [--user] [--os] [--timezone] [--hostname] [--filesystem] + [--disks]
Print information about the guest from the point of view of the guest agent. Note that this command requires a guest agent to be configured and running in @@ -2689,7 +2690,7 @@ are supported by the guest agent. You can limit the types of information that are returned by specifying one or more flags. If a requested information type is not supported, the processes will provide an exit code of 1. Available information types flags are *--user*, *--os*, -*--timezone*, *--hostname*, and *--filesystem*. +*--timezone*, *--hostname*, *--filesystem* and *--disks*.
Note that depending on the hypervisor type and the version of the guest agent running within the domain, not all of the following information may be @@ -2746,6 +2747,16 @@ returned: * ``fs.<num>.disk.<num>.serial`` - the serial number of disk <num> * ``fs.<num>.disk.<num>.device`` - the device node of disk <num>
+*--disks* returns: + +* ``disks.count`` - the number of disks defined on this domain +* ``disks.<num>.name`` - device node (Linux) or device UNC (Windows) +* ``disks.<num>.partition`` - whether this is a partition or disk +* ``disks.<num>.dependencies.count`` - the number of device dependencies +* ``disks.<num>.dependencies.<num>.name`` - a dependency name +* ``disks.<num>.alias`` - the device alias of the disk (e.g. sda) +* ``disks.<num>.guest_alias`` - optional alias assigned to the disk +
guestvcpus ----------
Looks good, thanks

On Fri, Nov 20, 2020 at 10:10 PM <marcandre.lureau@redhat.com> wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Hi,
The following series extends virDomainGetGuestInfo to report disk informations provided by the new QGA "guest-get-disks" command in QEMU 5.2.
Please review,
ping
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1899527
Marc-André Lureau (9): qemu_agent: rename qemuAgentDiskInfo->qemuAgentDiskAddress qemu_agent: export qemuAgentDiskAddressFree & add g_auto qemu_agent: factor out qemuAgentGetDiskAddress util: json: add virJSONValueObjectGetStringArray convenience qemu: use virJSONValueObjectGetStringArray qemu_agent: add qemuAgentGetDisks domain: add disk informations to virDomainGetGuestInfo qemu_driver: report guest disk informations virsh: add --disk informations to guestinfo command
include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 17 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_agent.c | 182 +++++++++++++++++++++++-------- src/qemu/qemu_agent.h | 25 ++++- src/qemu/qemu_driver.c | 103 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 34 +----- src/util/virjson.c | 30 +++++ src/util/virjson.h | 1 + tests/qemuagenttest.c | 111 +++++++++++++++++++ tools/virsh-domain.c | 6 + 11 files changed, 430 insertions(+), 81 deletions(-)
-- 2.29.0
-- Marc-André Lureau

On 11/20/20 7:09 PM, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Hi,
The following series extends virDomainGetGuestInfo to report disk informations provided by the new QGA "guest-get-disks" command in QEMU 5.2.
Please review,
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1899527
Marc-André Lureau (9): qemu_agent: rename qemuAgentDiskInfo->qemuAgentDiskAddress qemu_agent: export qemuAgentDiskAddressFree & add g_auto qemu_agent: factor out qemuAgentGetDiskAddress util: json: add virJSONValueObjectGetStringArray convenience qemu: use virJSONValueObjectGetStringArray qemu_agent: add qemuAgentGetDisks domain: add disk informations to virDomainGetGuestInfo qemu_driver: report guest disk informations virsh: add --disk informations to guestinfo command
include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 17 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_agent.c | 182 +++++++++++++++++++++++-------- src/qemu/qemu_agent.h | 25 ++++- src/qemu/qemu_driver.c | 103 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 34 +----- src/util/virjson.c | 30 +++++ src/util/virjson.h | 1 + tests/qemuagenttest.c | 111 +++++++++++++++++++ tools/virsh-domain.c | 6 + 11 files changed, 430 insertions(+), 81 deletions(-)
Patches look good. A huge sorry for letting these slip the release. To make it up to you, I'm proposing couple of adjustments and if you agree I will squash in proposed diffs before pushing - so that you don't have to send v2. Tentative: Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal

Hi On Mon, Nov 30, 2020 at 11:16 PM Michal Privoznik <mprivozn@redhat.com> wrote:
On 11/20/20 7:09 PM, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Hi,
The following series extends virDomainGetGuestInfo to report disk informations provided by the new QGA "guest-get-disks" command in QEMU 5.2.
Please review,
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1899527
Marc-André Lureau (9): qemu_agent: rename qemuAgentDiskInfo->qemuAgentDiskAddress qemu_agent: export qemuAgentDiskAddressFree & add g_auto qemu_agent: factor out qemuAgentGetDiskAddress util: json: add virJSONValueObjectGetStringArray convenience qemu: use virJSONValueObjectGetStringArray qemu_agent: add qemuAgentGetDisks domain: add disk informations to virDomainGetGuestInfo qemu_driver: report guest disk informations virsh: add --disk informations to guestinfo command
include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 17 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_agent.c | 182 +++++++++++++++++++++++-------- src/qemu/qemu_agent.h | 25 ++++- src/qemu/qemu_driver.c | 103 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 34 +----- src/util/virjson.c | 30 +++++ src/util/virjson.h | 1 + tests/qemuagenttest.c | 111 +++++++++++++++++++ tools/virsh-domain.c | 6 + 11 files changed, 430 insertions(+), 81 deletions(-)
Patches look good. A huge sorry for letting these slip the release. To make it up to you, I'm proposing couple of adjustments and if you agree I will squash in proposed diffs before pushing - so that you don't have to send v2.
Fine to me,
Tentative: Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
thanks!

On Sat, Nov 21, 2020 at 2:11 AM <marcandre.lureau@redhat.com> wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Hi,
The following series extends virDomainGetGuestInfo to report disk informations provided by the new QGA "guest-get-disks" command in QEMU 5.2.
Please review,
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1899527
Marc-André Lureau (9): qemu_agent: rename qemuAgentDiskInfo->qemuAgentDiskAddress qemu_agent: export qemuAgentDiskAddressFree & add g_auto qemu_agent: factor out qemuAgentGetDiskAddress util: json: add virJSONValueObjectGetStringArray convenience qemu: use virJSONValueObjectGetStringArray qemu_agent: add qemuAgentGetDisks domain: add disk informations to virDomainGetGuestInfo qemu_driver: report guest disk informations virsh: add --disk informations to guestinfo command
include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 17 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_agent.c | 182 +++++++++++++++++++++++-------- src/qemu/qemu_agent.h | 25 ++++- src/qemu/qemu_driver.c | 103 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 34 +----- src/util/virjson.c | 30 +++++ src/util/virjson.h | 1 + tests/qemuagenttest.c | 111 +++++++++++++++++++ tools/virsh-domain.c | 6 + 11 files changed, 430 insertions(+), 81 deletions(-)
-- 2.29.0
Works for me on qemu-5.2.0-0.7.rc2.fc34.x86_64: For the guest with qemu-guest-agent-5.2.0-0.7.rc2.fc34.x86_64: ➜ ~ virsh guestinfo pc --disks disks.count : 2 disks.0.name : /dev/vda1 disks.0.partition : yes disks.0.dependencies.count: 1 disks.0.dependencies.0.name: /dev/vda disks.1.name : /dev/vda disks.1.partition : no disks.1.alias : vda
For the guest with qemu-guest-agent-4.1.1-1.fc31.x86_64: ➜ ~ virsh guestinfo new --disks error: internal error: unable to execute QEMU agent command 'guest-get-disks': The command guest-get-disks has not been found -- Tested-by: Han Han <hhan@redhat.com>
participants (5)
-
Han Han
-
Marc-André Lureau
-
Marc-André Lureau
-
marcandre.lureau@redhat.com
-
Michal Privoznik