Update the per device boot schema to add an optional loadparm parameter.
eg: <boot order='1' loadparm='2'/>
Extend the virDomainDeviceInfo to support loadparm option.
Modify the appropriate functions to parse loadparm from boot device xml.
Add the xml2xml test to validate the field.
Signed-off-by: Farhan Ali <alifm@linux.vnet.ibm.com>
Reviewed-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
<dt><code>boot</code></dt>
<dd>Specifies that the disk is bootable. The <code>order</code>
attribute determines the order in which devices will be tried during
- boot sequence. The per-device <code>boot</code> elements cannot be
- used together with general boot elements in
+ boot sequence. On the S390 architecture only the first boot device is
+ used. The optional <code>loadparm</code> attribute is an 8 character
+ string which can be queried by guests on S390 via sclp or diag 308.
+ Linux guests on S390 can use <code>loadparm</code> to select a boot
+ entry. <span class="since">Since 3.5.0</span>
+ The per-device <code>boot</code> elements cannot be used together
+ with general boot elements in
<a href="#elementsOSBIOS">BIOS bootloader</a> section.
<span class="since">Since 0.8.8</span>
</dd>
<attribute name="order">
<ref name="positiveInteger"/>
</attribute>
+ <optional>
+ <attribute name="loadparm">
+ <data type="string">
+ <param name="pattern">[a-zA-Z0-9.\s]{1,8}</param>
+ </data>
+ </attribute>
+ </optional>
<empty/>
</element>
</define>
* assignment, never saved and never reported.
*/
int pciConnectFlags; /* enum virDomainPCIConnectFlags */
+ char *loadparm;
};
memset(&info->addr, 0, sizeof(info->addr));
info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
VIR_FREE(info->romfile);
+ VIR_FREE(info->loadparm);
}
}
+/**
+ * virDomainDeviceLoadparmIsValid
+ * @loadparm : The string to validate
+ *
+ * The valid set of values for loadparm are [a-zA-Z0-9.]
+ * and blank spaces.
+ * The maximum allowed length is 8 characters.
+ * An empty string is considered invalid
+ */
+static bool
+virDomainDeviceLoadparmIsValid(const char *loadparm)
+{
+ size_t i;
+
+ if (virStringIsEmpty(loadparm)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("loadparm cannot be an empty string"));
+ return false;
+ }
+
+ if (strlen(loadparm) > 8) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("loadparm '%s' exceeds 8 characters"), loadparm);
+ return false;
+ }
+
+ for (i = 0; i < strlen(loadparm); i++) {
+ uint8_t c = loadparm[i];
+
+ if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
+ (c == '.') || (c == ' ')) {
+ continue;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid loadparm char '%c', expecting chars"
+ " in set of [a-zA-Z0-9.] and blank spaces"), c);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
static void
virDomainVirtioOptionsFormat(virBufferPtr buf,
virDomainVirtioOptionsPtr virtio)
virDomainDeviceInfoPtr info,
unsigned int flags)
{
- if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex)
- virBufferAsprintf(buf, "<boot order='%u'/>\n", info->bootIndex);
+ if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
+ virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);
+ if (info->loadparm)
+ virBufferAsprintf(buf, " loadparm='%s'", info->loadparm);
+
+ virBufferAddLit(buf, "/>\n");
+ }
if (info->alias &&
!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
virBufferAsprintf(buf, "<alias name='%s'/>\n", info->alias);
virHashTablePtr bootHash)
{
char *order;
+ char *loadparm;
int ret = -1;
if (!(order = virXMLPropString(node, "order"))) {
goto cleanup;
}
+ loadparm = virXMLPropString(node, "loadparm");
+ if (loadparm) {
+ if (virStringToUpper(&info->loadparm, loadparm) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to convert loadparm '%s' to upper case"),
+ loadparm);
+ goto cleanup;
+ }
+
+ if (!virDomainDeviceLoadparmIsValid(info->loadparm)) {
+ VIR_FREE(info->loadparm);
+ goto cleanup;
+ }
+ }
+
ret = 0;
cleanup:
VIR_FREE(order);
+ VIR_FREE(loadparm);
return ret;
}
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219136</memory>
+ <currentMemory>219136</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-s390x</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='virtio'/>
+ <boot order='1' loadparm='system1'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x2'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hdb' bus='virtio'/>
+ <boot order='3' loadparm='3'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x3'/>
+ </disk>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:54'/>
+ <model type='virtio'/>
+ <boot order='2' loadparm='2.lp'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0'/>
+ </interface>
+ <interface type='user'>
+ <mac address='00:11:22:33:42:36'/>
+ <model type='virtio'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x4'/>
+ </interface>
+ <memballoon model='virtio'>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x1'/>
+ </memballoon>
+ </devices>
+</domain>
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-s390x</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='virtio'/>
+ <boot order='1' loadparm='SYSTEM1'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0002'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hdb' bus='virtio'/>
+ <boot order='3' loadparm='3'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0003'/>
+ </disk>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:54'/>
+ <model type='virtio'/>
+ <boot order='2' loadparm='2.LP'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
+ </interface>
+ <interface type='user'>
+ <mac address='00:11:22:33:42:36'/>
+ <model type='virtio'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0004'/>
+ </interface>
+ <memballoon model='virtio'>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0001'/>
+ </memballoon>
+ <panic model='s390'/>
+ </devices>
+</domain>
DO_TEST("minimal", NONE);
DO_TEST("machine-core-on", NONE);
DO_TEST("machine-core-off", NONE);
+ DO_TEST("machine-loadparm-multiple-disks-nets-s390", NONE);
DO_TEST("default-kvm-host-arch", NONE);
DO_TEST("default-qemu-host-arch", NONE);
DO_TEST("boot-cdrom", NONE);