@def->clock validation is done by qemuBuildClockCommandLine() and
qemuBuildClockArgStr(). This patch centralize the validation done
in both these functions to a new qemuDomainDefValidateClockTimers()
function. This new function is then called by qemuDomainDefValidate(),
promoting clock validation in domain define time.
Tests were adapted to consider the new caps being needed in
this earlier stage.
Signed-off-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
---
src/qemu/qemu_command.c | 35 ++------------
src/qemu/qemu_domain.c | 100 ++++++++++++++++++++++++++++++++++++++++
tests/qemuxml2xmltest.c | 2 +-
3 files changed, 106 insertions(+), 31 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fe5333efdf..13abee9a42 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6111,9 +6111,6 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
case -1: /* unspecified - use hypervisor default */
break;
case VIR_DOMAIN_TIMER_TRACK_BOOT:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported rtc timer track '%s'"),
-
virDomainTimerTrackTypeToString(def->timers[i]->track));
return NULL;
case VIR_DOMAIN_TIMER_TRACK_GUEST:
virBufferAddLit(&buf, ",clock=vm");
@@ -6135,9 +6132,6 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported rtc timer tickpolicy
'%s'"),
-
virDomainTimerTickpolicyTypeToString(def->timers[i]->tickpolicy));
return NULL;
}
break; /* no need to check other timers - there is only one rtc */
@@ -6172,9 +6166,8 @@ qemuBuildClockCommandLine(virCommandPtr cmd,
for (i = 0; i < def->clock.ntimers; i++) {
switch ((virDomainTimerNameType)def->clock.timers[i]->name) {
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported timer type (name) '%s'"),
-
virDomainTimerNameTypeToString(def->clock.timers[i]->name));
+ /* qemuDomainDefValidateClockTimers will handle this
+ * error condition */
return -1;
case VIR_DOMAIN_TIMER_NAME_TSC:
@@ -6185,7 +6178,7 @@ qemuBuildClockCommandLine(virCommandPtr cmd,
break;
case VIR_DOMAIN_TIMER_NAME_RTC:
- /* Already handled in qemuBuildClockArgStr */
+ /* Already handled in qemuDomainDefValidateClockTimers */
break;
case VIR_DOMAIN_TIMER_NAME_PIT:
@@ -6199,15 +6192,8 @@ qemuBuildClockCommandLine(virCommandPtr cmd,
"kvm-pit.lost_tick_policy=delay",
NULL);
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
- /* do nothing - this is default for kvm-pit */
- } else {
- /* can't catchup if we don't have kvm-pit */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported pit tickpolicy
'%s'"),
-
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
- return -1;
- }
+ /* Do nothing - qemuDomainDefValidateClockTimers handled
+ * the possible error condition here. */
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
@@ -6216,9 +6202,6 @@ qemuBuildClockCommandLine(virCommandPtr cmd,
break;
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
/* no way to support this mode for pit in qemu */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported pit tickpolicy '%s'"),
-
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
return -1;
}
break;
@@ -6234,14 +6217,6 @@ qemuBuildClockCommandLine(virCommandPtr cmd,
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET)) {
if (def->clock.timers[i]->present == 0)
virCommandAddArg(cmd, "-no-hpet");
- } else {
- /* no hpet timer available. The only possible action
- is to raise an error if present="yes" */
- if (def->clock.timers[i]->present == 1) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("hpet timer is not
supported"));
- return -1;
- }
}
break;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 94bb4e4fca..4715976b1b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5320,6 +5320,103 @@ qemuDomainDeviceDefValidateHub(virDomainHubDefPtr hub,
}
+static int
+qemuDomainDefValidateClockTimers(const virDomainDef *def,
+ virQEMUCapsPtr qemuCaps)
+{
+ size_t i;
+
+ for (i = 0; i < def->clock.ntimers; i++) {
+ virDomainTimerDefPtr timer = def->clock.timers[i];
+
+ switch ((virDomainTimerNameType)timer->name) {
+ case VIR_DOMAIN_TIMER_NAME_PLATFORM:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported timer type (name) '%s'"),
+ virDomainTimerNameTypeToString(timer->name));
+ return -1;
+
+ case VIR_DOMAIN_TIMER_NAME_TSC:
+ case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
+ case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
+ case VIR_DOMAIN_TIMER_NAME_LAST:
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_RTC:
+ switch (timer->track) {
+ case -1: /* unspecified - use hypervisor default */
+ case VIR_DOMAIN_TIMER_TRACK_GUEST:
+ case VIR_DOMAIN_TIMER_TRACK_WALL:
+ break;
+ case VIR_DOMAIN_TIMER_TRACK_BOOT:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported rtc timer track '%s'"),
+ virDomainTimerTrackTypeToString(timer->track));
+ return -1;
+ }
+
+ switch (timer->tickpolicy) {
+ case -1:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
+ /* This is the default - missed ticks delivered when
+ next scheduled, at normal rate */
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
+ /* deliver ticks at a faster rate until caught up */
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported rtc timer tickpolicy
'%s'"),
+ virDomainTimerTickpolicyTypeToString(
+ timer->tickpolicy));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_PIT:
+ switch (timer->tickpolicy) {
+ case -1:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
+ case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
+ /* can't catchup if we don't have kvm-pit */
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported pit tickpolicy
'%s'"),
+ virDomainTimerTickpolicyTypeToString(
+ timer->tickpolicy));
+ return -1;
+ }
+ break;
+ case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
+ /* no way to support this mode for pit in qemu */
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported pit tickpolicy '%s'"),
+ virDomainTimerTickpolicyTypeToString(
+ timer->tickpolicy));
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_TIMER_NAME_HPET:
+ /* no hpet timer available. The only possible action
+ is to raise an error if present="yes" */
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_HPET) &&
+ timer->present == 1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("hpet timer is not
supported"));
+ return -1;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
static int
qemuDomainDefValidate(const virDomainDef *def,
void *opaque)
@@ -5412,6 +5509,9 @@ qemuDomainDefValidate(const virDomainDef *def,
}
}
+ if (qemuDomainDefValidateClockTimers(def, qemuCaps) < 0)
+ goto cleanup;
+
/* QEMU 2.7 (detected via the availability of query-hotpluggable-cpus)
* enforces stricter rules than previous versions when it comes to guest
* CPU topology. Verify known constraints are respected */
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index bd505ff157..0fa8582dd5 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -266,7 +266,7 @@ mymain(void)
DO_TEST("cpu-host-kvmclock", NONE);
DO_TEST("cpu-host-passthrough-features", NONE);
DO_TEST("cpu-host-model-features", NONE);
- DO_TEST("clock-catchup", NONE);
+ DO_TEST("clock-catchup", QEMU_CAPS_KVM_PIT_TICK_POLICY);
DO_TEST("kvmclock", NONE);
DO_TEST("clock-timer-hyperv-rtc", NONE);
--
2.23.0