On Thu, Feb 18, 2010 at 05:54:28PM +0000, Daniel P. Berrange wrote:
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.
hum ... if the management layer start to track time of delta w.r.t.
UTC as defined by node clock, I also assume they manage the variations
in clock when migrating too (or that the nodes clocks are actually
properly sync'ed).
* 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">
hum isn't that inserting tabs in the XML that we remove from time to
time :-) ?
<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">
actually we could use XSD integer there
http://www.w3.org/TR/xmlschema-2/#integer
but this won't change much
+ <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;
Hum, should probably give an error message here
+ 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
ACK
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/