[libvirt] [PATCH] lib: implement new API to retrieve the list of CPU models

Giuseppe Scrivano gscrivan at redhat.com
Wed Aug 21 19:02:00 UTC 2013


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 at redhat.com>
---
I have collected your comments on my RFC patch into this new version.  I've
replaced "virConnectGetCPUMapDesc" with "virConnectGetCPUModelNames".

The new function signature is:

int
virConnectGetCPUModelNames(virConnectPtr conn, const char *arch, char **models,
                           unsigned int flags);

It returns (in MODELS) the list of CPU models formatted as an XML document,
like:

<models>
  <arch name='x86'>
    <model name='486'/>
    <model name='pentium'/>
    <model name='pentium2'/>
    <model name='pentium3'/>
    <model name='pentiumpro'/>
    <model name='coreduo'/>
    ...
  </arch>
</models>

The FLAGS attribute is not used for now.

 daemon/remote.c                 | 36 +++++++++++++++++++++++++++
 include/libvirt/libvirt.h.in    | 18 ++++++++++++++
 python/generator.py             |  1 +
 python/libvirt-override-api.xml |  7 ++++++
 python/libvirt-override.c       | 28 +++++++++++++++++++++
 python/libvirt-override.py      | 11 +++++++++
 src/cpu/cpu.c                   | 55 +++++++++++++++++++++++++++++++++++++++++
 src/cpu/cpu.h                   |  3 +++
 src/driver.h                    |  7 ++++++
 src/libvirt.c                   | 42 +++++++++++++++++++++++++++++++
 src/libvirt_private.syms        |  1 +
 src/libvirt_public.syms         |  5 ++++
 src/qemu/qemu_driver.c          | 14 +++++++++++
 src/remote/remote_driver.c      | 40 ++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x    | 22 ++++++++++++++++-
 src/remote_protocol-structs     |  8 ++++++
 src/test/test_driver.c          | 17 +++++++++++++
 tools/virsh-host.c              | 45 +++++++++++++++++++++++++++++++++
 tools/virsh.pod                 |  5 ++++
 19 files changed, 364 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 03d5557..6fc2d78 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -4923,6 +4923,42 @@ cleanup:
 }
 
 
+static int
+remoteDispatchConnectGetCPUModelNames(
+        virNetServerPtr server ATTRIBUTE_UNUSED,
+        virNetServerClientPtr client ATTRIBUTE_UNUSED,
+        virNetMessagePtr msg ATTRIBUTE_UNUSED,
+        virNetMessageErrorPtr rerr,
+        remote_connect_get_cpu_model_names_args *args,
+        remote_connect_get_cpu_model_names_ret *ret)
+{
+    virDomainPtr dom = NULL;
+    int rv = -1;
+    char *models = NULL;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    if (virConnectGetCPUModelNames(priv->conn, args->arch, &models,
+                                   args->flags) < 0)
+        goto cleanup;
+
+    ret->models = models;
+    rv = 0;
+
+cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    if (dom)
+        virDomainFree(dom);
+    return rv;
+}
+
+
 static int remoteDispatchDomainCreateXMLWithFiles(
     virNetServerPtr server ATTRIBUTE_UNUSED,
     virNetServerClientPtr client,
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index a47e33c..3819606 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: XML description containing the CPU models.  The string is allocated
+ * by virConnectGetCPUModelNames and needs to be released using free() by the
+ * caller.
+ * @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..10d4a49 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -250,6 +250,7 @@ lxc_functions_failed = []
 qemu_functions_failed = []
 functions_skipped = [
     "virConnectListDomains",
+    "virConnectGetCPUModelNames",
 ]
 lxc_functions_skipped = []
 qemu_functions_skipped = []
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 9a88215..1bceb05 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -476,6 +476,13 @@
       <arg name='xmlCPUs' type='const char **' info='array of XML descriptions of host CPUs'/>
       <arg name='flags' type='unsigned int' info='fine-tuning flags, currently unused, pass 0.'/>
     </function>
+    <function name='virConnectGetCPUModelNames' file='python'>
+      <info>Get the list of supported CPU models.</info>
+      <return type='char *' info='list of supported CPU models'/>
+      <arg name='conn' type='virConnectPtr' info='virConnect connection'/>
+      <arg name='arch' type='const char *' info='arch'/>
+      <arg name='flags' type='unsigned int' info='fine-tuning flags, currently unused, pass 0.'/>
+    </function>
     <function name='virDomainSnapshotListNames' file='python'>
       <info>collect the list of snapshot names for the given domain</info>
       <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index d16b9a2..7537cf5 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -2276,6 +2276,34 @@ libvirt_virConnectGetVersion(PyObject *self ATTRIBUTE_UNUSED,
     return PyInt_FromLong(hvVersion);
 }
 
+PyObject *
+libvirt_virConnectGetCPUModelNames(PyObject *self ATTRIBUTE_UNUSED,
+                                   PyObject *args)
+{
+    int c_retval;
+    virConnectPtr conn;
+    PyObject *pyobj_conn;
+    char *models;
+    int flags = 0;
+    const char *arch = NULL;
+
+    if (!PyArg_ParseTuple(args, (char *)"Osi:virConnectGetCPUModelNames",
+                          &pyobj_conn, &arch, &flags))
+        return NULL;
+    conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+
+    c_retval = virConnectGetCPUModelNames(conn, arch, &models, flags);
+
+    LIBVIRT_END_ALLOW_THREADS;
+
+    if (c_retval == -1)
+        return VIR_PY_INT_FAIL;
+
+    return PyString_FromString(models);
+}
+
 static PyObject *
 libvirt_virConnectGetLibVersion(PyObject *self ATTRIBUTE_UNUSED,
                                 PyObject *args)
diff --git a/python/libvirt-override.py b/python/libvirt-override.py
index ccfec48..3471a43 100644
--- a/python/libvirt-override.py
+++ b/python/libvirt-override.py
@@ -207,3 +207,14 @@ def virEventAddTimeout(timeout, cb, opaque):
     ret = libvirtmod.virEventAddTimeout(timeout, cbData)
     if ret == -1: raise libvirtError ('virEventAddTimeout() failed')
     return ret
+
+def getCPUModelNames(conn, arch, flags=0):
+    """
+    get the list of supported CPU models.
+    @conn: virConnect connection
+    @arch: Architecture
+    @flags: extra flags; not used yet, so callers should always pass 0.
+    """
+    ret = libvirtmod.virConnectGetCPUModelNames(conn._o, arch, flags)
+    if ret == None: raise libvirtError ('virConnectGetCPUModelNames() failed', conn=self)
+    return ret
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 023ce26..5d05951 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,57 @@ cpuModelIsAllowed(const char *model,
     }
     return false;
 }
+
+static int
+cpuGetArchModelsCb(enum cpuMapElement element,
+                   xmlXPathContextPtr ctxt,
+                   void *data)
+{
+    virBufferPtr buf = (virBufferPtr) data;
+    if (element == CPU_MAP_ELEMENT_MODEL) {
+        const char *name = virXPathString("string(@name)", ctxt);
+        virBufferStrcat(buf, "    <model name='", name, "'/>\n", NULL);
+        VIR_FREE(name);
+        return virBufferError(buf) ? -1 : 0;
+    }
+    return 0;
+}
+
+
+static int
+cpuGetArchModels(virBufferPtr buf, const char *arch)
+{
+    return cpuMapLoad(arch, cpuGetArchModelsCb, buf);
+}
+
+
+int
+cpuGetModels(const char *arch, char **models)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAddLit(&buf, "<models>\n");
+    if (virBufferError(&buf))
+        goto no_memory;
+
+    virBufferStrcat(&buf, "  <arch name='", arch, "'>\n", NULL);
+    if (virBufferError(&buf))
+        goto no_memory;
+
+    if (cpuGetArchModels(&buf, arch) < 0)
+        goto error;
+
+    virBufferAddLit(&buf, "  </arch>\n</models>\n");
+    if (virBufferError(&buf))
+        goto no_memory;
+
+    *models = virBufferContentAndReset(&buf);
+    return 0;
+
+no_memory:
+    virReportOOMError();
+
+error:
+    virBufferFreeAndReset(&buf);
+    return -1;
+}
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 7f1d4bd..3e123b2 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..9cf74f5 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..56d6d1b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -18519,6 +18519,48 @@ error:
 
 
 /**
+ * virConnectGetCPUModelNames:
+ *
+ * @conn: virConnect connection
+ * @arch: Architecture
+ * @models: XML description containing the CPU models.  The string is allocated
+ * by virConnectGetCPUModelNames and needs to be released using free() by the
+ * caller.
+ * @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 (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/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2ad236e..c212b76 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16033,6 +16033,19 @@ qemuNodeSuspendForDuration(virConnectPtr conn,
     return nodeSuspendForDuration(target, duration, flags);
 }
 
+static int
+qemuConnectGetCPUModelNames(virConnectPtr conn,
+                            const char *arch,
+                            char **models,
+                            unsigned int flags)
+{
+    virCheckFlags(0, -1);
+    if (virConnectGetCPUModelNamesEnsureACL(conn) < 0)
+        return -1;
+
+    return cpuGetModels(arch, models);
+}
+
 
 static virDriver qemuDriver = {
     .no = VIR_DRV_QEMU,
@@ -16220,6 +16233,7 @@ static virDriver qemuDriver = {
     .domainMigratePerform3Params = qemuDomainMigratePerform3Params, /* 1.1.0 */
     .domainMigrateFinish3Params = qemuDomainMigrateFinish3Params, /* 1.1.0 */
     .domainMigrateConfirm3Params = qemuDomainMigrateConfirm3Params, /* 1.1.0 */
+    .connectGetCPUModelNames = qemuConnectGetCPUModelNames, /* 1.1.2 */
 };
 
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 71d0034..ebbcc48 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -5485,6 +5485,45 @@ done:
 
 
 static int
+remoteConnectGetCPUModelNames(virConnectPtr conn,
+                              const char *arch,
+                              char **models,
+                              unsigned int flags)
+{
+    int rv = -1;
+    remote_connect_get_cpu_model_names_args args;
+    remote_connect_get_cpu_model_names_ret ret;
+    struct private_data *priv = conn->privateData;
+
+    remoteDriverLock(priv);
+
+    memset(&args, 0, sizeof(args));
+    memset(&ret, 0, sizeof(ret));
+
+    args.arch = (char *) arch;
+    args.flags = flags;
+
+    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES,
+             (xdrproc_t) xdr_remote_connect_get_cpu_model_names_args, (char *) &args,
+             (xdrproc_t) xdr_remote_connect_get_cpu_model_names_ret, (char *) &ret) < 0)
+        goto error;
+
+    *models = ret.models; /* Caller frees. */
+
+    rv = 0;
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+
+error:
+    rv = -1;
+    VIR_FREE(ret.models);
+    goto done;
+}
+
+
+static int
 remoteDomainOpenGraphics(virDomainPtr dom,
                          unsigned int idx,
                          int fd,
@@ -6811,6 +6850,7 @@ static virDriver remote_driver = {
     .domainMigratePerform3Params = remoteDomainMigratePerform3Params, /* 1.1.0 */
     .domainMigrateFinish3Params = remoteDomainMigrateFinish3Params, /* 1.1.0 */
     .domainMigrateConfirm3Params = remoteDomainMigrateConfirm3Params, /* 1.1.0 */
+    .connectGetCPUModelNames = remoteConnectGetCPUModelNames, /* 1.1.2 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 7cfebdf..7ef6c61 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -234,6 +234,11 @@ const REMOTE_DOMAIN_DISK_ERRORS_MAX = 256;
  */
 const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64;
 
+/*
+ * Upper limit on lists of CPU models
+ */
+const REMOTE_INTERFACE_CPU_MODELS_MAX = 16384;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@@ -2837,6 +2842,15 @@ struct remote_domain_event_device_removed_msg {
     remote_nonnull_string devAlias;
 };
 
+struct remote_connect_get_cpu_model_names_args {
+    remote_nonnull_string arch;
+    unsigned int flags;
+};
+
+struct remote_connect_get_cpu_model_names_ret {
+    remote_nonnull_string models;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -5000,5 +5014,11 @@ enum remote_procedure {
      * @generate: both
      * @acl: none
      */
-    REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311
+    REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
+
+    /**
+     * @generate: none
+     * @acl: connect:read
+     */
+    REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 4e27aae..a2c3b14 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2316,6 +2316,13 @@ struct remote_domain_event_device_removed_msg {
         remote_nonnull_domain      dom;
         remote_nonnull_string      devAlias;
 };
+struct remote_connect_get_cpu_model_names_args {
+        remote_nonnull_string      arch;
+        u_int                      flags;
+};
+struct remote_connect_get_cpu_model_names_ret {
+        remote_nonnull_string      models;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -2628,4 +2635,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_CREATE_XML_WITH_FILES = 309,
         REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310,
         REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
+        REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312,
 };
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index d7b2e40..51baf18 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -5801,6 +5801,22 @@ testDomainScreenshot(virDomainPtr dom ATTRIBUTE_UNUSED,
     return ret;
 }
 
+static int
+testConnectGetCPUModelNames(virConnectPtr conn ATTRIBUTE_UNUSED,
+                            const char *arch,
+                            char **models,
+                            unsigned int flags)
+{
+    char *ret;
+    virCheckFlags(0, -1);
+    if (virAsprintf(&ret, "<models>\n"
+                          "  <arch name='%s'/>\n"
+                          "</models>\n", arch) < 0)
+        return -1;
+
+    *models = ret;
+    return 0;
+}
 
 static virDriver testDriver = {
     .no = VIR_DRV_TEST,
@@ -5872,6 +5888,7 @@ static virDriver testDriver = {
     .connectIsAlive = testConnectIsAlive, /* 0.9.8 */
     .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */
     .domainScreenshot = testDomainScreenshot, /* 1.0.5 */
+    .connectGetCPUModelNames = testConnectGetCPUModelNames, /* 1.1.2 */
 };
 
 static virNetworkDriver testNetworkDriver = {
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 880ae4b..cc210b4 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,26 @@ cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
     return true;
 }
 
+static bool
+cmdCPUModelNames(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    char *models;
+    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;
+    }
+
+    vshPrint(ctl, "%s\n", models);
+    VIR_FREE(models);
+
+    return true;
+}
+
 /*
  * "version" command
  */
@@ -851,6 +890,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




More information about the libvir-list mailing list