]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add new clock mode allowing variable adjustments
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 2 Feb 2010 17:49:09 +0000 (17:49 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 1 Mar 2010 18:36:01 +0000 (18:36 +0000)
This introduces a third option for clock offset synchronization,
that allows an arbitrary / variable adjustment to be set. In
essence the XML contains the time delta in seconds, relative to
UTC.

  <clock offset='variable' adjustment='123465'/>

The difference from 'utc' mode, is that management apps should
track adjustments and preserve them at next reboot.

* docs/schemas/domain.rng: Schema for new clock mode
* src/conf/domain_conf.c, src/conf/domain_conf.h: Parse
  new clock time delta
* src/libvirt_private.syms, src/util/xml.c, src/util/xml.h: Add
  virXPathLongLong() method

docs/schemas/domain.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/util/xml.c
src/util/xml.h

index 0fc8fc0b78d960f7bc39860c61eaa43474c7863a..820729fa77a6c8b27bf1c4621b477113ee5c63a8 100644 (file)
   <define name="clock">
     <optional>
       <element name="clock">
-        <attribute name="offset">
-          <choice>
+        <choice>
+          <attribute name="offset">
             <value>localtime</value>
+          </attribute>
+          <attribute name="offset">
             <value>utc</value>
-          </choice>
-        </attribute>
+          </attribute>
+          <group>
+            <attribute name="offset">
+              <value>variable</value>
+            </attribute>
+            <optional>
+              <attribute name="adjustment">
+                <ref name="timeDelta"/>
+              </attribute>
+            </optional>
+          </group>
+        </choice>
         <empty/>
       </element>
     </optional>
       <param name='pattern'>[a-zA-Z0-9\-_]+</param>
     </data>
   </define>
+  <define name="timeDelta">
+    <data type="string">
+      <param name="pattern">(-|\+)?[0-9]+</param>
+    </data>
+  </define>
 </grammar>
index 8a36fd8e37c4685e7c1866862acddb209cd3fdba..7820634046000c1aa5ed6de894c5b233fc34e410 100644 (file)
@@ -234,7 +234,8 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST,
 
 VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST,
               "utc",
-              "localtime");
+              "localtime",
+              "variable");
 
 #define virDomainReportError(code, fmt...)                           \
     virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__,      \
@@ -3580,6 +3581,13 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
     } else {
         def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
     }
+    switch (def->clock.offset) {
+    case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
+        if (virXPathLongLong("number(./clock/@adjustment)", ctxt,
+                             &def->clock.adjustment) < 0)
+            def->clock.adjustment = 0;
+        break;
+    }
 
     def->os.bootloader = virXPathString("string(./bootloader)", ctxt);
     def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt);
@@ -5535,8 +5543,14 @@ char *virDomainDefFormat(virDomainDefPtr def,
     if (virCPUDefFormatBuf(&buf, def->cpu, "  ", 0) < 0)
         goto cleanup;
 
-    virBufferVSprintf(&buf, "  <clock offset='%s'/>\n",
+    virBufferVSprintf(&buf, "  <clock offset='%s'",
                       virDomainClockOffsetTypeToString(def->clock.offset));
+    switch (def->clock.offset) {
+    case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
+        virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.adjustment);
+        break;
+    }
+    virBufferAddLit(&buf, "/>\n");
 
     if (virDomainLifecycleDefFormat(&buf, def->onPoweroff,
                                     "on_poweroff") < 0)
index 7ef99d6f0a10c1815da0c87bc506764c3722396f..e597ea8f7f898dfc41296d792ea72e51ad2e5463 100644 (file)
@@ -634,6 +634,7 @@ struct _virSecurityLabelDef {
 enum virDomainClockOffsetType {
     VIR_DOMAIN_CLOCK_OFFSET_UTC = 0,
     VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1,
+    VIR_DOMAIN_CLOCK_OFFSET_VARIABLE = 2,
 
     VIR_DOMAIN_CLOCK_OFFSET_LAST,
 };
@@ -642,6 +643,10 @@ typedef struct _virDomainClockDef virDomainClockDef;
 typedef virDomainClockDef *virDomainClockDefPtr;
 struct _virDomainClockDef {
     int offset;
+
+    /* Adjustment in seconds, relative to UTC, when
+     * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */
+    long long adjustment;
 };
 
 #define VIR_DOMAIN_CPUMASK_LEN 1024
index 5b3fc71d840eb8f5aaba28e24bcf86eb99fb6d04..ce9f01373f4949ad0ccbcdaea90836b909e0ce55 100644 (file)
@@ -629,6 +629,7 @@ virXPathStringLimit;
 virXPathBoolean;
 virXPathNumber;
 virXPathULong;
+virXPathLongLong;
 virXPathULongLong;
 virXPathLongHex;
 virXPathULongHex;
index 46ea9aa27b90a54fd8933f58c3a17360fa916563..14c83453b1eee81e9af25550e26dff32dd7091f3 100644 (file)
@@ -364,6 +364,60 @@ virXPathULongLong(const char *xpath,
     return (ret);
 }
 
+/**
+ * virXPathULongLong:
+ * @xpath: the XPath string to evaluate
+ * @ctxt: an XPath context
+ * @value: the returned long long value
+ *
+ * Convenience function to evaluate an XPath number
+ *
+ * Returns 0 in case of success in which case @value is set,
+ *         or -1 if the XPath evaluation failed or -2 if the
+ *         value doesn't have a long format.
+ */
+int
+virXPathLongLong(const char *xpath,
+                 xmlXPathContextPtr ctxt,
+                 long long *value)
+{
+    xmlXPathObjectPtr obj;
+    xmlNodePtr relnode;
+    int ret = 0;
+
+    if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
+        virXMLError(VIR_ERR_INTERNAL_ERROR,
+                    "%s", _("Invalid parameter to virXPathLongLong()"));
+        return (-1);
+    }
+    relnode = ctxt->node;
+    obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+    ctxt->node = relnode;
+    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
+        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
+        char *conv = NULL;
+        unsigned long long val;
+
+        val = strtoll((const char *) obj->stringval, &conv, 10);
+        if (conv == (const char *) obj->stringval) {
+            ret = -2;
+        } else {
+            *value = val;
+        }
+    } else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
+               (!(isnan(obj->floatval)))) {
+        *value = (long long) obj->floatval;
+        if (*value != obj->floatval) {
+            ret = -2;
+        }
+    } else {
+        ret = -1;
+    }
+
+    xmlXPathFreeObject(obj);
+    return (ret);
+}
+
 char *
 virXMLPropString(xmlNodePtr node,
                  const char *name)
index 246672da2a28c980af1c976f76e5d31002b0f86f..af721bbb8bc95978b307542b1f94db5bbeefe876 100644 (file)
@@ -30,7 +30,10 @@ int                 virXPathULong(const char *xpath,
 int            virXPathULongLong(const char *xpath,
                                  xmlXPathContextPtr ctxt,
                                  unsigned long long *value);
-int              virXPathLongHex(const char *xpath,
+int            virXPathLongLong(const char *xpath,
+                                 xmlXPathContextPtr ctxt,
+                                 long long *value);
+int            virXPathLongHex (const char *xpath,
                                  xmlXPathContextPtr ctxt,
                                  long *value);
 int             virXPathULongHex(const char *xpath,