mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
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
This commit is contained in:
parent
eed2f8c3a9
commit
b9e2967a5e
@ -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 @@
|
|||||||
<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,
|
|||||||
|
|
||||||
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,
|
|||||||
} 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,
|
|||||||
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 {
|
|||||||
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;
|
|||||||
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;
|
|||||||
virXPathBoolean;
|
virXPathBoolean;
|
||||||
virXPathNumber;
|
virXPathNumber;
|
||||||
virXPathULong;
|
virXPathULong;
|
||||||
|
virXPathLongLong;
|
||||||
virXPathULongLong;
|
virXPathULongLong;
|
||||||
virXPathLongHex;
|
virXPathLongHex;
|
||||||
virXPathULongHex;
|
virXPathULongHex;
|
||||||
|
@ -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,
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user