diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index c1e99951a6..c132d2abbb 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2170,6 +2170,11 @@ 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 at startup of the domain. The ``start`` attribute takes 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 70562cc993..1167e06f09 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1172,6 +1172,7 @@ VIR_ENUM_IMPL(virDomainClockOffset, "localtime", "variable", "timezone", + "absolute", ); VIR_ENUM_IMPL(virDomainClockBasis, @@ -19459,6 +19460,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) @@ -26263,6 +26273,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 2e2da0c69c..4e9790b385 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2453,6 +2453,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; @@ -2487,6 +2488,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 2544864eb4..35c973c354 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -1252,6 +1252,14 @@ + + + absolute + + + + + diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index e5fe209718..a96dd09e80 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 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + +
+ + + + + + + + + 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 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + qemu64 + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + +
+ + +
+ + +
+ + + + +