mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
qemu: Introduce qemuBuildClockCommandLine
Add new function to manage adding the '-clock' options to the command line removing that task from the mainline qemuBuildCommandLine. Also includes some minor formatting cleanups. Signed-off-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
1e34a8f919
commit
05e9790802
@ -4753,6 +4753,7 @@ qemuBuildSgaCommandLine(virCommandPtr cmd,
|
|||||||
static char *
|
static char *
|
||||||
qemuBuildClockArgStr(virDomainClockDefPtr def)
|
qemuBuildClockArgStr(virDomainClockDefPtr def)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
switch (def->offset) {
|
switch (def->offset) {
|
||||||
@ -4817,8 +4818,8 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for an 'rtc' timer element, and add in appropriate clock= and driftfix= */
|
/* Look for an 'rtc' timer element, and add in appropriate
|
||||||
size_t i;
|
* clock= and driftfix= */
|
||||||
for (i = 0; i < def->ntimers; i++) {
|
for (i = 0; i < def->ntimers; i++) {
|
||||||
if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) {
|
if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) {
|
||||||
switch (def->timers[i]->track) {
|
switch (def->timers[i]->track) {
|
||||||
@ -4868,6 +4869,161 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: Building of commands can change def->clock->data.* values, so
|
||||||
|
* virDomainDef is not const here.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qemuBuildClockCommandLine(virCommandPtr cmd,
|
||||||
|
virDomainDefPtr def,
|
||||||
|
virQEMUCapsPtr qemuCaps)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_RTC)) {
|
||||||
|
char *rtcopt;
|
||||||
|
virCommandAddArg(cmd, "-rtc");
|
||||||
|
if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
|
||||||
|
return -1;
|
||||||
|
virCommandAddArg(cmd, rtcopt);
|
||||||
|
VIR_FREE(rtcopt);
|
||||||
|
} else {
|
||||||
|
switch (def->clock.offset) {
|
||||||
|
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
|
||||||
|
case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
|
||||||
|
virCommandAddArg(cmd, "-localtime");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
|
||||||
|
/* Nothing, its the default */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported clock offset '%s'"),
|
||||||
|
virDomainClockOffsetTypeToString(def->clock.offset));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
|
||||||
|
def->clock.data.timezone) {
|
||||||
|
virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < def->clock.ntimers; i++) {
|
||||||
|
switch ((virDomainTimerNameType) def->clock.timers[i]->name) {
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_TSC:
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported timer type (name) '%s'"),
|
||||||
|
virDomainTimerNameTypeToString(def->clock.timers[i]->name));
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
|
||||||
|
/* Timers above are handled when building -cpu. */
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_LAST:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_RTC:
|
||||||
|
/* This has already been taken care of (in qemuBuildClockArgStr)
|
||||||
|
if QEMU_CAPS_RTC is set (mutually exclusive with
|
||||||
|
QEMUD_FLAG_RTC_TD_HACK) */
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_RTC_TD_HACK)) {
|
||||||
|
switch (def->clock.timers[i]->tickpolicy) {
|
||||||
|
case -1:
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
|
||||||
|
/* the default - do nothing */
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
|
||||||
|
virCommandAddArg(cmd, "-rtc-td-hack");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported rtc tickpolicy '%s'"),
|
||||||
|
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_RTC) &&
|
||||||
|
(def->clock.timers[i]->tickpolicy
|
||||||
|
!= VIR_DOMAIN_TIMER_TICKPOLICY_DELAY) &&
|
||||||
|
(def->clock.timers[i]->tickpolicy != -1)) {
|
||||||
|
/* a non-default rtc policy was given, but there is no
|
||||||
|
way to implement it in this version of qemu */
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported rtc tickpolicy '%s'"),
|
||||||
|
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_PIT:
|
||||||
|
switch (def->clock.timers[i]->tickpolicy) {
|
||||||
|
case -1:
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
|
||||||
|
/* delay is the default if we don't have kernel
|
||||||
|
(-no-kvm-pit), otherwise, the default is catchup. */
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
|
||||||
|
virCommandAddArgList(cmd, "-global",
|
||||||
|
"kvm-pit.lost_tick_policy=discard", NULL);
|
||||||
|
else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_KVM_PIT))
|
||||||
|
virCommandAddArg(cmd, "-no-kvm-pit-reinjection");
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
|
||||||
|
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_KVM_PIT) ||
|
||||||
|
virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
|
||||||
|
/* do nothing - this is default for kvm-pit */
|
||||||
|
} else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_TDF)) {
|
||||||
|
/* -tdf switches to 'catchup' with userspace pit. */
|
||||||
|
virCommandAddArg(cmd, "-tdf");
|
||||||
|
} else {
|
||||||
|
/* can't catchup if we have neither pit mode */
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported pit tickpolicy '%s'"),
|
||||||
|
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
|
||||||
|
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
|
||||||
|
/* no way to support these modes for pit in qemu */
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported pit tickpolicy '%s'"),
|
||||||
|
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_HPET:
|
||||||
|
/* the only meaningful attribute for hpet is "present". If
|
||||||
|
* present is -1, that means it wasn't specified, and
|
||||||
|
* should be left at the default for the
|
||||||
|
* hypervisor. "default" when -no-hpet exists is "yes",
|
||||||
|
* and when -no-hpet doesn't exist is "no". "confusing"?
|
||||||
|
* "yes"! */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
|
qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
|
||||||
const virDomainDef *def,
|
const virDomainDef *def,
|
||||||
@ -7288,144 +7444,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
monitor_json) < 0)
|
monitor_json) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_RTC)) {
|
if (qemuBuildClockCommandLine(cmd, def, qemuCaps) < 0)
|
||||||
char *rtcopt;
|
goto error;
|
||||||
virCommandAddArg(cmd, "-rtc");
|
|
||||||
if (!(rtcopt = qemuBuildClockArgStr(&def->clock)))
|
|
||||||
goto error;
|
|
||||||
virCommandAddArg(cmd, rtcopt);
|
|
||||||
VIR_FREE(rtcopt);
|
|
||||||
} else {
|
|
||||||
switch (def->clock.offset) {
|
|
||||||
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
|
|
||||||
case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
|
|
||||||
virCommandAddArg(cmd, "-localtime");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
|
|
||||||
/* Nothing, its the default */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unsupported clock offset '%s'"),
|
|
||||||
virDomainClockOffsetTypeToString(def->clock.offset));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE &&
|
|
||||||
def->clock.data.timezone) {
|
|
||||||
virCommandAddEnvPair(cmd, "TZ", def->clock.data.timezone);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < def->clock.ntimers; i++) {
|
|
||||||
switch ((virDomainTimerNameType) def->clock.timers[i]->name) {
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_PLATFORM:
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_TSC:
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unsupported timer type (name) '%s'"),
|
|
||||||
virDomainTimerNameTypeToString(def->clock.timers[i]->name));
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK:
|
|
||||||
/* Timers above are handled when building -cpu. */
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_LAST:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_RTC:
|
|
||||||
/* This has already been taken care of (in qemuBuildClockArgStr)
|
|
||||||
if QEMU_CAPS_RTC is set (mutually exclusive with
|
|
||||||
QEMUD_FLAG_RTC_TD_HACK) */
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_RTC_TD_HACK)) {
|
|
||||||
switch (def->clock.timers[i]->tickpolicy) {
|
|
||||||
case -1:
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
|
|
||||||
/* the default - do nothing */
|
|
||||||
break;
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
|
|
||||||
virCommandAddArg(cmd, "-rtc-td-hack");
|
|
||||||
break;
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unsupported rtc tickpolicy '%s'"),
|
|
||||||
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_RTC) &&
|
|
||||||
(def->clock.timers[i]->tickpolicy
|
|
||||||
!= VIR_DOMAIN_TIMER_TICKPOLICY_DELAY) &&
|
|
||||||
(def->clock.timers[i]->tickpolicy != -1)) {
|
|
||||||
/* a non-default rtc policy was given, but there is no
|
|
||||||
way to implement it in this version of qemu */
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unsupported rtc tickpolicy '%s'"),
|
|
||||||
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_PIT:
|
|
||||||
switch (def->clock.timers[i]->tickpolicy) {
|
|
||||||
case -1:
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
|
|
||||||
/* delay is the default if we don't have kernel
|
|
||||||
(-no-kvm-pit), otherwise, the default is catchup. */
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY))
|
|
||||||
virCommandAddArgList(cmd, "-global",
|
|
||||||
"kvm-pit.lost_tick_policy=discard", NULL);
|
|
||||||
else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_KVM_PIT))
|
|
||||||
virCommandAddArg(cmd, "-no-kvm-pit-reinjection");
|
|
||||||
break;
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP:
|
|
||||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_KVM_PIT) ||
|
|
||||||
virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM_PIT_TICK_POLICY)) {
|
|
||||||
/* do nothing - this is default for kvm-pit */
|
|
||||||
} else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_TDF)) {
|
|
||||||
/* -tdf switches to 'catchup' with userspace pit. */
|
|
||||||
virCommandAddArg(cmd, "-tdf");
|
|
||||||
} else {
|
|
||||||
/* can't catchup if we have neither pit mode */
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unsupported pit tickpolicy '%s'"),
|
|
||||||
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_MERGE:
|
|
||||||
case VIR_DOMAIN_TIMER_TICKPOLICY_DISCARD:
|
|
||||||
/* no way to support these modes for pit in qemu */
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unsupported pit tickpolicy '%s'"),
|
|
||||||
virDomainTimerTickpolicyTypeToString(def->clock.timers[i]->tickpolicy));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_HPET:
|
|
||||||
/* the only meaningful attribute for hpet is "present". If
|
|
||||||
* present is -1, that means it wasn't specified, and
|
|
||||||
* should be left at the default for the
|
|
||||||
* hypervisor. "default" when -no-hpet exists is "yes",
|
|
||||||
* and when -no-hpet doesn't exist is "no". "confusing"?
|
|
||||||
* "yes"! */
|
|
||||||
|
|
||||||
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"));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only add -no-reboot option if each event destroys domain */
|
/* Only add -no-reboot option if each event destroys domain */
|
||||||
if (def->onReboot == VIR_DOMAIN_LIFECYCLE_DESTROY &&
|
if (def->onReboot == VIR_DOMAIN_LIFECYCLE_DESTROY &&
|
||||||
|
Loading…
Reference in New Issue
Block a user