[PATCH] schemas: rng: Make secret optional in storage vol

2022-07-05 Thread Han Han
For a qcow2 storage volume with luks encryption created by qemu-img, its
dumped storage vol XML has no secret element in encryption:

...


...


That will cause a failure in rng validation. Fix that validation failure.

Signed-off-by: Han Han 
---
 src/conf/schemas/storagecommon.rng | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/src/conf/schemas/storagecommon.rng 
b/src/conf/schemas/storagecommon.rng
index 10f1bc6a15..76714c9aad 100644
--- a/src/conf/schemas/storagecommon.rng
+++ b/src/conf/schemas/storagecommon.rng
@@ -24,17 +24,19 @@
   
 
   
-  
-
-
-  
-
-  
-  
-
-  
-
-  
+  
+
+  
+  
+
+  
+
+
+  
+
+  
+
+  
 
   
 
-- 
2.36.1



[PATCH] virt-xml-validate: Fix incorrect wildcards for XML roots

2022-07-05 Thread Han Han
To match the XML roots domainCapabilities and storagepoolCapabilities,
the wildcards should be *domainCap* and *storagepoolCap*.

Fixes: 7b0e2e4a55
Signed-off-by: Han Han 
---
 tools/virt-xml-validate.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/virt-xml-validate.in b/tools/virt-xml-validate.in
index e444ef2fbc..2d5ba510ab 100644
--- a/tools/virt-xml-validate.in
+++ b/tools/virt-xml-validate.in
@@ -86,7 +86,7 @@ if [ -z "$TYPE" ]; then
  *domainbackup*)
 TYPE="domainbackup"
 ;;
- *domaincaps*)
+ *domainCap*)
 TYPE="domaincaps"
 ;;
  *domain*)
@@ -98,7 +98,7 @@ if [ -z "$TYPE" ]; then
  *network*)
 TYPE="network"
 ;;
- *storagepoolcaps*)
+ *storagepoolCap*)
 TYPE="storagepoolcaps"
 ;;
  *pool*)
-- 
2.36.1



[PATCH RFC v2 3/3] qemu_driver: use qemuMonitorQueryStats to extract halt poll time

2022-07-05 Thread Amneesh Singh
Related: https://gitlab.com/libvirt/libvirt/-/issues/276

This patch uses qemuMonitorQueryStats to query "halt_poll_success_ns"
and "halt_poll_fail_ns" for every vCPU. The respective values for each
vCPU are then added together.

Signed-off-by: Amneesh Singh 
---
 src/qemu/qemu_driver.c | 70 +-
 1 file changed, 62 insertions(+), 8 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 97c6ed95..30170d5c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18052,15 +18052,69 @@ qemuDomainGetStatsCpuCgroup(virDomainObj *dom,
 }
 
 static int
-qemuDomainGetStatsCpuHaltPollTime(virDomainObj *dom,
-  virTypedParamList *params)
+qemuDomainGetStatsCpuHaltPollTime(virQEMUDriver *driver,
+  virDomainObj *dom,
+  virTypedParamList *params,
+  unsigned int privflags)
 {
 unsigned long long haltPollSuccess = 0;
 unsigned long long haltPollFail = 0;
-pid_t pid = dom->pid;
+qemuDomainObjPrivate *priv = dom->privateData;
+bool queryStatsCap = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_STATS);
 
-if (virHostCPUGetHaltPollTime(pid, , ) < 0)
-return 0;
+if (queryStatsCap && HAVE_JOB(privflags) && virDomainObjIsActive(dom) && 
driver->privileged) {
+size_t i;
+qemuMonitorQueryStatsTargetType target = 
QEMU_MONITOR_QUERY_STATS_TARGET_VCPU;
+qemuMonitorQueryStatsProvider *provider = NULL;
+g_autoptr(GPtrArray) providers = NULL;
+g_autoptr(GPtrArray) queried_stats = NULL;
+provider = qemuMonitorQueryStatsProviderNew(
+target,
+QEMU_MONITOR_QUERY_STATS_PROVIDER_KVM,
+QEMU_MONITOR_QUERY_STATS_VCPU_NAME_HALT_POLL_SUCCESS_NS,
+QEMU_MONITOR_QUERY_STATS_VCPU_NAME_HALT_POLL_FAIL_NS,
+-1);
+
+if (!provider)
+return 0;
+
+providers = g_ptr_array_new_full(1, (GDestroyNotify) 
qemuMonitorQueryStatsProviderFree);
+g_ptr_array_add(providers, provider);
+
+qemuDomainObjEnterMonitor(driver, dom);
+queried_stats = qemuMonitorQueryStats(priv->mon, target, NULL, 
providers);
+qemuDomainObjExitMonitor(dom);
+
+if (!queried_stats)
+return 0;
+
+for (i = 0; i < queried_stats->len; i++) {
+unsigned long long curHaltPollSuccess, curHaltPollFail;
+GHashTable *cur_table = queried_stats->pdata[i];
+virJSONValue *success_obj, *fail_obj;
+const char *success_str = 
qemuMonitorQueryStatsVcpuNameTypeToString(
+QEMU_MONITOR_QUERY_STATS_VCPU_NAME_HALT_POLL_SUCCESS_NS);
+const char *fail_str = qemuMonitorQueryStatsVcpuNameTypeToString(
+QEMU_MONITOR_QUERY_STATS_VCPU_NAME_HALT_POLL_FAIL_NS);
+
+success_obj = g_hash_table_lookup(cur_table, success_str);
+fail_obj = g_hash_table_lookup(cur_table, fail_str);
+
+if (!(success_obj && fail_obj))
+return 0;
+
+ignore_value(virJSONValueGetNumberUlong(success_obj, 
));
+ignore_value(virJSONValueGetNumberUlong(fail_obj, 
));
+
+haltPollSuccess += curHaltPollSuccess;
+haltPollFail += curHaltPollFail;
+}
+} else {
+pid_t pid = dom->pid;
+
+if (virHostCPUGetHaltPollTime(pid, , ) < 
0)
+return 0;
+}
 
 if (virTypedParamListAddULLong(params, haltPollSuccess, 
"cpu.haltpoll.success.time") < 0 ||
 virTypedParamListAddULLong(params, haltPollFail, 
"cpu.haltpoll.fail.time") < 0)
@@ -18073,7 +18127,7 @@ static int
 qemuDomainGetStatsCpu(virQEMUDriver *driver,
   virDomainObj *dom,
   virTypedParamList *params,
-  unsigned int privflags G_GNUC_UNUSED)
+  unsigned int privflags)
 {
 if (qemuDomainGetStatsCpuCgroup(dom, params) < 0)
 return -1;
@@ -18081,7 +18135,7 @@ qemuDomainGetStatsCpu(virQEMUDriver *driver,
 if (qemuDomainGetStatsCpuCache(driver, dom, params) < 0)
 return -1;
 
-if (qemuDomainGetStatsCpuHaltPollTime(dom, params) < 0)
+if (qemuDomainGetStatsCpuHaltPollTime(driver, dom, params, privflags) < 0)
 return -1;
 
 return 0;
@@ -18915,7 +18969,7 @@ static virQEMUCapsFlags queryDirtyRateRequired[] = {
 
 static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
 { qemuDomainGetStatsState, VIR_DOMAIN_STATS_STATE, false, NULL },
-{ qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, false, NULL },
+{ qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, true, NULL },
 { qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true, NULL },
 { qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, true, NULL },
 { qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false, NULL },
-- 
2.36.1



[PATCH RFC v2 0/3] qemu: add an API for "query-stats" QMP command

2022-07-05 Thread Amneesh Singh
QEMU is gaining introspectable statistics which can be queried via the
"query-stats" QMP command. This patchset aims to add an API for the
same.

The returned JSON for "query-stats" is an array of objects containing
their own respective array of statistics.

Patch 1 adds the API which returns the deserialized JSON in the form of
a GPtrArray of GHashTables.

Patch 2 adds the "query-stats" to QEMU capabilities.

Patch 3 uses the API to query the halt poll success time and the halt
poll failure time.

v1 -> v2

I have been tinkering with the v1 patchset and have rewrote the v2
patches a couple of times. I believe the current patchset is still not
perfect and would appreciate some reviews.

I have another patch or two written but they do not make any significant
changes to the current patchset.

[1/3]:
  - use virBitmap instead of an array of strings for statistics.
  - add enums for the stat names and add
qemuMonitorQueryStatsNameTypeToString to switch between the
"ToString" functions based on the target type.
  - change qemuMonitorQueryStatsProviderNew to a variadic function that
takes stat enum values with the sentinel value being -1.

[2/3]:
  - No changes

[3/3]:
  - Add relevant monitor related checks to check if the domain is
active.
  - Acquire and release qemuMonitorObj lock before and after calling
qemuMonitorQueryStats respectively.
  - Add the check for privileged access.

Relevant QEMU patches can be found here:
https://lore.kernel.org/all/20220530150714.756954-1-pbonz...@redhat.com/

This patchset is part of the 2022 GSOC contributor project.

Amneesh Singh (3):
  qemu_monitor: add qemuMonitorQueryStats
  qemu_capabilities: add "query-stats" QMP command to the QEMU
capabilities
  qemu_driver: use qemuMonitorQueryStats to extract halt poll time

 src/qemu/qemu_capabilities.c |   2 +
 src/qemu/qemu_capabilities.h |   1 +
 src/qemu/qemu_driver.c   |  70 ---
 src/qemu/qemu_monitor.c  | 106 
 src/qemu/qemu_monitor.h  |  56 +++
 src/qemu/qemu_monitor_json.c | 130 +++
 src/qemu/qemu_monitor_json.h |   6 ++
 7 files changed, 363 insertions(+), 8 deletions(-)

-- 
2.36.1



[PATCH RFC v2 2/3] qemu_capabilities: add "query-stats" QMP command to the QEMU capabilities

2022-07-05 Thread Amneesh Singh
Related: https://gitlab.com/libvirt/libvirt/-/issues/276

This patch adds "query-stats" to the QEMU capabilities.

Signed-off-by: Amneesh Singh 
---
 src/qemu/qemu_capabilities.c | 2 ++
 src/qemu/qemu_capabilities.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2c3be3ec..81fc597a 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -671,6 +671,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
   "chardev.qemu-vdagent", /* QEMU_CAPS_CHARDEV_QEMU_VDAGENT */
   "display-dbus", /* QEMU_CAPS_DISPLAY_DBUS */
   "iothread.thread-pool-max", /* 
QEMU_CAPS_IOTHREAD_THREAD_POOL_MAX */
+  "query-stats", /* QEMU_CAPS_QUERY_STATS */
 );
 
 
@@ -1225,6 +1226,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = {
 { "query-dirty-rate", QEMU_CAPS_QUERY_DIRTY_RATE },
 { "sev-inject-launch-secret", QEMU_CAPS_SEV_INJECT_LAUNCH_SECRET },
 { "calc-dirty-rate", QEMU_CAPS_CALC_DIRTY_RATE },
+{ "query-stats", QEMU_CAPS_QUERY_STATS },
 };
 
 struct virQEMUCapsStringFlags virQEMUCapsMigration[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 6f35ba14..29e55b3a 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -650,6 +650,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for 
syntax-check */
 QEMU_CAPS_CHARDEV_QEMU_VDAGENT, /* -chardev qemu-vdagent */
 QEMU_CAPS_DISPLAY_DBUS, /* -display dbus */
 QEMU_CAPS_IOTHREAD_THREAD_POOL_MAX, /* -object iothread.thread-pool-max */
+QEMU_CAPS_QUERY_STATS,  /*accepts query-stats */
 
 QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
-- 
2.36.1



[PATCH RFC v2 1/3] qemu_monitor: add qemuMonitorQueryStats

2022-07-05 Thread Amneesh Singh
Related: https://gitlab.com/libvirt/libvirt/-/issues/276

This patch adds an API for the "query-stats" QMP command.

The query returns a JSON containing the statistics based on the target,
which can either be vCPU or VM, and the providers. The API deserializes
the query result into an array of GHashMaps, which can later be used to
extract all the query statistics. GHashMaps are used to avoid traversing
the entire array to find the statistics you are looking for. This would
be a singleton array if the target is a VM since the returned JSON is
also a singleton array in that case.

Signed-off-by: Amneesh Singh 
---
 src/qemu/qemu_monitor.c  | 106 
 src/qemu/qemu_monitor.h  |  56 +++
 src/qemu/qemu_monitor_json.c | 130 +++
 src/qemu/qemu_monitor_json.h |   6 ++
 4 files changed, 298 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index fda5d2f3..528aed49 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4541,3 +4541,109 @@ qemuMonitorMigrateRecover(qemuMonitor *mon,
 
 return qemuMonitorJSONMigrateRecover(mon, uri);
 }
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsTarget,
+  QEMU_MONITOR_QUERY_STATS_TARGET_LAST,
+  "vm",
+  "vcpu",
+);
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsVmName,
+  QEMU_MONITOR_QUERY_STATS_VM_NAME_LAST,
+);
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsVcpuName,
+  QEMU_MONITOR_QUERY_STATS_VCPU_NAME_LAST,
+  "halt_poll_success_ns",
+  "halt_poll_fail_ns"
+);
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsProvider,
+  QEMU_MONITOR_QUERY_STATS_PROVIDER_LAST,
+  "kvm",
+);
+
+const char *
+qemuMonitorQueryStatsNameTypeToString(qemuMonitorQueryStatsTargetType target,
+  int type)
+{
+switch (target) {
+case QEMU_MONITOR_QUERY_STATS_TARGET_VM:
+return qemuMonitorQueryStatsVmNameTypeToString(type);
+case QEMU_MONITOR_QUERY_STATS_TARGET_VCPU:
+return qemuMonitorQueryStatsVcpuNameTypeToString(type);
+
+/* unreachable */
+case QEMU_MONITOR_QUERY_STATS_TARGET_LAST:
+;
+}
+
+return NULL;
+}
+
+void
+qemuMonitorQueryStatsProviderFree(qemuMonitorQueryStatsProvider *provider)
+{
+virBitmapFree(provider->names);
+g_free(provider);
+}
+
+qemuMonitorQueryStatsProvider *
+qemuMonitorQueryStatsProviderNew(qemuMonitorQueryStatsTargetType target,
+ qemuMonitorQueryStatsProviderType 
provider_type,
+ ...)
+{
+g_autoptr(qemuMonitorQueryStatsProvider) provider = NULL;
+va_list name_list;
+int stat;
+
+provider = g_new0(qemuMonitorQueryStatsProvider, 1);
+provider->provider = provider_type;
+provider->names = NULL;
+
+va_start(name_list, provider_type);
+stat = va_arg(name_list, int);
+
+if (stat != -1) {
+size_t sz = 0;
+
+switch (target) {
+case QEMU_MONITOR_QUERY_STATS_TARGET_VM:
+sz = QEMU_MONITOR_QUERY_STATS_VM_NAME_LAST;
+break;
+case QEMU_MONITOR_QUERY_STATS_TARGET_VCPU:
+sz = QEMU_MONITOR_QUERY_STATS_VCPU_NAME_LAST;
+break;
+case QEMU_MONITOR_QUERY_STATS_TARGET_LAST:
+break;
+}
+
+provider->names = virBitmapNew(sz);
+
+while (stat != -1) {
+if (virBitmapSetBit(provider->names, stat) < 0)
+return NULL;
+stat = va_arg(name_list, int);
+}
+}
+
+va_end(name_list);
+
+return g_steal_pointer();
+}
+
+GPtrArray *
+qemuMonitorQueryStats(qemuMonitor *mon,
+  qemuMonitorQueryStatsTargetType target,
+  char **vcpus,
+  GPtrArray *providers)
+{
+VIR_DEBUG("target=%u vcpus=%p providers=%p", target, vcpus, providers);
+
+QEMU_CHECK_MONITOR_NULL(mon);
+
+if (target != QEMU_MONITOR_QUERY_STATS_TARGET_VCPU && !vcpus)
+return NULL;
+
+return qemuMonitorJSONQueryStats(mon, target, vcpus, providers);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 95267ec6..26df9c63 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1554,3 +1554,59 @@ qemuMonitorChangeMemoryRequestedSize(qemuMonitor *mon,
 int
 qemuMonitorMigrateRecover(qemuMonitor *mon,
   const char *uri);
+
+typedef enum {
+QEMU_MONITOR_QUERY_STATS_TARGET_VM,
+QEMU_MONITOR_QUERY_STATS_TARGET_VCPU,
+QEMU_MONITOR_QUERY_STATS_TARGET_LAST,
+} qemuMonitorQueryStatsTargetType;
+
+VIR_ENUM_DECL(qemuMonitorQueryStatsTarget);
+
+typedef enum {
+QEMU_MONITOR_QUERY_STATS_VM_NAME_LAST,
+} qemuMonitorQueryStatsVmNameType;
+
+VIR_ENUM_DECL(qemuMonitorQueryStatsVmName);
+
+typedef enum {
+QEMU_MONITOR_QUERY_STATS_VCPU_NAME_HALT_POLL_SUCCESS_NS,
+QEMU_MONITOR_QUERY_STATS_VCPU_NAME_HALT_POLL_FAIL_NS,
+