[libvirt] [PATCH 4/6] Allow a timezone to be specified instead of sync to host timezone

Daniel P. Berrange berrange at redhat.com
Thu Feb 18 17:54:30 UTC 2010


This extends the XML to allow for

  <clock offset='timezone' timezone='Europe/Paris'/>

This is useful if the admin has not configured any timezone on the
host OS, but still wants to synchronize a guest to a specific one.

* src/conf/domain_conf.h, src/conf/domain_conf.c: Support extra
  'timezone' attribute on clock configuration
* docs/schemas/domain.rng: Add 'timezone' attribute
* src/xen/xend_internal.c, src/xen/xm_internal.c: Reject configs
  with a configurable timezone
---
 docs/schemas/domain.rng |   18 +++++++++++++++---
 src/conf/domain_conf.c  |   24 ++++++++++++++++++++----
 src/conf/domain_conf.h  |   13 ++++++++++---
 src/qemu/qemu_conf.c    |    2 +-
 src/xen/xend_internal.c |   10 ++++++++--
 src/xen/xm_internal.c   |   17 ++++++++++++-----
 6 files changed, 66 insertions(+), 18 deletions(-)

diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index d295bfe..4a36a97 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -298,9 +298,16 @@
     <optional>
       <element name="clock">
 	<choice>
-          <attribute name="offset">
-            <value>localtime</value>
-	  </attribute>
+	  <group>
+            <attribute name="offset">
+              <value>localtime</value>
+	    </attribute>
+	    <optional>
+	      <attribute name="timezone">
+		<ref name="timeZone"/>
+	      </attribute>
+	    </optional>
+	  </group>
           <attribute name="offset">
             <value>utc</value>
 	  </attribute>
@@ -1584,4 +1591,9 @@
       <param name="pattern">(-|\+)?[0-9]+</param>
     </data>
   </define>
+  <define name="timeZone">
+    <data type="string">
+      <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param>
+    </data>
+  </define>
 </grammar>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 49d5d19..ed5d9fd 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -232,7 +232,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__,      \
@@ -650,6 +651,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);
@@ -3496,8 +3500,17 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
     switch (def->clock.offset) {
     case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
         if (virXPathLongLong("./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;
     }
 
@@ -5411,7 +5424,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 f5fe016..1dcfaa5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -613,6 +613,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,
 };
@@ -622,9 +623,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/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 112a7c2..cd0dd7f 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2990,7 +2990,7 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
         time_t now = time(NULL);
         struct tm nowbits;
 
-        now += def->adjustment;
+        now += def->data.adjustment;
         gmtime_r(&now, &nowbits);
 
         virBufferVSprintf(&buf, "base=%d-%d-%dT%d:%d:%d",
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index c88ea64..3a14d91 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 4c20666..014cbfc 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));
-- 
1.6.6




More information about the libvir-list mailing list