[libvirt] [PATCH v2 0/3] Add support for reboot-timeout

This series introduces simple reboot timeout support. That means what should be done in case all boot options fail, reboot or not. And if yes, then how long the machine should wait. Before adding the support for that into XML parser, builder, and qemu, I felt the need to cleanup the boot parsing and enums (I couldn't look at that), so that's the first patch. Most of it is mechanical, the rest should be pretty straight-forward. --- v2: - modified according to mprivozn and danpb - ACK'd patch not sent Martin Kletzander (3): Add support for reboot-timeout qemu: Add support for reboot-timeout QEMU Tests for reboot-timeout docs/formatdomain.html.in | 11 +++++-- docs/schemas/domaincommon.rng | 24 +++++++++++---- src/conf/domain_conf.c | 34 ++++++++++++++++++---- src/conf/domain_conf.h | 3 ++ src/qemu/qemu_capabilities.c | 4 +++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 28 ++++++++++++++++++ tests/qemuargv2xmltest.c | 4 +++ .../qemuxml2argv-reboot-timeout-disabled.args | 3 ++ .../qemuxml2argv-reboot-timeout-disabled.xml | 21 +++++++++++++ .../qemuxml2argv-reboot-timeout-enabled.args | 3 ++ .../qemuxml2argv-reboot-timeout-enabled.xml | 21 +++++++++++++ tests/qemuxml2argvtest.c | 5 ++++ tests/qemuxml2xmltest.c | 4 +++ 14 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml -- 1.7.12

Whenever the guest machine fails to boot, new parameter (reboot-timeout) controls whether it should reboot and after how many ms it should do so. Docs included. --- docs/formatdomain.html.in | 11 ++++++++--- docs/schemas/domaincommon.rng | 24 ++++++++++++++++++------ src/conf/domain_conf.c | 34 ++++++++++++++++++++++++++++------ src/conf/domain_conf.h | 3 +++ 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 51f897c..d021837 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -105,7 +105,7 @@ <boot dev='cdrom'/> <bootmenu enable='yes'/> <smbios mode='sysinfo'/> - <bios useserial='yes'/> + <bios useserial='yes' reboot-timeout='0'/> </os> ...</pre> @@ -175,8 +175,13 @@ Serial Graphics Adapter which allows users to see BIOS messages on a serial port. Therefore, one needs to have <a href="#elementCharSerial">serial port</a> defined. - <span class="since">Since 0.9.4</span> - </dd> + <span class="since">Since 0.9.4</span>. + <span class="since">Since 0.10.2 (QEMU only)</span> there is + another attribute, <code>reboot-timeout</code> that controls + whether and after how long the guest should start booting + again in case the boot fails (according to BIOS). The value is + in milliseconds with maximum of <code>65535</code> and special + value <code>-1</code> disables the reboot. </dl> <h4><a name="elementsOSBootloader">Host bootloader</a></h4> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index aafb10c..ed25f58 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3190,12 +3190,19 @@ <define name="bios"> <element name="bios"> - <attribute name="useserial"> - <choice> - <value>yes</value> - <value>no</value> - </choice> - </attribute> + <optional> + <attribute name="useserial"> + <choice> + <value>yes</value> + <value>no</value> + </choice> + </attribute> + </optional> + <optional> + <attribute name="reboot-timeout"> + <ref name="RebootTimeout"/> + </attribute> + </optional> </element> </define> @@ -3469,6 +3476,11 @@ <param name='minInclusive'>-1</param> </data> </define> + <define name="RebootTimeout"> + <data type="short"> + <param name="minInclusive">-1</param> + </data> + </define> <define name="PortNumber"> <data type="short"> <param name="minInclusive">-1</param> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 35814fb..4714312 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8136,7 +8136,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, { xmlNodePtr *nodes = NULL; int i, n; - char *bootstr; + char *bootstr, *tmp; char *useserial = NULL; int ret = -1; unsigned long deviceBoot, serialPorts; @@ -8214,6 +8214,22 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, } } + tmp = virXPathString("string(./os/bios[1]/@reboot-timeout)", ctxt); + if (tmp) { + /* that was really just for the check if it is there */ + VIR_FREE(tmp); + + if ((virXPathInt("string(./os/bios[1]/@reboot-timeout)", + ctxt, &def->os.bios.rt_delay) < 0) || + def->os.bios.rt_delay < -1 || def->os.bios.rt_delay > 65535) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("invalid value for reboot-timeout, " + "must be in range [-1,65535]")); + goto cleanup; + } + def->os.bios.rt_set = true; + } + *bootCount = deviceBoot; ret = 0; @@ -13494,11 +13510,17 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAsprintf(buf, " <bootmenu enable='%s'/>\n", enabled); } - if (def->os.bios.useserial) { - const char *useserial = (def->os.bios.useserial == - VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes" - : "no"); - virBufferAsprintf(buf, " <bios useserial='%s'/>\n", useserial); + if (def->os.bios.useserial || def->os.bios.rt_set) { + virBufferAddLit(buf, " <bios"); + if (def->os.bios.useserial) + virBufferAsprintf(buf, " useserial='%s'", + (def->os.bios.useserial == + VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes" + : "no")); + if (def->os.bios.rt_set) + virBufferAsprintf(buf, " reboot-timeout='%d'", def->os.bios.rt_delay); + + virBufferAddLit(buf, "/>\n"); } } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 510406a..d719d57 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1420,6 +1420,9 @@ typedef struct _virDomainBIOSDef virDomainBIOSDef; typedef virDomainBIOSDef *virDomainBIOSDefPtr; struct _virDomainBIOSDef { int useserial; + /* reboot-timeout parameters */ + bool rt_set; + int rt_delay; }; /* Operating system configuration data & machine / arch */ -- 1.7.12

On 09/19/12 19:22, Martin Kletzander wrote:
Whenever the guest machine fails to boot, new parameter (reboot-timeout) controls whether it should reboot and after how many ms it should do so.
Docs included. --- docs/formatdomain.html.in | 11 ++++++++--- docs/schemas/domaincommon.rng | 24 ++++++++++++++++++------ src/conf/domain_conf.c | 34 ++++++++++++++++++++++++++++------ src/conf/domain_conf.h | 3 +++ 4 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 51f897c..d021837 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -105,7 +105,7 @@ <boot dev='cdrom'/> <bootmenu enable='yes'/> <smbios mode='sysinfo'/> - <bios useserial='yes'/> + <bios useserial='yes' reboot-timeout='0'/> </os> ...</pre>
@@ -175,8 +175,13 @@ Serial Graphics Adapter which allows users to see BIOS messages on a serial port. Therefore, one needs to have <a href="#elementCharSerial">serial port</a> defined. - <span class="since">Since 0.9.4</span> - </dd> + <span class="since">Since 0.9.4</span>. + <span class="since">Since 0.10.2 (QEMU only)</span> there is + another attribute, <code>reboot-timeout</code> that controls + whether and after how long the guest should start booting + again in case the boot fails (according to BIOS). The value is + in milliseconds with maximum of <code>65535</code> and special + value <code>-1</code> disables the reboot. </dl>
<h4><a name="elementsOSBootloader">Host bootloader</a></h4> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index aafb10c..ed25f58 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3190,12 +3190,19 @@
<define name="bios"> <element name="bios"> - <attribute name="useserial"> - <choice> - <value>yes</value> - <value>no</value> - </choice> - </attribute> + <optional> + <attribute name="useserial"> + <choice> + <value>yes</value> + <value>no</value> + </choice> + </attribute> + </optional> + <optional> + <attribute name="reboot-timeout">
As DanPB pointed out, this should be changed to camel case.
+ <ref name="RebootTimeout"/> + </attribute> + </optional> </element> </define>
@@ -3469,6 +3476,11 @@ <param name='minInclusive'>-1</param> </data> </define> + <define name="RebootTimeout"> + <data type="short"> + <param name="minInclusive">-1</param> + </data> + </define> <define name="PortNumber"> <data type="short"> <param name="minInclusive">-1</param> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 35814fb..4714312 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8136,7 +8136,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, { xmlNodePtr *nodes = NULL; int i, n; - char *bootstr; + char *bootstr, *tmp; char *useserial = NULL; int ret = -1; unsigned long deviceBoot, serialPorts; @@ -8214,6 +8214,22 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, } }
+ tmp = virXPathString("string(./os/bios[1]/@reboot-timeout)", ctxt); + if (tmp) { + /* that was really just for the check if it is there */ + VIR_FREE(tmp); + + if ((virXPathInt("string(./os/bios[1]/@reboot-timeout)",
Ew. Doing the XPath query twice seems like a waste to me. What about using virStrToLong_i on the string instead of querying again?
+ ctxt, &def->os.bios.rt_delay) < 0) || + def->os.bios.rt_delay < -1 || def->os.bios.rt_delay > 65535) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("invalid value for reboot-timeout, " + "must be in range [-1,65535]")); + goto cleanup; + } + def->os.bios.rt_set = true; + } + *bootCount = deviceBoot; ret = 0;
@@ -13494,11 +13510,17 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAsprintf(buf, " <bootmenu enable='%s'/>\n", enabled); }
- if (def->os.bios.useserial) { - const char *useserial = (def->os.bios.useserial == - VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes" - : "no"); - virBufferAsprintf(buf, " <bios useserial='%s'/>\n", useserial); + if (def->os.bios.useserial || def->os.bios.rt_set) { + virBufferAddLit(buf, " <bios"); + if (def->os.bios.useserial) + virBufferAsprintf(buf, " useserial='%s'", + (def->os.bios.useserial == + VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes" + : "no")); + if (def->os.bios.rt_set) + virBufferAsprintf(buf, " reboot-timeout='%d'", def->os.bios.rt_delay); + + virBufferAddLit(buf, "/>\n"); } }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 510406a..d719d57 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1420,6 +1420,9 @@ typedef struct _virDomainBIOSDef virDomainBIOSDef; typedef virDomainBIOSDef *virDomainBIOSDefPtr; struct _virDomainBIOSDef { int useserial; + /* reboot-timeout parameters */ + bool rt_set; + int rt_delay; };
/* Operating system configuration data & machine / arch */
ACK if you don't do the xpath query twice and (carefully) rename the element. Peter

On 09/20/2012 11:54 AM, Peter Krempa wrote:
On 09/19/12 19:22, Martin Kletzander wrote:
Whenever the guest machine fails to boot, new parameter (reboot-timeout) controls whether it should reboot and after how many ms it should do so.
Docs included. --- docs/formatdomain.html.in | 11 ++++++++--- docs/schemas/domaincommon.rng | 24 ++++++++++++++++++------ src/conf/domain_conf.c | 34 ++++++++++++++++++++++++++++------ src/conf/domain_conf.h | 3 +++ 4 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 51f897c..d021837 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -105,7 +105,7 @@ <boot dev='cdrom'/> <bootmenu enable='yes'/> <smbios mode='sysinfo'/> - <bios useserial='yes'/> + <bios useserial='yes' reboot-timeout='0'/> </os> ...</pre>
@@ -175,8 +175,13 @@ Serial Graphics Adapter which allows users to see BIOS messages on a serial port. Therefore, one needs to have <a href="#elementCharSerial">serial port</a> defined. - <span class="since">Since 0.9.4</span> - </dd> + <span class="since">Since 0.9.4</span>. + <span class="since">Since 0.10.2 (QEMU only)</span> there is + another attribute, <code>reboot-timeout</code> that controls + whether and after how long the guest should start booting + again in case the boot fails (according to BIOS). The value is + in milliseconds with maximum of <code>65535</code> and special + value <code>-1</code> disables the reboot. </dl>
<h4><a name="elementsOSBootloader">Host bootloader</a></h4> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index aafb10c..ed25f58 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3190,12 +3190,19 @@
<define name="bios"> <element name="bios"> - <attribute name="useserial"> - <choice> - <value>yes</value> - <value>no</value> - </choice> - </attribute> + <optional> + <attribute name="useserial"> + <choice> + <value>yes</value> + <value>no</value> + </choice> + </attribute> + </optional> + <optional> + <attribute name="reboot-timeout">
As DanPB pointed out, this should be changed to camel case.
+ <ref name="RebootTimeout"/> + </attribute> + </optional> </element> </define>
@@ -3469,6 +3476,11 @@ <param name='minInclusive'>-1</param> </data> </define> + <define name="RebootTimeout"> + <data type="short"> + <param name="minInclusive">-1</param> + </data> + </define> <define name="PortNumber"> <data type="short"> <param name="minInclusive">-1</param> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 35814fb..4714312 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -8136,7 +8136,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, { xmlNodePtr *nodes = NULL; int i, n; - char *bootstr; + char *bootstr, *tmp; char *useserial = NULL; int ret = -1; unsigned long deviceBoot, serialPorts; @@ -8214,6 +8214,22 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, } }
+ tmp = virXPathString("string(./os/bios[1]/@reboot-timeout)", ctxt); + if (tmp) { + /* that was really just for the check if it is there */ + VIR_FREE(tmp); + + if ((virXPathInt("string(./os/bios[1]/@reboot-timeout)",
Ew. Doing the XPath query twice seems like a waste to me. What about using virStrToLong_i on the string instead of querying again?
+ ctxt, &def->os.bios.rt_delay) < 0) || + def->os.bios.rt_delay < -1 || def->os.bios.rt_delay > 65535) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("invalid value for reboot-timeout, " + "must be in range [-1,65535]")); + goto cleanup; + } + def->os.bios.rt_set = true; + } + *bootCount = deviceBoot; ret = 0;
@@ -13494,11 +13510,17 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAsprintf(buf, " <bootmenu enable='%s'/>\n", enabled); }
- if (def->os.bios.useserial) { - const char *useserial = (def->os.bios.useserial == - VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes" - : "no"); - virBufferAsprintf(buf, " <bios useserial='%s'/>\n", useserial); + if (def->os.bios.useserial || def->os.bios.rt_set) { + virBufferAddLit(buf, " <bios"); + if (def->os.bios.useserial) + virBufferAsprintf(buf, " useserial='%s'", + (def->os.bios.useserial == + VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes" + : "no")); + if (def->os.bios.rt_set) + virBufferAsprintf(buf, " reboot-timeout='%d'", def->os.bios.rt_delay); + + virBufferAddLit(buf, "/>\n"); } }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 510406a..d719d57 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1420,6 +1420,9 @@ typedef struct _virDomainBIOSDef virDomainBIOSDef; typedef virDomainBIOSDef *virDomainBIOSDefPtr; struct _virDomainBIOSDef { int useserial; + /* reboot-timeout parameters */ + bool rt_set; + int rt_delay; };
/* Operating system configuration data & machine / arch */
ACK if you don't do the xpath query twice and (carefully) rename the element.
Peter
I didn't realize the function does the same. It simplified the code a lot, I double checked that and pushed. Thanks. Martin

This patch adds support for "-boot reboot-timeout=rb_time" that is added in QEMU. --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 278b550..3582cbd 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -180,6 +180,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "ide-drive.wwn", "scsi-disk.wwn", "seccomp-sandbox", + + "reboot-timeout", /* 110 */ ); struct _qemuCaps { @@ -1191,6 +1193,8 @@ qemuCapsComputeCmdFlags(const char *help, qemuCapsSet(caps, QEMU_CAPS_NESTING); if (strstr(help, ",menu=on")) qemuCapsSet(caps, QEMU_CAPS_BOOT_MENU); + if (strstr(help, ",reboot-timeout=rb_time")) + qemuCapsSet(caps, QEMU_CAPS_REBOOT_TIMEOUT); if ((fsdev = strstr(help, "-fsdev"))) { qemuCapsSet(caps, QEMU_CAPS_FSDEV); if (strstr(fsdev, "readonly")) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 4da2a29..2201cb3 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -145,6 +145,7 @@ enum qemuCapsFlags { QEMU_CAPS_IDE_DRIVE_WWN = 107, /* Is ide-drive.wwn available? */ QEMU_CAPS_SCSI_DISK_WWN = 108, /* Is scsi-disk.wwn available? */ QEMU_CAPS_SECCOMP_SANDBOX = 109, /* -sandbox */ + QEMU_CAPS_REBOOT_TIMEOUT = 110, /* -boot reboot-timeout */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f8012ec..3807596 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4945,7 +4945,22 @@ qemuBuildCommandLine(virConnectPtr conn, VIR_WARN("bootmenu is enabled but not " "supported by this QEMU binary"); } + } + + if (def->os.bios.rt_set) { + if (!qemuCapsGet(caps, QEMU_CAPS_REBOOT_TIMEOUT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("reboot timeout is not supported " + "by this QEMU binary")); + goto error; + } + + if (boot_nparams++) + virBufferAddChar(&boot_buf, ','); + virBufferAsprintf(&boot_buf, + "reboot-timeout=%d", + def->os.bios.rt_delay); } if (boot_nparams > 0) { @@ -8271,6 +8286,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr = strchr(token, ','); + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 0, &num) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot parse reboot-timeout value")); + goto error; + } + if (num > 65535) + num = 65535; + def->os.bios.rt_delay = num; + def->os.bios.rt_set = true; } token = strchr(token, ','); /* This incrementation has to be done here in order to make it -- 1.7.12

On 09/19/12 19:22, Martin Kletzander wrote:
This patch adds support for "-boot reboot-timeout=rb_time" that is added in QEMU. --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 278b550..3582cbd 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -180,6 +180,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "ide-drive.wwn", "scsi-disk.wwn", "seccomp-sandbox", + + "reboot-timeout", /* 110 */ );
struct _qemuCaps { @@ -1191,6 +1193,8 @@ qemuCapsComputeCmdFlags(const char *help, qemuCapsSet(caps, QEMU_CAPS_NESTING); if (strstr(help, ",menu=on")) qemuCapsSet(caps, QEMU_CAPS_BOOT_MENU); + if (strstr(help, ",reboot-timeout=rb_time")) + qemuCapsSet(caps, QEMU_CAPS_REBOOT_TIMEOUT); if ((fsdev = strstr(help, "-fsdev"))) { qemuCapsSet(caps, QEMU_CAPS_FSDEV); if (strstr(fsdev, "readonly")) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 4da2a29..2201cb3 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -145,6 +145,7 @@ enum qemuCapsFlags { QEMU_CAPS_IDE_DRIVE_WWN = 107, /* Is ide-drive.wwn available? */ QEMU_CAPS_SCSI_DISK_WWN = 108, /* Is scsi-disk.wwn available? */ QEMU_CAPS_SECCOMP_SANDBOX = 109, /* -sandbox */ + QEMU_CAPS_REBOOT_TIMEOUT = 110, /* -boot reboot-timeout */
QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f8012ec..3807596 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4945,7 +4945,22 @@ qemuBuildCommandLine(virConnectPtr conn, VIR_WARN("bootmenu is enabled but not " "supported by this QEMU binary"); } + } + + if (def->os.bios.rt_set) { + if (!qemuCapsGet(caps, QEMU_CAPS_REBOOT_TIMEOUT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("reboot timeout is not supported " + "by this QEMU binary")); + goto error; + } + + if (boot_nparams++) + virBufferAddChar(&boot_buf, ',');
+ virBufferAsprintf(&boot_buf, + "reboot-timeout=%d", + def->os.bios.rt_delay); }
if (boot_nparams > 0) { @@ -8271,6 +8286,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr = strchr(token, ','); + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 0, &num) < 0) {
This doesn't seem ok. You assign endptr somewhere into the string and then virStrToLong_i rewrites it, but you never check the return value. I suppose you wanted to check if after the number is converted the next char is a comma. You need to do the check after virStrToLong_i.
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot parse reboot-timeout value")); + goto error; + } + if (num > 65535) + num = 65535; + def->os.bios.rt_delay = num; + def->os.bios.rt_set = true; } token = strchr(token, ','); /* This incrementation has to be done here in order to make it
ACK when you fix the checking for the comma. Peter

On 09/20/2012 12:22 PM, Peter Krempa wrote:
@@ -8271,6 +8286,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr = strchr(token, ','); + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 0, &num) < 0) {
This doesn't seem ok. You assign endptr somewhere into the string and then virStrToLong_i rewrites it, but you never check the return value. I suppose you wanted to check if after the number is converted the next char is a comma. You need to do the check after virStrToLong_i.
Yes, sorry for that, you're absolutely right. To be sure, is this alright? diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f8012ec..4821910 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8271,6 +8286,20 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr; + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 10, &num) < 0) || + endptr != strchr(token, ',') { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot parse reboot-timeout value")); + goto error; + } + if (num > 65535) + num = 65535; + def->os.bios.rt_delay = num; + def->os.bios.rt_set = true; } token = strchr(token, ','); /* This incrementation has to be done here in order to make it -- Martin

On 09/20/12 15:15, Martin Kletzander wrote:
On 09/20/2012 12:22 PM, Peter Krempa wrote:
@@ -8271,6 +8286,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr = strchr(token, ','); + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 0, &num) < 0) {
This doesn't seem ok. You assign endptr somewhere into the string and then virStrToLong_i rewrites it, but you never check the return value. I suppose you wanted to check if after the number is converted the next char is a comma. You need to do the check after virStrToLong_i.
Yes, sorry for that, you're absolutely right. To be sure, is this alright?
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f8012ec..4821910 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8271,6 +8286,20 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr; + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 10, &num) < 0) || + endptr != strchr(token, ',') { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot parse reboot-timeout value")); + goto error; + } + if (num > 65535) + num = 65535;
You should probably check for the lower bound too here.
+ def->os.bios.rt_delay = num; + def->os.bios.rt_set = true; } token = strchr(token, ','); /* This incrementation has to be done here in order to make it
ACK to this with the lower bound check. Peter

On 09/20/2012 03:32 PM, Peter Krempa wrote:
On 09/20/12 15:15, Martin Kletzander wrote:
On 09/20/2012 12:22 PM, Peter Krempa wrote:
@@ -8271,6 +8286,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr = strchr(token, ','); + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 0, &num) < 0) {
This doesn't seem ok. You assign endptr somewhere into the string and then virStrToLong_i rewrites it, but you never check the return value. I suppose you wanted to check if after the number is converted the next char is a comma. You need to do the check after virStrToLong_i.
Yes, sorry for that, you're absolutely right. To be sure, is this alright?
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f8012ec..4821910 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8271,6 +8286,20 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, qemuParseCommandLineBootDevs(def, token); } else if (STRPREFIX(token, "menu=on")) { def->os.bootmenu = 1; + } else if (STRPREFIX(token, "reboot-timeout=")) { + int num; + char *endptr; + if (virStrToLong_i(token + strlen("reboot-timeout="), + &endptr, 10, &num) < 0) || + endptr != strchr(token, ',') { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot parse reboot-timeout value")); + goto error; + } + if (num > 65535) + num = 65535;
You should probably check for the lower bound too here.
+ def->os.bios.rt_delay = num; + def->os.bios.rt_set = true; } token = strchr(token, ','); /* This incrementation has to be done here in order to make it
ACK to this with the lower bound check.
Peter
Thanks, fixed that and one more thing (the endptr may point to end of the string in which case that makes it valid, "thanks tests"), double checked and pushed. Martin

--- tests/qemuargv2xmltest.c | 4 ++++ .../qemuxml2argv-reboot-timeout-disabled.args | 3 +++ .../qemuxml2argv-reboot-timeout-disabled.xml | 21 +++++++++++++++++++++ .../qemuxml2argv-reboot-timeout-enabled.args | 3 +++ .../qemuxml2argv-reboot-timeout-enabled.xml | 21 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 5 +++++ tests/qemuxml2xmltest.c | 4 ++++ 7 files changed, 61 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index ad5f45b..c4c2cd9 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -151,6 +151,10 @@ mymain(void) /* Can't roundtrip xenner arch */ /*DO_TEST("bootloader");*/ + + DO_TEST("reboot-timeout-enabled"); + DO_TEST("reboot-timeout-disabled"); + DO_TEST("clock-utc"); DO_TEST("clock-localtime"); DO_TEST("disk-cdrom"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args new file mode 100644 index 0000000..1a2bf4d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args @@ -0,0 +1,3 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \ +-m 214 -smp 6 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot order=n,reboot-timeout=-1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml new file mode 100644 index 0000000..2aabb9e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml @@ -0,0 +1,21 @@ +<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'/> + <bios reboot-timeout='-1'/> + </os> + <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'/> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args new file mode 100644 index 0000000..ab18b30 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args @@ -0,0 +1,3 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \ +-m 214 -smp 6 -nographic -monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot order=n,reboot-timeout=128 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml new file mode 100644 index 0000000..100316a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml @@ -0,0 +1,21 @@ +<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'/> + <bios reboot-timeout='128'/> + </os> + <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'/> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 0ec3c2c..629d767 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -373,6 +373,11 @@ mymain(void) QEMU_CAPS_BOOTINDEX, QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SG_IO); DO_TEST("bootloader", QEMU_CAPS_DOMID, QEMU_CAPS_KVM); + + DO_TEST("reboot-timeout-disabled", QEMU_CAPS_REBOOT_TIMEOUT); + DO_TEST("reboot-timeout-enabled", QEMU_CAPS_REBOOT_TIMEOUT); + DO_TEST_FAILURE("reboot-timeout-enabled", NONE); + DO_TEST("bios", QEMU_CAPS_DEVICE, QEMU_CAPS_SGA); DO_TEST("clock-utc", NONE); DO_TEST("clock-localtime", NONE); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0a6da98..b968566 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -133,6 +133,10 @@ mymain(void) DO_TEST("boot-menu-disable"); DO_TEST("boot-order"); DO_TEST("bootloader"); + + DO_TEST("reboot-timeout-enabled"); + DO_TEST("reboot-timeout-disabled"); + DO_TEST("clock-utc"); DO_TEST("clock-localtime"); DO_TEST("cpu-kvmclock"); -- 1.7.12

On 09/19/12 19:22, Martin Kletzander wrote:
--- tests/qemuargv2xmltest.c | 4 ++++ .../qemuxml2argv-reboot-timeout-disabled.args | 3 +++ .../qemuxml2argv-reboot-timeout-disabled.xml | 21 +++++++++++++++++++++ .../qemuxml2argv-reboot-timeout-enabled.args | 3 +++ .../qemuxml2argv-reboot-timeout-enabled.xml | 21 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 5 +++++ tests/qemuxml2xmltest.c | 4 ++++ 7 files changed, 61 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml
Looks like nothing has changed so Michal's ACK stands. Peter

On 09/20/2012 11:59 AM, Peter Krempa wrote:
On 09/19/12 19:22, Martin Kletzander wrote:
--- tests/qemuargv2xmltest.c | 4 ++++ .../qemuxml2argv-reboot-timeout-disabled.args | 3 +++ .../qemuxml2argv-reboot-timeout-disabled.xml | 21 +++++++++++++++++++++ .../qemuxml2argv-reboot-timeout-enabled.args | 3 +++ .../qemuxml2argv-reboot-timeout-enabled.xml | 21 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 5 +++++ tests/qemuxml2xmltest.c | 4 ++++ 7 files changed, 61 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-disabled.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-reboot-timeout-enabled.xml
Looks like nothing has changed so Michal's ACK stands.
Peter
Thanks guys. Pushed. Martin
participants (2)
-
Martin Kletzander
-
Peter Krempa