[RFC PATCH 0/2] Introduce 'absolute' clock offset

Based on https://listman.redhat.com/archives/libvirt-users/2022-April/013537.html Looked as a very simple addition. Peter Krempa (2): conf: Introduce 'absolute' clock offset qemu: Implement 'absolute' clock offset mode docs/formatdomain.rst | 4 ++ src/conf/domain_conf.c | 13 +++++++ src/conf/domain_conf.h | 4 ++ src/conf/schemas/domaincommon.rng | 8 ++++ src/libxl/libxl_conf.c | 1 + src/qemu/qemu_command.c | 10 ++++- .../clock-absolute.x86_64-latest.args | 36 ++++++++++++++++++ tests/qemuxml2argvdata/clock-absolute.xml | 30 +++++++++++++++ tests/qemuxml2argvtest.c | 1 + .../clock-absolute.x86_64-latest.xml | 38 +++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 11 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/clock-absolute.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/clock-absolute.xml create mode 100644 tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml -- 2.35.1

The 'absolute' clock offset type has a 'start' attribute which is an unix epoch timestamp to which the hardware clock is always set at start of the VM. This is useful if some VM needs to be kept set to an arbitrary time for e.g. testing or working around broken software. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/formatdomain.rst | 4 ++ src/conf/domain_conf.c | 13 +++++++ src/conf/domain_conf.h | 4 ++ src/conf/schemas/domaincommon.rng | 8 ++++ src/libxl/libxl_conf.c | 1 + tests/qemuxml2argvdata/clock-absolute.xml | 30 +++++++++++++++ .../clock-absolute.x86_64-latest.xml | 38 +++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 8 files changed, 99 insertions(+) create mode 100644 tests/qemuxml2argvdata/clock-absolute.xml create mode 100644 tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 9be305f3e6..5639a3014b 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2170,6 +2170,10 @@ Windows, however, expects it to be in so called 'localtime'. the RTC adjustments are lost at each reboot. :since:`Since 0.7.7` :since:`Since 0.9.11` the ``basis`` attribute can be either 'utc' (default) or 'localtime'. + ``absolute`` + The guest clock will be always set to the value of the ``start`` + attribute. The ``start`` attribute takes the an epoch timestamp. + :since:`Since 8.4.0`. A ``clock`` may have zero or more ``timer`` sub-elements. :since:`Since 0.8.0` diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bd2884088c..d0c88e6d7f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1171,6 +1171,7 @@ VIR_ENUM_IMPL(virDomainClockOffset, "localtime", "variable", "timezone", + "absolute", ); VIR_ENUM_IMPL(virDomainClockBasis, @@ -19412,6 +19413,15 @@ virDomainDefClockParse(virDomainDef *def, return -1; } break; + + case VIR_DOMAIN_CLOCK_OFFSET_ABSOLUTE: + if (virXPathULongLong("number(./clock/@start)", ctxt, + &def->clock.data.starttime) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing 'start' attribute for clock with offset='absolute'")); + return -1; + } + break; } if ((n = virXPathNodeSet("./clock/timer", ctxt, &nodes)) < 0) @@ -26202,6 +26212,9 @@ virDomainClockDefFormat(virBuffer *buf, case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: virBufferEscapeString(&clockAttr, " timezone='%s'", def->data.timezone); break; + case VIR_DOMAIN_CLOCK_OFFSET_ABSOLUTE: + virBufferAsprintf(&clockAttr, " start='%llu'", def->data.starttime); + break; } for (n = 0; n < def->ntimers; n++) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 88a411d00c..3bdf4b51b1 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2449,6 +2449,7 @@ typedef enum { VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1, VIR_DOMAIN_CLOCK_OFFSET_VARIABLE = 2, VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE = 3, + VIR_DOMAIN_CLOCK_OFFSET_ABSOLUTE = 4, VIR_DOMAIN_CLOCK_OFFSET_LAST } virDomainClockOffsetType; @@ -2483,6 +2484,9 @@ struct _virDomainClockDef { /* Timezone name, when * offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME */ char *timezone; + + /* absolute clock start time for VIR_DOMAIN_CLOCK_OFFSET_ABSOLUTE */ + unsigned long long starttime; } data; size_t ntimers; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 8afb0dadd4..d0c9ea7973 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -1252,6 +1252,14 @@ </attribute> </optional> </group> + <group> + <attribute name="offset"> + <value>absolute</value> + </attribute> + <attribute name="start"> + <ref name="unsignedInt"/> + </attribute> + </group> </choice> <zeroOrMore> <ref name="timer"/> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 6398129195..a0d4ba51ba 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -391,6 +391,7 @@ libxlMakeDomBuildInfo(virDomainDef *def, virDomainClockOffsetTypeToString(clock.offset)); return -1; + case VIR_DOMAIN_CLOCK_OFFSET_ABSOLUTE: case VIR_DOMAIN_CLOCK_OFFSET_LAST: default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, diff --git a/tests/qemuxml2argvdata/clock-absolute.xml b/tests/qemuxml2argvdata/clock-absolute.xml new file mode 100644 index 0000000000..e79f53ed3c --- /dev/null +++ b/tests/qemuxml2argvdata/clock-absolute.xml @@ -0,0 +1,30 @@ +<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'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='absolute' start='1234'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml b/tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml new file mode 100644 index 0000000000..b313a74039 --- /dev/null +++ b/tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml @@ -0,0 +1,38 @@ +<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'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='absolute' start='1234'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 58ee29cd33..ea524685b2 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -274,6 +274,7 @@ mymain(void) DO_TEST_NOCAPS("clock-timer-hyperv-rtc"); DO_TEST_CAPS_ARCH_LATEST("clock-timer-armvtimer", "aarch64"); DO_TEST_NOCAPS("clock-realtime"); + DO_TEST_CAPS_LATEST("clock-absolute"); DO_TEST_NOCAPS("cpu-eoi-disabled"); DO_TEST_NOCAPS("cpu-eoi-enabled"); -- 2.35.1

On Tue, Apr 26, 2022 at 05:34:21PM +0200, Peter Krempa wrote:
The 'absolute' clock offset type has a 'start' attribute which is an unix epoch timestamp to which the hardware clock is always set at start of the VM.
This is useful if some VM needs to be kept set to an arbitrary time for e.g. testing or working around broken software.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/formatdomain.rst | 4 ++ src/conf/domain_conf.c | 13 +++++++ src/conf/domain_conf.h | 4 ++ src/conf/schemas/domaincommon.rng | 8 ++++ src/libxl/libxl_conf.c | 1 + tests/qemuxml2argvdata/clock-absolute.xml | 30 +++++++++++++++ .../clock-absolute.x86_64-latest.xml | 38 +++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 8 files changed, 99 insertions(+) create mode 100644 tests/qemuxml2argvdata/clock-absolute.xml create mode 100644 tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 9be305f3e6..5639a3014b 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2170,6 +2170,10 @@ Windows, however, expects it to be in so called 'localtime'. the RTC adjustments are lost at each reboot. :since:`Since 0.7.7` :since:`Since 0.9.11` the ``basis`` attribute can be either 'utc' (default) or 'localtime'. + ``absolute`` + The guest clock will be always set to the value of the ``start`` + attribute. The ``start`` attribute takes the an epoch timestamp.
s/the an/an/
+ :since:`Since 8.4.0`.
A ``clock`` may have zero or more ``timer`` sub-elements. :since:`Since 0.8.0`

Add support for the mode and add the corresponding qemuxml2argv test case. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 10 +++++- .../clock-absolute.x86_64-latest.args | 36 +++++++++++++++++++ tests/qemuxml2argvtest.c | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/clock-absolute.x86_64-latest.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3746f02ff0..11dda52270 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6120,7 +6120,7 @@ qemuBuildClockArgStr(virDomainClockDef *def) size_t i; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; - switch (def->offset) { + switch ((virDomainClockOffsetType) def->offset) { case VIR_DOMAIN_CLOCK_OFFSET_UTC: virBufferAddLit(&buf, "base=utc"); break; @@ -6170,6 +6170,14 @@ qemuBuildClockArgStr(virDomainClockDef *def) virBufferAsprintf(&buf, "base=%s", thenstr); } break; + case VIR_DOMAIN_CLOCK_OFFSET_ABSOLUTE: { + g_autoptr(GDateTime) then = g_date_time_new_from_unix_utc(def->data.starttime); + g_autofree char *thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S"); + + virBufferAsprintf(&buf, "base=%s", thenstr); + } break; + + case VIR_DOMAIN_CLOCK_OFFSET_LAST: default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported clock offset '%s'"), diff --git a/tests/qemuxml2argvdata/clock-absolute.x86_64-latest.args b/tests/qemuxml2argvdata/clock-absolute.x86_64-latest.args new file mode 100644 index 0000000000..75fc162cee --- /dev/null +++ b/tests/qemuxml2argvdata/clock-absolute.x86_64-latest.args @@ -0,0 +1,36 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-accel tcg \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=1970-01-01T00:20:34 \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 1f080daba7..34d068a873 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1217,6 +1217,7 @@ mymain(void) DO_TEST("kvmclock", QEMU_CAPS_KVM); DO_TEST("clock-timer-hyperv-rtc", QEMU_CAPS_KVM); DO_TEST_NOCAPS("clock-realtime"); + DO_TEST_CAPS_LATEST("clock-absolute"); DO_TEST_CAPS_LATEST("controller-usb-order"); -- 2.35.1

On 4/26/22 17:34, Peter Krempa wrote:
Based on https://listman.redhat.com/archives/libvirt-users/2022-April/013537.html
Looked as a very simple addition.
Peter Krempa (2): conf: Introduce 'absolute' clock offset qemu: Implement 'absolute' clock offset mode
docs/formatdomain.rst | 4 ++ src/conf/domain_conf.c | 13 +++++++ src/conf/domain_conf.h | 4 ++ src/conf/schemas/domaincommon.rng | 8 ++++ src/libxl/libxl_conf.c | 1 + src/qemu/qemu_command.c | 10 ++++- .../clock-absolute.x86_64-latest.args | 36 ++++++++++++++++++ tests/qemuxml2argvdata/clock-absolute.xml | 30 +++++++++++++++ tests/qemuxml2argvtest.c | 1 + .../clock-absolute.x86_64-latest.xml | 38 +++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 11 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/clock-absolute.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/clock-absolute.xml create mode 100644 tests/qemuxml2xmloutdata/clock-absolute.x86_64-latest.xml
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (3)
-
Michal Prívozník
-
Pavel Hrdina
-
Peter Krempa