]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce /domain/cpu/@check XML attribute
authorJiri Denemark <jdenemar@redhat.com>
Wed, 1 Mar 2017 14:18:22 +0000 (15:18 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Fri, 17 Mar 2017 10:50:48 +0000 (11:50 +0100)
The attribute can be used to request a specific way of checking whether
the virtual CPU matches created by the hypervisor matches the
specification in domain XML.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
docs/formatdomain.html.in
docs/schemas/cputypes.rng
docs/schemas/domaincommon.rng
src/conf/cpu_conf.c
src/conf/cpu_conf.h
src/conf/domain_conf.c

index 3d16d5fada1df336c88573c97ee987d19d8bc841..4a3123e989706c6e42ab03029e95fda1473fd197 100644 (file)
         <span class="since">Since 0.8.5</span> the <code>match</code>
         attribute can be omitted and will default to <code>exact</code>.
 
+        Sometimes the hypervisor is not able to create a virtual CPU exactly
+        matching the specification passed by libvirt.
+        <span class="since">Since 3.2.0</span>, an optional <code>check</code>
+        attribute can be used to request a specific way of checking whether
+        the virtual CPU matches the specification. It is usually safe to omit
+        this attribute when starting a domain and stick with the default
+        value. Once the domain starts, libvirt will automatically change the
+        <code>check</code> attribute to the best supported value to ensure the
+        virtual CPU does not change when the domain is migrated to another
+        host. The following values can be used:
+
+        <dl>
+          <dt><code>none</code></dt>
+          <dd>Libvirt does no checking and it is up to the hypervisor to
+            refuse to start the domain if it cannot provide the requested CPU.
+            With QEMU this means no checking is done at all since the default
+            behavior of QEMU is to emit warnings, but start the domain anyway.
+          </dd>
+
+          <dt><code>partial</code></dt>
+          <dd>Libvirt will check the guest CPU specification before starting
+            a domain, but the rest is left on the hypervisor. It can still
+            provide a different virtual CPU.</dd>
+
+          <dt><code>full</code></dt>
+          <dd>The virtual CPU created by the hypervisor will be checked
+            against the CPU specification and the domain will not be started
+            unless the two CPUs match.</dd>
+        </dl>
+
         <span class="since">Since 0.9.10</span>, an optional <code>mode</code>
         attribute may be used to make it easier to configure a guest CPU to be
         as close to host CPU as possible. Possible values for the
index 7cc9dd3d8351b194b0b87a7c45f323fbaa06082f..8189114e3c3032711e53aec2e1628790e71b31a7 100644 (file)
     </attribute>
   </define>
 
+  <define name="cpuCheck">
+    <attribute name="check">
+      <choice>
+        <value>none</value>
+        <value>partial</value>
+        <value>full</value>
+      </choice>
+    </attribute>
+  </define>
+
   <define name="cpuModel">
     <element name="model">
       <optional>
index 24d1edbddd6edec5d3eee9068977b71ef14563fc..fbedc9b1f92d5b20d3ab24ff0a9dce3d5236d1b1 100644 (file)
       <optional>
         <ref name="cpuMatch"/>
       </optional>
+      <optional>
+        <ref name="cpuCheck"/>
+      </optional>
       <interleave>
         <optional>
           <ref name="cpuModel"/>
index 2724fa30a979927cef304793615bb0b91b630d3f..d7c8b8ff211eed7594ca57283c44924c4615db74 100644 (file)
@@ -45,6 +45,12 @@ VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST,
               "exact",
               "strict")
 
+VIR_ENUM_IMPL(virCPUCheck, VIR_CPU_CHECK_LAST,
+              "default",
+              "none",
+              "partial",
+              "full")
+
 VIR_ENUM_IMPL(virCPUFallback, VIR_CPU_FALLBACK_LAST,
               "allow",
               "forbid")
@@ -182,6 +188,7 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu)
     copy->type = cpu->type;
     copy->mode = cpu->mode;
     copy->match = cpu->match;
+    copy->check = cpu->check;
     copy->fallback = cpu->fallback;
     copy->sockets = cpu->sockets;
     copy->cores = cpu->cores;
@@ -277,6 +284,7 @@ virCPUDefParseXML(xmlNodePtr node,
 
     if (def->type == VIR_CPU_TYPE_GUEST) {
         char *match = virXMLPropString(node, "match");
+        char *check;
 
         if (!match) {
             if (virXPathBoolean("boolean(./model)", ctxt))
@@ -294,6 +302,19 @@ virCPUDefParseXML(xmlNodePtr node,
                 goto error;
             }
         }
+
+        if ((check = virXMLPropString(node, "check"))) {
+            int value = virCPUCheckTypeFromString(check);
+            VIR_FREE(check);
+
+            if (value < 0) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("Invalid check attribute for CPU "
+                                 "specification"));
+                goto error;
+            }
+            def->check = value;
+        }
     }
 
     if (def->type == VIR_CPU_TYPE_HOST) {
@@ -532,6 +553,11 @@ virCPUDefFormatBufFull(virBufferPtr buf,
             }
             virBufferAsprintf(&attributeBuf, " match='%s'", tmp);
         }
+
+        if (def->check) {
+            virBufferAsprintf(&attributeBuf, " check='%s'",
+                              virCPUCheckTypeToString(def->check));
+        }
     }
 
     /* Format children */
index cc3fbf0a45b95d23f5923f404000807ceb77b04e..9118f037ed20dca48ebe55809f3be3a361329620 100644 (file)
@@ -63,6 +63,17 @@ typedef enum {
 
 VIR_ENUM_DECL(virCPUMatch)
 
+typedef enum {
+    VIR_CPU_CHECK_DEFAULT,
+    VIR_CPU_CHECK_NONE,
+    VIR_CPU_CHECK_PARTIAL,
+    VIR_CPU_CHECK_FULL,
+
+    VIR_CPU_CHECK_LAST
+} virCPUCheck;
+
+VIR_ENUM_DECL(virCPUCheck)
+
 typedef enum {
     VIR_CPU_FALLBACK_ALLOW,
     VIR_CPU_FALLBACK_FORBID,
@@ -98,6 +109,7 @@ struct _virCPUDef {
     int type;           /* enum virCPUType */
     int mode;           /* enum virCPUMode */
     int match;          /* enum virCPUMatch */
+    virCPUCheck check;
     virArch arch;
     char *model;
     char *vendor_id;    /* vendor id returned by CPUID in the guest */
index eaf46b2a48412f3032c51d4c24a23a07b0ebc34a..6bbc6a2a7b4af2e03c5cfcddafbc682fc3502913 100644 (file)
@@ -4592,6 +4592,24 @@ virDomainVcpuDefPostParse(virDomainDefPtr def)
 }
 
 
+static int
+virDomainDefPostParseCPU(virDomainDefPtr def)
+{
+    if (!def->cpu)
+        return 0;
+
+    if (def->cpu->mode == VIR_CPU_MODE_CUSTOM &&
+        !def->cpu->model &&
+        def->cpu->check != VIR_CPU_CHECK_DEFAULT) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("check attribute specified for CPU with no model"));
+        return -1;
+    }
+
+    return 0;
+}
+
+
 static int
 virDomainDefPostParseInternal(virDomainDefPtr def,
                               struct virDomainDefPostParseDeviceIteratorData *data)
@@ -4642,6 +4660,9 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
 
     virDomainDefPostParseGraphics(def);
 
+    if (virDomainDefPostParseCPU(def) < 0)
+        return -1;
+
     return 0;
 }