[libvirt] [PATCH 2/6] Add new clock mode allowing variable adjustments

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


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  |   25 +++++++++++++++++---
 src/conf/domain_conf.c   |   18 +++++++++++++-
 src/conf/domain_conf.h   |    5 ++++
 src/libvirt_private.syms |    1 +
 src/util/xml.c           |   54 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/xml.h           |    5 +++-
 6 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 1ff0944..d295bfe 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -297,12 +297,24 @@
   <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>
@@ -1567,4 +1579,9 @@
       <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>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f86b4eb..49d5d19 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -231,7 +231,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__,      \
@@ -3492,6 +3493,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("./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);
@@ -5399,8 +5407,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)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fbbe683..f5fe016 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -612,6 +612,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,
 };
@@ -620,6 +621,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
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1af34bd..41bde8e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -629,6 +629,7 @@ virXPathStringLimit;
 virXPathBoolean;
 virXPathNumber;
 virXPathULong;
+virXPathLongLong;
 virXPathULongLong;
 virXPathLongHex;
 virXPathULongHex;
diff --git a/src/util/xml.c b/src/util/xml.c
index 46ea9aa..14c8345 100644
--- a/src/util/xml.c
+++ b/src/util/xml.c
@@ -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)
diff --git a/src/util/xml.h b/src/util/xml.h
index 246672d..af721bb 100644
--- a/src/util/xml.h
+++ b/src/util/xml.h
@@ -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,
-- 
1.6.6




More information about the libvir-list mailing list