commit e4d7433ef0201bd5c5ce0ecaa2ca85a68ca48df6
Author: Daniel P. Berrange <berrange@redhat.com>
Date:   Tue Feb 2 18:28:44 2010 +0000

    Allow a timezone to be specified instead of sync to host timezone
    
    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

Index: libvirt-0.7.6/docs/schemas/domain.rng
===================================================================
--- libvirt-0.7.6.orig/docs/schemas/domain.rng
+++ libvirt-0.7.6/docs/schemas/domain.rng
@@ -306,6 +306,16 @@
           </attribute>
           <group>
             <attribute name="offset">
+              <value>timezone</value>
+            </attribute>
+            <optional>
+              <attribute name="timezone">
+                <ref name="timeZone"/>
+              </attribute>
+            </optional>
+          </group>
+          <group>
+            <attribute name="offset">
               <value>variable</value>
             </attribute>
             <optional>
@@ -1566,4 +1576,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>
Index: libvirt-0.7.6/src/conf/domain_conf.c
===================================================================
--- libvirt-0.7.6.orig/src/conf/domain_conf.c
+++ libvirt-0.7.6/src/conf/domain_conf.c
@@ -234,7 +234,8 @@ VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOM
 VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST,
               "utc",
               "localtime",
-              "variable");
+              "variable",
+              "timezone");
 
 #define virDomainReportError(conn, code, fmt...)                           \
         virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__,        \
@@ -648,6 +649,9 @@ void virDomainDefFree(virDomainDefPtr de
     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);
@@ -3510,8 +3514,17 @@ static virDomainDefPtr virDomainDefParse
     switch (def->clock.offset) {
     case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
         if (virXPathLongLong(conn, "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(conn, "string(./clock/@timezone)", ctxt);
+        if (!def->clock.data.timezone) {
+            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+                                 _("missing 'timezone' attribute for clock with offset='timezone'"));
+            goto error;
+        }
         break;
     }
 
@@ -5560,7 +5573,10 @@ char *virDomainDefFormat(virConnectPtr c
                       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");
Index: libvirt-0.7.6/src/conf/domain_conf.h
===================================================================
--- libvirt-0.7.6.orig/src/conf/domain_conf.h
+++ libvirt-0.7.6/src/conf/domain_conf.h
@@ -609,6 +609,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,
 };
@@ -618,9 +619,15 @@ typedef virDomainClockDef *virDomainCloc
 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
Index: libvirt-0.7.6/src/xen/xend_internal.c
===================================================================
--- libvirt-0.7.6.orig/src/xen/xend_internal.c
+++ libvirt-0.7.6/src/xen/xend_internal.c
@@ -5866,9 +5866,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));
Index: libvirt-0.7.6/src/xen/xm_internal.c
===================================================================
--- libvirt-0.7.6.orig/src/xen/xm_internal.c
+++ libvirt-0.7.6/src/xen/xm_internal.c
@@ -2330,13 +2330,20 @@ virConfPtr xenXMDomainConfigFormat(virCo
             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));
