diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 820729fa77..5a8c82be23 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -304,6 +304,16 @@
utc
+
+
+ timezone
+
+
+
+
+
+
+
variable
@@ -1633,4 +1643,9 @@
(-|\+)?[0-9]+
+
+
+ [a-zA-Z0-9_\.\+\-/]+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7820634046..df1ec18e2f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -235,7 +235,8 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST,
VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST,
"utc",
"localtime",
- "variable");
+ "variable",
+ "timezone");
#define virDomainReportError(code, fmt...) \
virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \
@@ -657,6 +658,9 @@ void virDomainDefFree(virDomainDefPtr def)
VIR_FREE(def->os.bootloader);
VIR_FREE(def->os.bootloaderArgs);
+ if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE)
+ VIR_FREE(def->clock.data.timezone);
+
VIR_FREE(def->name);
VIR_FREE(def->cpumask);
VIR_FREE(def->emulator);
@@ -3584,8 +3588,17 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
switch (def->clock.offset) {
case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
if (virXPathLongLong("number(./clock/@adjustment)", ctxt,
- &def->clock.adjustment) < 0)
- def->clock.adjustment = 0;
+ &def->clock.data.adjustment) < 0)
+ def->clock.data.adjustment = 0;
+ break;
+
+ case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
+ def->clock.data.timezone = virXPathString("string(./clock/@timezone)", ctxt);
+ if (!def->clock.data.timezone) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing 'timezone' attribute for clock with offset='timezone'"));
+ goto error;
+ }
break;
}
@@ -5547,7 +5560,10 @@ char *virDomainDefFormat(virDomainDefPtr def,
virDomainClockOffsetTypeToString(def->clock.offset));
switch (def->clock.offset) {
case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
- virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.adjustment);
+ virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.data.adjustment);
+ break;
+ case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
+ virBufferEscapeString(&buf, " timezone='%s'", def->clock.data.timezone);
break;
}
virBufferAddLit(&buf, "/>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e597ea8f7f..bb6b3aad18 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -635,6 +635,7 @@ enum virDomainClockOffsetType {
VIR_DOMAIN_CLOCK_OFFSET_UTC = 0,
VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1,
VIR_DOMAIN_CLOCK_OFFSET_VARIABLE = 2,
+ VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE = 3,
VIR_DOMAIN_CLOCK_OFFSET_LAST,
};
@@ -644,9 +645,15 @@ typedef virDomainClockDef *virDomainClockDefPtr;
struct _virDomainClockDef {
int offset;
- /* Adjustment in seconds, relative to UTC, when
- * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */
- long long adjustment;
+ union {
+ /* Adjustment in seconds, relative to UTC, when
+ * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */
+ long long adjustment;
+
+ /* Timezone name, when
+ * offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME */
+ char *timezone;
+ } data;
};
#define VIR_DOMAIN_CPUMASK_LEN 1024
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 860cd6a7e6..5f46e9f5be 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -5846,9 +5846,15 @@ xenDaemonFormatSxpr(virConnectPtr conn,
virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
/* Set localtime here for current XenD (both PV & HVM) */
- if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME)
+ if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
+ if (def->clock.data.timezone) {
+ virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED,
+ _("configurable timezones are not supported"));
+ goto error;
+ }
+
virBufferAddLit(&buf, "(localtime 1)");
- else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) {
+ } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) {
virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported clock offset '%s'"),
virDomainClockOffsetTypeToString(def->clock.offset));
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 4c2066698d..014cbfc16f 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -2328,13 +2328,20 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
goto no_memory;
- if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME ||
- def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) {
- if (xenXMConfigSetInt(conf, "localtime",
- def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME ?
- 1 : 0) < 0)
+ if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) {
+ if (def->clock.data.timezone) {
+ xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED,
+ _("configurable timezones are not supported"));
+ goto cleanup;
+ }
+
+ if (xenXMConfigSetInt(conf, "localtime", 1) < 0)
+ goto no_memory;
+ } else if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) {
+ if (xenXMConfigSetInt(conf, "localtime", 0) < 0)
goto no_memory;
} else {
+ /* XXX We could support Xen's rtc clock offset */
xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported clock offset '%s'"),
virDomainClockOffsetTypeToString(def->clock.offset));