提交 b9e2967a 编写于 作者: D Daniel P. Berrange

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.

  <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
上级 eed2f8c3
...@@ -297,12 +297,24 @@ ...@@ -297,12 +297,24 @@
<define name="clock"> <define name="clock">
<optional> <optional>
<element name="clock"> <element name="clock">
<attribute name="offset">
<choice> <choice>
<attribute name="offset">
<value>localtime</value> <value>localtime</value>
</attribute>
<attribute name="offset">
<value>utc</value> <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/> <empty/>
</element> </element>
</optional> </optional>
...@@ -1616,4 +1628,9 @@ ...@@ -1616,4 +1628,9 @@
<param name='pattern'>[a-zA-Z0-9\-_]+</param> <param name='pattern'>[a-zA-Z0-9\-_]+</param>
</data> </data>
</define> </define>
<define name="timeDelta">
<data type="string">
<param name="pattern">(-|\+)?[0-9]+</param>
</data>
</define>
</grammar> </grammar>
...@@ -234,7 +234,8 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST, ...@@ -234,7 +234,8 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST,
VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST, VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST,
"utc", "utc",
"localtime"); "localtime",
"variable");
#define virDomainReportError(code, fmt...) \ #define virDomainReportError(code, fmt...) \
virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \
...@@ -3580,6 +3581,13 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, ...@@ -3580,6 +3581,13 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
} else { } else {
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; 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.bootloader = virXPathString("string(./bootloader)", ctxt);
def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt); def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt);
...@@ -5535,8 +5543,14 @@ char *virDomainDefFormat(virDomainDefPtr def, ...@@ -5535,8 +5543,14 @@ char *virDomainDefFormat(virDomainDefPtr def,
if (virCPUDefFormatBuf(&buf, def->cpu, " ", 0) < 0) if (virCPUDefFormatBuf(&buf, def->cpu, " ", 0) < 0)
goto cleanup; goto cleanup;
virBufferVSprintf(&buf, " <clock offset='%s'/>\n", virBufferVSprintf(&buf, " <clock offset='%s'",
virDomainClockOffsetTypeToString(def->clock.offset)); 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, if (virDomainLifecycleDefFormat(&buf, def->onPoweroff,
"on_poweroff") < 0) "on_poweroff") < 0)
......
...@@ -634,6 +634,7 @@ struct _virSecurityLabelDef { ...@@ -634,6 +634,7 @@ struct _virSecurityLabelDef {
enum virDomainClockOffsetType { enum virDomainClockOffsetType {
VIR_DOMAIN_CLOCK_OFFSET_UTC = 0, VIR_DOMAIN_CLOCK_OFFSET_UTC = 0,
VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1, VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1,
VIR_DOMAIN_CLOCK_OFFSET_VARIABLE = 2,
VIR_DOMAIN_CLOCK_OFFSET_LAST, VIR_DOMAIN_CLOCK_OFFSET_LAST,
}; };
...@@ -642,6 +643,10 @@ typedef struct _virDomainClockDef virDomainClockDef; ...@@ -642,6 +643,10 @@ typedef struct _virDomainClockDef virDomainClockDef;
typedef virDomainClockDef *virDomainClockDefPtr; typedef virDomainClockDef *virDomainClockDefPtr;
struct _virDomainClockDef { struct _virDomainClockDef {
int offset; int offset;
/* Adjustment in seconds, relative to UTC, when
* offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */
long long adjustment;
}; };
#define VIR_DOMAIN_CPUMASK_LEN 1024 #define VIR_DOMAIN_CPUMASK_LEN 1024
......
...@@ -629,6 +629,7 @@ virXPathStringLimit; ...@@ -629,6 +629,7 @@ virXPathStringLimit;
virXPathBoolean; virXPathBoolean;
virXPathNumber; virXPathNumber;
virXPathULong; virXPathULong;
virXPathLongLong;
virXPathULongLong; virXPathULongLong;
virXPathLongHex; virXPathLongHex;
virXPathULongHex; virXPathULongHex;
...@@ -364,6 +364,60 @@ virXPathULongLong(const char *xpath, ...@@ -364,6 +364,60 @@ virXPathULongLong(const char *xpath,
return (ret); 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 * char *
virXMLPropString(xmlNodePtr node, virXMLPropString(xmlNodePtr node,
const char *name) const char *name)
......
...@@ -30,7 +30,10 @@ int virXPathULong(const char *xpath, ...@@ -30,7 +30,10 @@ int virXPathULong(const char *xpath,
int virXPathULongLong(const char *xpath, int virXPathULongLong(const char *xpath,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
unsigned long long *value); 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, xmlXPathContextPtr ctxt,
long *value); long *value);
int virXPathULongHex(const char *xpath, int virXPathULongHex(const char *xpath,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册