From b9e2967a5ecbad6fd5d62e6e7a951cb4b50426a6 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 2 Feb 2010 17:49:09 +0000 Subject: [PATCH] Add new clock mode allowing variable adjustments 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. 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 0fc8fc0b78..820729fa77 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -297,12 +297,24 @@ - - + + localtime + + utc - - + + + + variable + + + + + + + + @@ -1616,4 +1628,9 @@ [a-zA-Z0-9\-_]+ + + + (-|\+)?[0-9]+ + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8a36fd8e37..7820634046 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -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, " \n", + virBufferVSprintf(&buf, " 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 7ef99d6f0a..e597ea8f7f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -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 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5b3fc71d84..ce9f01373f 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 46ea9aa27b..14c83453b1 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 246672da2a..af721bbb8b 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, -- GitLab