return qemuMonitorJSONGetMigrationBlockers(mon, blockers);
}
+
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsTarget,
+ QEMU_MONITOR_QUERY_STATS_TARGET_LAST,
+ "vm",
+ "vcpu",
+);
+
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsName,
+ QEMU_MONITOR_QUERY_STATS_NAME_LAST,
+ "halt_poll_success_ns",
+ "halt_poll_fail_ns",
+);
+
+
+VIR_ENUM_IMPL(qemuMonitorQueryStatsProvider,
+ QEMU_MONITOR_QUERY_STATS_PROVIDER_LAST,
+ "kvm",
+);
+
+
+void
+qemuMonitorQueryStatsProviderFree(qemuMonitorQueryStatsProvider *provider)
+{
+ virBitmapFree(provider->names);
+ g_free(provider);
+}
+
+
+qemuMonitorQueryStatsProvider *
+qemuMonitorQueryStatsProviderNew(qemuMonitorQueryStatsProviderType provider_type,
+ ...)
+{
+ qemuMonitorQueryStatsProvider *provider = g_new0(qemuMonitorQueryStatsProvider, 1);
+ qemuMonitorQueryStatsNameType stat;
+ va_list name_list;
+
+ /*
+ * This can be lowered later in case of the enum getting quite large, hence
+ * the virBitmapSetExpand below which also incidently makes this function
+ * non-fallible.
+ */
+ provider->names = virBitmapNew(QEMU_MONITOR_QUERY_STATS_NAME_LAST);
+ provider->type = provider_type;
+
+ va_start(name_list, provider_type);
+
+ while ((stat = va_arg(name_list, qemuMonitorQueryStatsNameType)) !=
+ QEMU_MONITOR_QUERY_STATS_NAME_LAST)
+ virBitmapSetBitExpand(provider->names, stat);
+
+ va_end(name_list);
+
+ return provider;
+}
+
+
+virJSONValue *
+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);
+}
+
+
+/**
+ * qemuMonitorExtractQueryStats:
+ * @info: One of the array members returned by qemuMonitorQueryStat
+ *
+ * Converts all the statistics into a GHashTable similar to virQEMU
+ * except only object with the key "value" is stored as the value i
+ *
+ * Returns NULL on failure.
+ */
+GHashTable *
+qemuMonitorExtractQueryStats(virJSONValue *info)
+{
+ g_autoptr(GHashTable) hash_table = NULL;
+ virJSONValue *stats = NULL;
+ size_t i;
+
+ if (!virJSONValueIsObject(info))
+ return NULL;
+
+ stats = virJSONValueObjectGetArray(info, "stats");
+ if (!stats)
+ return NULL;
+
+ hash_table = virHashNew(virJSONValueHashFree);
+
+ for (i = 0; i < virJSONValueArraySize(stats); i++) {
+ virJSONValue *stat = virJSONValueArrayGet(stats, i);
+ virJSONValue *value = NULL;
+ const char *name = NULL;
+
+ if (!virJSONValueIsObject(stat))
+ continue;
+
+ name = virJSONValueObjectGetString(stat, "name");
+ if (!name)
+ continue;
+
+ if (virJSONValueObjectRemoveKey(stat, "value", &value) < 0)
+ continue;
+
+ virHashAddEntry(hash_table, name, value);
+ }
+
+ return g_steal_pointer(&hash_table);
+}
int
qemuMonitorGetMigrationBlockers(qemuMonitor *mon,
char ***blockers);
+
+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_NAME_HALT_POLL_SUCCESS_NS,
+ QEMU_MONITOR_QUERY_STATS_NAME_HALT_POLL_FAIL_NS,
+ QEMU_MONITOR_QUERY_STATS_NAME_LAST,
+} qemuMonitorQueryStatsNameType;
+
+VIR_ENUM_DECL(qemuMonitorQueryStatsName);
+
+typedef enum {
+ QEMU_MONITOR_QUERY_STATS_PROVIDER_KVM,
+ QEMU_MONITOR_QUERY_STATS_PROVIDER_LAST,
+} qemuMonitorQueryStatsProviderType;
+
+VIR_ENUM_DECL(qemuMonitorQueryStatsProvider);
+
+typedef struct _qemuMonitorQueryStatsProvider qemuMonitorQueryStatsProvider;
+struct _qemuMonitorQueryStatsProvider {
+ qemuMonitorQueryStatsProviderType type;
+ virBitmap *names;
+};
+
+void
+qemuMonitorQueryStatsProviderFree(qemuMonitorQueryStatsProvider *provider);
+
+qemuMonitorQueryStatsProvider *
+qemuMonitorQueryStatsProviderNew(qemuMonitorQueryStatsProviderType provider_type,
+ ...);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorQueryStatsProvider,
+ qemuMonitorQueryStatsProviderFree);
+
+virJSONValue *
+qemuMonitorQueryStats(qemuMonitor *mon,
+ qemuMonitorQueryStatsTargetType target,
+ char **vcpus,
+ GPtrArray *providers);
+
+GHashTable *
+qemuMonitorExtractQueryStats(virJSONValue *info);
return qemuMonitorJSONCheckError(cmd, reply);
}
+
+
+/**
+ * qemuMonitorJSONQueryStats:
+ * @mon: monitor object
+ * @target: the target type for the query
+ * @vcpus: a list of vCPU QOM paths for filtering the statistics
+ * @providers: an array of providers to filter statistics
+ *
+ * @vcpus is a NULL terminated array of strings. @providers is a GPtrArray
+ * for qemuMonitorQueryStatsProvider.
+ * @vcpus and @providers are optional and can be NULL.
+ *
+ * Queries for the @target based statistics.
+ * Returns NULL on failure.
+ */
+virJSONValue *
+qemuMonitorJSONQueryStats(qemuMonitor *mon,
+ qemuMonitorQueryStatsTargetType target,
+ char **vcpus,
+ GPtrArray *providers)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+ g_autoptr(virJSONValue) vcpu_list = NULL;
+ g_autoptr(virJSONValue) provider_list = NULL;
+
+ size_t i;
+
+ if (providers) {
+ provider_list = virJSONValueNewArray();
+
+ for (i = 0; i < providers->len; i++) {
+ g_autoptr(virJSONValue) provider_obj = virJSONValueNewObject();
+ qemuMonitorQueryStatsProvider *provider = providers->pdata[i];
+ const char *type_str = qemuMonitorQueryStatsProviderTypeToString(provider->type);
+ virBitmap *names = provider->names;
+ int rc;
+
+ rc = virJSONValueObjectAppendString(provider_obj, "provider", type_str);
+
+ if (rc < 0)
+ return NULL;
+
+ if (!virBitmapIsAllClear(names)) {
+ g_autoptr(virJSONValue) provider_names = virJSONValueNewArray();
+ ssize_t curBit = -1;
+
+ while ((curBit = virBitmapNextSetBit(names, curBit)) != -1) {
+ const char *name = qemuMonitorQueryStatsNameTypeToString(curBit);
+
+ if (virJSONValueArrayAppendString(provider_names, name) < 0)
+ return NULL;
+ }
+
+ rc = virJSONValueObjectAppend(provider_obj, "names", &provider_names);
+
+ if (rc < 0)
+ return NULL;
+ }
+
+ if (virJSONValueArrayAppend(provider_list, &provider_obj) < 0)
+ return NULL;
+ }
+ }
+
+ if (vcpus) {
+ vcpu_list = virJSONValueNewArray();
+
+ for (i = 0; vcpus[i]; i++)
+ if (virJSONValueArrayAppendString(vcpu_list, vcpus[i]) < 0)
+ return NULL;
+ }
+
+ cmd = qemuMonitorJSONMakeCommand("query-stats",
+ "s:target", qemuMonitorQueryStatsTargetTypeToString(target),
+ "A:vcpus", &vcpu_list,
+ "A:providers", &provider_list,
+ NULL);
+
+ if (!cmd)
+ return NULL;
+
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ return NULL;
+
+ if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
+ return NULL;
+
+ return virJSONValueObjectStealArray(reply, "return");
+}
int
qemuMonitorJSONMigrateRecover(qemuMonitor *mon,
const char *uri);
+
+virJSONValue *
+qemuMonitorJSONQueryStats(qemuMonitor *mon,
+ qemuMonitorQueryStatsTargetType target,
+ char **vcpus,
+ GPtrArray *providers);