[libvirt] [PATCHv4 3/6] schema: allow multiple panic devices

Dmitry Andreev dandreev at virtuozzo.com
Fri Nov 13 17:16:37 UTC 2015


'model' attribute was added to a panic device but only one panic
device is allowed. This patch changes panic device presence
from 'optional' to 'zeroOrMore'.
---
 docs/formatdomain.html.in     |  1 +
 docs/schemas/domaincommon.rng |  4 +--
 src/conf/domain_conf.c        | 73 ++++++++++++++++++-------------------------
 src/conf/domain_conf.h        |  4 ++-
 src/qemu/qemu_command.c       | 50 ++++++++++++++++++-----------
 src/qemu/qemu_domain.c        | 21 ++++++++++---
 6 files changed, 83 insertions(+), 70 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index ef30624..7a14473 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6152,6 +6152,7 @@ qemu-kvm -net nic,model=? /dev/null
 <pre>
   ...
   <devices>
+    <panic model='hyperv'/>
     <panic model='isa'>
       <address type='isa' iobase='0x505'/>
     </panic>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d67b1bf..8965976 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4044,9 +4044,9 @@
         <optional>
           <ref name="nvram"/>
         </optional>
-        <optional>
+        <zeroOrMore>
           <ref name="panic"/>
-        </optional>
+        </zeroOrMore>
       </interleave>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8339280..2f17675 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2538,7 +2538,9 @@ void virDomainDefFree(virDomainDefPtr def)
 
     virDomainTPMDefFree(def->tpm);
 
-    virDomainPanicDefFree(def->panic);
+    for (i = 0; i < def->npanics; i++)
+        virDomainPanicDefFree(def->panics[i]);
+    VIR_FREE(def->panics);
 
     VIR_FREE(def->idmap.uidmap);
     VIR_FREE(def->idmap.gidmap);
@@ -3617,10 +3619,10 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
         if (cb(def, &device, &def->tpm->info, opaque) < 0)
             return -1;
     }
-    if (def->panic) {
-        device.type = VIR_DOMAIN_DEVICE_PANIC;
-        device.data.panic = def->panic;
-        if (cb(def, &device, &def->panic->info, opaque) < 0)
+    device.type = VIR_DOMAIN_DEVICE_PANIC;
+    for (i = 0; i < def->npanics; i++) {
+        device.data.panic = def->panics[i];
+        if (cb(def, &device, &def->panics[i]->info, opaque) < 0)
             return -1;
     }
 
@@ -16407,23 +16409,20 @@ virDomainDefParseXML(xmlDocPtr xml,
     VIR_FREE(nodes);
 
     /* analysis of the panic devices */
-    def->panic = NULL;
     if ((n = virXPathNodeSet("./devices/panic", ctxt, &nodes)) < 0)
         goto error;
-    if (n > 1) {
-        virReportError(VIR_ERR_XML_ERROR, "%s",
-                       _("only a single panic device is supported"));
+    if (n && VIR_ALLOC_N(def->panics, n) < 0)
         goto error;
-    }
-    if (n > 0) {
+    for (i = 0; i < n; i++) {
         virDomainPanicDefPtr panic =
-            virDomainPanicDefParseXML(nodes[0]);
+            virDomainPanicDefParseXML(nodes[i]);
+
         if (!panic)
             goto error;
 
-        def->panic = panic;
-        VIR_FREE(nodes);
+        def->panics[def->npanics++] = panic;
     }
+    VIR_FREE(nodes);
 
     /* analysis of the shmem devices */
     if ((n = virXPathNodeSet("./devices/shmem", ctxt, &nodes)) < 0)
@@ -17633,17 +17632,14 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
 }
 
 static bool
-virDomainPanicCheckABIStability(virDomainPanicDefPtr src,
+virDomainPanicDefCheckABIStability(virDomainPanicDefPtr src,
                                 virDomainPanicDefPtr dst)
 {
-    if (!src && !dst)
-        return true;
-
-    if (!src || !dst) {
+    if (src->model != dst->model) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("Target domain panic device count '%d' "
-                         "does not match source count '%d'"),
-                       src ? 1 : 0, dst ? 1 : 0);
+                       _("Target panic model '%s' does not match source '%s'"),
+                       virDomainPanicModelTypeToString(dst->model),
+                       virDomainPanicModelTypeToString(src->model));
         return false;
     }
 
@@ -17709,13 +17705,6 @@ virDomainTPMDefCheckABIStability(virDomainTPMDefPtr src,
 }
 
 static bool
-virDomainPanicDefCheckABIStability(virDomainPanicDefPtr src,
-                                   virDomainPanicDefPtr dst)
-{
-    return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
-}
-
-static bool
 virDomainMemoryDefCheckABIStability(virDomainMemoryDefPtr src,
                                     virDomainMemoryDefPtr dst)
 {
@@ -18132,8 +18121,16 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
         if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
             goto error;
 
-    if (!virDomainPanicCheckABIStability(src->panic, dst->panic))
+    if (src->npanics != dst->npanics) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain panic device count %zu "
+                         "does not match source %zu"), dst->npanics, src->npanics);
         goto error;
+    }
+
+    for (i = 0; i < src->npanics; i++)
+        if (!virDomainPanicDefCheckABIStability(src->panics[i], dst->panics[i]))
+            goto error;
 
     if (src->nshmems != dst->nshmems) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -18157,16 +18154,6 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
         goto error;
     }
 
-    if (src->panic && dst->panic) {
-        if (!virDomainPanicDefCheckABIStability(src->panic, dst->panic))
-            goto error;
-    } else if (src->panic || dst->panic) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Either both target and source domains or none of "
-                         "them must have PANIC device present"));
-        goto error;
-    }
-
     if (src->nmems != dst->nmems) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target domain memory device count %zu "
@@ -22460,9 +22447,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     if (def->nvram)
         virDomainNVRAMDefFormat(buf, def->nvram, flags);
 
-    if (def->panic &&
-        virDomainPanicDefFormat(buf, def->panic) < 0)
-        goto error;
+    for (n = 0; n < def->npanics; n++)
+        if (virDomainPanicDefFormat(buf, def->panics[n]) < 0)
+            goto error;
 
     for (n = 0; n < def->nshmems; n++)
         if (virDomainShmemDefFormat(buf, def->shmems[n], flags) < 0)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index be18994..43f99ac 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2316,6 +2316,9 @@ struct _virDomainDef {
     size_t nmems;
     virDomainMemoryDefPtr *mems;
 
+    size_t npanics;
+    virDomainPanicDefPtr *panics;
+
     /* Only 1 */
     virDomainWatchdogDefPtr watchdog;
     virDomainMemballoonDefPtr memballoon;
@@ -2324,7 +2327,6 @@ struct _virDomainDef {
     virCPUDefPtr cpu;
     virSysinfoDefPtr sysinfo;
     virDomainRedirFilterDefPtr redirfilter;
-    virDomainPanicDefPtr panic;
 
     void *namespaceData;
     virDomainXMLNamespace ns;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2d0cec0..965b68e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7623,14 +7623,16 @@ qemuBuildCpuArgStr(virQEMUDriverPtr driver,
         }
     }
 
-    if (def->panic &&
-        def->panic->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
-        if (!have_cpu) {
-            virBufferAdd(&buf, default_model, -1);
-            have_cpu = true;
-        }
+    for (i = 0; i < def->npanics; i++) {
+        if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
+            if (!have_cpu) {
+                virBufferAdd(&buf, default_model, -1);
+                have_cpu = true;
+            }
 
-        virBufferAddLit(&buf, ",hv_crash");
+            virBufferAddLit(&buf, ",hv_crash");
+            break;
+        }
     }
 
     if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
@@ -11159,8 +11161,8 @@ qemuBuildCommandLine(virConnectPtr conn,
         goto error;
     }
 
-    if (def->panic) {
-        virDomainPanicModel model = def->panic->model;
+    for (i = 0; i < def->npanics; i++) {
+        virDomainPanicModel model = def->panics[i]->model;
 
         if (model == VIR_DOMAIN_PANIC_MODEL_DEFAULT) {
             if (ARCH_IS_PPC64(def->os.arch) &&
@@ -11175,7 +11177,7 @@ qemuBuildCommandLine(virConnectPtr conn,
             /* Panic with model 'hyperv' is not a device, it should
              * be configured in cpu commandline. The address
              * cannot be configured by the user */
-            if (def->panic->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+            if (def->panics[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                _("setting the panic device address is not "
                                  "supported for model 'hyperv'"));
@@ -11188,7 +11190,7 @@ qemuBuildCommandLine(virConnectPtr conn,
                 /* For pSeries guests, the firmware provides the same
                  * functionality as the pvpanic device. The address
                  * cannot be configured by the user */
-                if (def->panic->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+                if (def->panics[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                    _("setting the panic device address is not "
                                      "supported for model 'pseries'"));
@@ -11210,11 +11212,11 @@ qemuBuildCommandLine(virConnectPtr conn,
                 goto error;
             }
 
-            switch (def->panic->info.type) {
+            switch (def->panics[i]->info.type) {
             case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
                 virCommandAddArg(cmd, "-device");
                 virCommandAddArgFormat(cmd, "pvpanic,ioport=%d",
-                                       def->panic->info.addr.isa.iobase);
+                                       def->panics[i]->info.addr.isa.iobase);
                 break;
 
             case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
@@ -12582,12 +12584,22 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
                     goto cleanup;
             }
         } else if (STREQ(tokens[i], "hv_crash")) {
-            virDomainPanicDefPtr panic;
-            if (VIR_ALLOC(panic) < 0)
-                goto cleanup;
-
-            panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
-            dom->panic = panic;
+            size_t j;
+            for (j = 0; j < dom->npanics; j++) {
+                 if (dom->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV)
+                     break;
+            }
+
+            if (j == dom->npanics) {
+                virDomainPanicDefPtr panic;
+                if (VIR_ALLOC(panic) < 0 ||
+                    VIR_APPEND_ELEMENT_COPY(dom->panics,
+                                            dom->npanics, panic) < 0) {
+                    VIR_FREE(panic);
+                    goto cleanup;
+                }
+                panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
+            }
         } else if (STRPREFIX(tokens[i], "hv_")) {
             const char *token = tokens[i] + 3; /* "hv_" */
             const char *feature, *value;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 3d2b7a0..19ae5f7 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1175,12 +1175,23 @@ qemuDomainDefPostParse(virDomainDefPtr def,
                                   VIR_DOMAIN_INPUT_BUS_USB) < 0)
         goto cleanup;
 
-    if (addPanicDevice && !def->panic) {
-        virDomainPanicDefPtr panic;
-        if (VIR_ALLOC(panic) < 0)
-            goto cleanup;
+    if (addPanicDevice) {
+        size_t j;
+        for (j = 0; j < def->npanics; j++) {
+            if (def->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_DEFAULT ||
+                def->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_PSERIES)
+                break;
+        }
 
-        def->panic = panic;
+        if (j == def->npanics) {
+                virDomainPanicDefPtr panic;
+            if (VIR_ALLOC(panic) < 0 ||
+                VIR_APPEND_ELEMENT_COPY(def->panics,
+                                        def->npanics, panic) < 0) {
+                VIR_FREE(panic);
+                goto cleanup;
+            }
+        }
     }
 
     ret = 0;
-- 
1.8.3.1




More information about the libvir-list mailing list