From: Dmitry Andreev Date: Tue, 24 Nov 2015 12:26:36 +0000 (+0300) Subject: Allow multiple panic devices X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=59fc0d060926c43bfcb456ee290819bdb03fe5e2;p=people%2Fliuw%2Flibxenctrl-split%2Flibvirt.git Allow multiple panic devices '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'. --- diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 32b196dd2..06aec4b14 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -6152,6 +6152,7 @@ qemu-kvm -net nic,model=? /dev/null
   ...
   <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 9d21650e8..7e7fd583f 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4044,9 +4044,9 @@
         
           
         
-        
+        
           
-        
+        
       
     
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 58a2d18f4..2bddb67e0 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;
     }
 
@@ -16406,23 +16408,19 @@ 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)
@@ -17635,17 +17633,6 @@ static bool
 virDomainPanicDefCheckABIStability(virDomainPanicDefPtr src,
                                    virDomainPanicDefPtr dst)
 {
-    if (!src && !dst)
-        return true;
-
-    if (!src || !dst) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("Target domain panic device count '%d' "
-                         "does not match source count '%d'"),
-                       src ? 1 : 0, dst ? 1 : 0);
-        return false;
-    }
-
     if (src->model != dst->model) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target panic model '%s' does not match source '%s'"),
@@ -18132,8 +18119,17 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
         if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
             goto error;
 
-    if (!virDomainPanicDefCheckABIStability(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,
@@ -22451,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 11d891fb5..038d65b05 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 e83be585e..a0947b2aa 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7577,14 +7577,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) {
@@ -11059,8 +11061,8 @@ qemuBuildCommandLine(virConnectPtr conn,
         goto error;
     }
 
-    if (def->panic) {
-        switch ((virDomainPanicModel) def->panic->model) {
+    for (i = 0; i < def->npanics; i++) {
+        switch ((virDomainPanicModel) def->panics[i]->model) {
         case VIR_DOMAIN_PANIC_MODEL_HYPERV:
             /* Panic with model 'hyperv' is not a device, it should
              * be configured in cpu commandline. The address
@@ -11071,7 +11073,7 @@ qemuBuildCommandLine(virConnectPtr conn,
                                  "panic device of model 'hyperv'"));
                 goto error;
             }
-            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'"));
@@ -11090,7 +11092,7 @@ qemuBuildCommandLine(virConnectPtr conn,
                                  "of model 'pseries'"));
                 goto error;
             }
-            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'"));
@@ -11106,11 +11108,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:
@@ -12480,12 +12482,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 689abc283..8e6c0380b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1178,12 +1178,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;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-panic-double.args b/tests/qemuxml2argvdata/qemuxml2argv-panic-double.args
new file mode 100644
index 000000000..0d3a38591
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-panic-double.args
@@ -0,0 +1,21 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-cpu qemu32,hv_crash \
+-m 214 \
+-smp 6 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefconfig \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-boot n \
+-usb \
+-device pvpanic,ioport=1285
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-panic-double.xml b/tests/qemuxml2argvdata/qemuxml2argv-panic-double.xml
new file mode 100644
index 000000000..aadb75896
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-panic-double.xml
@@ -0,0 +1,28 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  6
+  
+    hvm
+    
+  
+  
+    
+  
+  
+  destroy
+  restart
+  destroy
+  
+    /usr/bin/qemu
+    
+    
+    
+    
+    
+      
+ + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index a15305d2a..ea16c9829 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1633,6 +1633,8 @@ mymain(void) DO_TEST("panic", QEMU_CAPS_DEVICE_PANIC, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + DO_TEST("panic-double", QEMU_CAPS_DEVICE_PANIC, + QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); DO_TEST("panic-no-address", QEMU_CAPS_DEVICE_PANIC, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0e43ee92d..fd58331c9 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -594,6 +594,7 @@ mymain(void) DO_TEST_DIFFERENT("panic"); DO_TEST("panic-isa"); DO_TEST("panic-pseries"); + DO_TEST("panic-double"); DO_TEST("panic-no-address"); DO_TEST_DIFFERENT("disk-backing-chains");