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'.
This commit is contained in:
Dmitry Andreev 2015-11-24 15:26:36 +03:00 committed by Jiri Denemark
parent ca6ddffe2c
commit 59fc0d0609
10 changed files with 129 additions and 55 deletions

View File

@ -6152,6 +6152,7 @@ qemu-kvm -net nic,model=? /dev/null
<pre>
...
&lt;devices&gt;
&lt;panic model='hyperv'/&gt;
&lt;panic model='isa'&gt;
&lt;address type='isa' iobase='0x505'/&gt;
&lt;/panic&gt;

View File

@ -4044,9 +4044,9 @@
<optional>
<ref name="nvram"/>
</optional>
<optional>
<zeroOrMore>
<ref name="panic"/>
</optional>
</zeroOrMore>
</interleave>
</element>
</define>

View File

@ -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)

View File

@ -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;

View File

@ -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;
size_t j;
for (j = 0; j < dom->npanics; j++) {
if (dom->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV)
break;
}
panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
dom->panic = panic;
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;

View File

@ -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;

View File

@ -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

View File

@ -0,0 +1,28 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219100</memory>
<currentMemory unit='KiB'>219100</currentMemory>
<vcpu placement='static'>6</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='network'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<controller type='usb' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='none'/>
<panic model='hyperv'/>
<panic model='isa'>
<address type='isa' iobase='0x505'/>
</panic>
</devices>
</domain>

View File

@ -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);

View File

@ -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");