The new function virConnectGetCPUModelNames allows to retrieve the list
of CPU models known by the hypervisor for a specific architecture.
Signed-off-by: Giuseppe Scrivano <gscrivan(a)redhat.com>
---
It explicitly disables the Python bindings as generator.py doesn't deal
correctly with the new API. Patch 5 in this series will implement the Python
bindings.
include/libvirt/libvirt.h.in | 18 ++++++++++++
python/generator.py | 1 +
src/cpu/cpu.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
src/cpu/cpu.h | 3 ++
src/driver.h | 7 +++++
src/libvirt.c | 47 ++++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 5 ++++
tools/virsh-host.c | 48 ++++++++++++++++++++++++++++++
tools/virsh.pod | 5 ++++
10 files changed, 204 insertions(+)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..43fb738 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4006,6 +4006,24 @@ int virConnectCompareCPU(virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
+/**
+ * virConnectGetCPUModelNames:
+ *
+ * @conn: virConnect connection
+ * @arch: Architecture
+ * @models: NULL terminated array of the CPU models supported for the specified
+ * architecture. Each element and the array itself must be freed by the caller
+ * with free.
+ * @flags: extra flags; not used yet, so callers should always pass 0.
+ *
+ * Get the list of supported CPU models for a specific architecture.
+ *
+ * Returns -1 on error, 0 on success.
+ */
+int virConnectGetCPUModelNames(virConnectPtr conn,
+ const char *arch,
+ char ***models,
+ unsigned int flags);
/**
* virConnectBaselineCPUFlags
diff --git a/python/generator.py b/python/generator.py
index 427cebc..f8ac100 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -366,6 +366,7 @@ foreign_encoding_args = (
# Class methods which are written by hand in libvirt.c but the Python-level
# code is still automatically generated (so they are not in skip_function()).
skip_impl = (
+ "virConnectGetCPUModelNames",
'virConnectGetVersion',
'virConnectGetLibVersion',
'virConnectListDomainsID',
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 023ce26..6abb173 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -27,6 +27,7 @@
#include "viralloc.h"
#include "virxml.h"
#include "cpu.h"
+#include "cpu_map.h"
#include "cpu_x86.h"
#include "cpu_powerpc.h"
#include "cpu_s390.h"
@@ -456,3 +457,71 @@ cpuModelIsAllowed(const char *model,
}
return false;
}
+
+struct cpuGetModelsData
+{
+ char **data;
+ unsigned int used;
+ unsigned int len; /* Doesn't count the last element DATA (NULL). */
+};
+
+static int
+cpuGetArchModelsCb(enum cpuMapElement element,
+ xmlXPathContextPtr ctxt,
+ void *cbdata)
+{
+ char *name;
+ struct cpuGetModelsData *data = cbdata;
+ if (element != CPU_MAP_ELEMENT_MODEL)
+ return 0;
+
+ name = virXPathString("string(@name)", ctxt);
+ if (name == NULL)
+ return -1;
+
+ if (data->used == data->len) {
+ data->len *= 2;
+ if (VIR_REALLOC_N(data->data, data->len + 1) < 0)
+ return -1;
+ }
+
+ data->data[data->used++] = name;
+ data->data[data->used] = NULL;
+ return 0;
+}
+
+
+static int
+cpuGetArchModels(const char *arch, struct cpuGetModelsData *data)
+{
+ return cpuMapLoad(arch, cpuGetArchModelsCb, data);
+}
+
+
+int
+cpuGetModels(const char *arch, char ***models)
+{
+ struct cpuGetModelsData data;
+
+ *models = data.data = NULL;
+ data.used = 0;
+ data.len = 8;
+
+ if (VIR_ALLOC_N(data.data, data.len + 1) < 0)
+ goto error;
+
+ if (cpuGetArchModels(arch, &data) < 0)
+ goto error;
+
+ *models = data.data;
+ return 0;
+
+error:
+ if (data.data) {
+ char **it;
+ for (it = data.data; *it; it++)
+ VIR_FREE(*it);
+ VIR_FREE(data.data);
+ }
+ return -1;
+}
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 7f1d4bd..ba22919 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -175,4 +175,7 @@ cpuModelIsAllowed(const char *model,
const char **models,
unsigned int nmodels);
+extern int
+cpuGetModels(const char *arch, char ***models);
+
#endif /* __VIR_CPU_H__ */
diff --git a/src/driver.h b/src/driver.h
index be64333..8cd164a 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -682,6 +682,12 @@ typedef char *
unsigned int flags);
typedef int
+(*virDrvConnectGetCPUModelNames)(virConnectPtr conn,
+ const char *args,
+ char ***models,
+ unsigned int flags);
+
+typedef int
(*virDrvDomainGetJobInfo)(virDomainPtr domain,
virDomainJobInfoPtr info);
@@ -1332,6 +1338,7 @@ struct _virDriver {
virDrvDomainMigratePerform3Params domainMigratePerform3Params;
virDrvDomainMigrateFinish3Params domainMigrateFinish3Params;
virDrvDomainMigrateConfirm3Params domainMigrateConfirm3Params;
+ virDrvConnectGetCPUModelNames connectGetCPUModelNames;
};
diff --git a/src/libvirt.c b/src/libvirt.c
index 07a3fd5..2032519 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -18519,6 +18519,53 @@ error:
/**
+ * virConnectGetCPUModelNames:
+ *
+ * @conn: virConnect connection
+ * @arch: Architecture
+ * @models: NULL terminated array of the CPU models supported for the specified
+ * architecture. Each element and the array itself must be freed by the caller
+ * with free.
+ * @flags: extra flags; not used yet, so callers should always pass 0.
+ *
+ * Get the list of supported CPU models for a specific architecture.
+ *
+ * Returns -1 on error, 0 on success.
+ */
+int
+virConnectGetCPUModelNames(virConnectPtr conn, const char *arch, char ***models,
+ unsigned int flags)
+{
+ VIR_DEBUG("conn=%p", conn);
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (arch == NULL) {
+ virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->driver->connectGetCPUModelNames) {
+ if (conn->driver->connectGetCPUModelNames(conn, arch, models, flags) <
0)
+ goto error;
+
+ return 0;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
* virConnectBaselineCPU:
*
* @conn: virConnect connection
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c25a61f..e485bd2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -717,6 +717,7 @@ cpuCompareXML;
cpuDataFree;
cpuDecode;
cpuEncode;
+cpuGetModels;
cpuGuestData;
cpuHasFeature;
cpuMapOverride;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index bbdf78a..547b3ea 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -634,4 +634,9 @@ LIBVIRT_1.1.1 {
virDomainSetMemoryStatsPeriod;
} LIBVIRT_1.1.0;
+LIBVIRT_1.1.2 {
+ global:
+ virConnectGetCPUModelNames;
+} LIBVIRT_1.1.1;
+
# .... define new API here using predicted next version number ....
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 880ae4b..ebab5ae 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -92,6 +92,25 @@ static const vshCmdOptDef opts_freecell[] = {
{.name = NULL}
};
+static const vshCmdInfo info_cpu_models[] = {
+ {.name = "help",
+ .data = N_("CPU models.")
+ },
+ {.name = "desc",
+ .data = N_("Get the CPU models for an arch.")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_cpu_models[] = {
+ {.name = "arch",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("architecture")
+ },
+ {.name = NULL}
+};
+
static bool
cmdFreecell(vshControl *ctl, const vshCmd *cmd)
{
@@ -626,6 +645,29 @@ cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
return true;
}
+static bool
+cmdCPUModelNames(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ char **models, **it;
+ const char *arch = NULL;
+
+ if (vshCommandOptStringReq(ctl, cmd, "arch", &arch) < 0)
+ return false;
+
+ if (virConnectGetCPUModelNames(ctl->conn, arch, &models, 0) < 0) {
+ vshError(ctl, "%s", _("failed to get CPU Models Names"));
+ return false;
+ }
+
+ for (it = models; *it; it++) {
+ vshPrint(ctl, "%s\n", *it);
+ VIR_FREE(*it);
+ }
+ VIR_FREE(models);
+
+ return true;
+}
+
/*
* "version" command
*/
@@ -851,6 +893,12 @@ const vshCmdDef hostAndHypervisorCmds[] = {
.info = info_capabilities,
.flags = 0
},
+ {.name = "cpu-models",
+ .handler = cmdCPUModelNames,
+ .opts = opts_cpu_models,
+ .info = info_cpu_models,
+ .flags = 0
+ },
{.name = "freecell",
.handler = cmdFreecell,
.opts = opts_freecell,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 0ae5178..72555e7 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -163,6 +163,7 @@ group as an option. For example:
Host and Hypervisor (help keyword 'host'):
capabilities capabilities
+ cpu-models show the CPU models for an architecture
connect (re)connect to hypervisor
freecell NUMA free memory
hostname print the hypervisor hostname
@@ -358,6 +359,10 @@ current domain is in.
=over 4
+=item B<cpu-models> I<arch>
+
+Print the list of CPU models known for the specified architecture.
+
=item B<running>
The domain is currently running on a CPU
--
1.8.3.1