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));