From 200c83b29ddceaa4be045cafaff306620004c42b Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 2 Feb 2010 18:07:12 +0000 Subject: [PATCH] Support variable clock offset mode in QEMU This allows QEMU guests to be started with an arbitrary clock offset The test case can't actually be enabled, since QEMU argv expects an absolute timestring, and this will obviously change every time the test runs :-( Hopefully QEMU will allow a relative time offset in the future. * src/qemu/qemu_conf.c, src/qemu/qemu_conf.h: Use the -rtc arg if available to support variable clock offset mode * tests/qemuhelptest.c: Add QEMUD_CMD_FLAG_RTC for qemu 0.12.1 * qemuxml2argvdata/qemuxml2argv-clock-variable.args, qemuxml2argvdata/qemuxml2argv-clock-variable.xml, qemuxml2argvtest.c: Test case, except we can't actually enable it yet. --- src/qemu/qemu_conf.c | 82 +++++++++++++++++-- src/qemu/qemu_conf.h | 1 + tests/qemuhelptest.c | 3 +- .../qemuxml2argv-clock-variable.args | 1 + .../qemuxml2argv-clock-variable.xml | 24 ++++++ tests/qemuxml2argvtest.c | 4 + 6 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 8d5960e3e8..a6a9d75766 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1156,6 +1156,9 @@ static unsigned long long qemudComputeCmdFlags(const char *help, flags |= QEMUD_CMD_FLAG_BALLOON; if (strstr(help, "-device")) flags |= QEMUD_CMD_FLAG_DEVICE; + /* The trailing ' ' is important to avoid a bogus match */ + if (strstr(help, "-rtc ")) + flags |= QEMUD_CMD_FLAG_RTC; /* Keep disabled till we're actually ready to turn on netdev mode * The plan is todo it in 0.13.0 QEMU, but lets wait & see... */ #if 0 @@ -3057,6 +3060,56 @@ error: } +static char * +qemuBuildClockArgStr(virDomainClockDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + switch (def->offset) { + case VIR_DOMAIN_CLOCK_OFFSET_UTC: + virBufferAddLit(&buf, "base=utc"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + virBufferAddLit(&buf, "base=localtime"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: { + time_t now = time(NULL); + struct tm nowbits; + + now += def->data.adjustment; + gmtime_r(&now, &nowbits); + + virBufferVSprintf(&buf, "base=%d-%d-%dT%d:%d:%d", + nowbits.tm_year + 1900, + nowbits.tm_mon, + nowbits.tm_mday, + nowbits.tm_hour, + nowbits.tm_min, + nowbits.tm_sec); + } break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->offset)); + goto error; + } + + if (virBufferError(&buf)) { + virReportOOMError(); + goto error; + } + + return virBufferContentAndReset(&buf); + +error: + virBufferFreeAndReset(&buf); + return NULL; +} + + static int qemuBuildCpuArgStr(const struct qemud_driver *driver, const virDomainDefPtr def, @@ -3488,13 +3541,28 @@ int qemudBuildCommandLine(virConnectPtr conn, } } - if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) - ADD_ARG_LIT("-localtime"); - else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported clock offset '%s'"), - virDomainClockOffsetTypeToString(def->clock.offset)); - goto error; + if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC) { + const char *rtcopt; + ADD_ARG_LIT("-rtc"); + if (!(rtcopt = qemuBuildClockArgStr(&def->clock))) + goto error; + ADD_ARG(rtcopt); + } else { + switch (def->clock.offset) { + case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + ADD_ARG_LIT("-localtime"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_UTC: + /* Nothing, its the default */ + break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + } } if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index c8757c53a1..1821252d62 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -82,6 +82,7 @@ enum qemud_cmd_flags { QEMUD_CMD_FLAG_SDL = (1 << 27), /* Is the new -sdl arg available */ QEMUD_CMD_FLAG_SMP_TOPOLOGY = (1 << 28), /* Is sockets=s,cores=c,threads=t available for -smp? */ QEMUD_CMD_FLAG_NETDEV = (1 << 29), /* The -netdev flag & netdev_add/remove monitor commands */ + QEMUD_CMD_FLAG_RTC = (1 << 30), /* The -rtc flag for clock options */ }; /* Main driver state */ diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index ad355d7eb9..e61f4e2de7 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -226,7 +226,8 @@ mymain(int argc, char **argv) QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_BALLOON | QEMUD_CMD_FLAG_DEVICE | - QEMUD_CMD_FLAG_SMP_TOPOLOGY, + QEMUD_CMD_FLAG_SMP_TOPOLOGY | + QEMUD_CMD_FLAG_RTC, 12001, 0, 0); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args new file mode 100644 index 0000000000..09a91979e6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -rtc base=2010-2-2T18:22:10 -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml new file mode 100644 index 0000000000..fa20b27374 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml @@ -0,0 +1,24 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219200 + 219200 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index a8c9ed3ff0..6525daec94 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -226,6 +226,10 @@ mymain(int argc, char **argv) DO_TEST("bootloader", QEMUD_CMD_FLAG_DOMID); DO_TEST("clock-utc", 0); DO_TEST("clock-localtime", 0); + /* + * Can't be enabled since the absolute timestamp changes every time + DO_TEST("clock-variable", QEMUD_CMD_FLAG_RTC); + */ DO_TEST("hugepages", QEMUD_CMD_FLAG_MEM_PATH); DO_TEST("disk-cdrom", 0); DO_TEST("disk-cdrom-empty", QEMUD_CMD_FLAG_DRIVE);