[libvirt] [PATCH 0/6] Add more guest clock mods

An update of http://www.redhat.com/archives/libvir-list/2010-February/msg00104.html The two current options are: <clock offset='utc'/> <clock offset='localtime'/> This introduces a way to set a specific timezone <clock offset='timezone' timezone='Europe/Paris'/> And a way to set a completely arbitrary time, by giving the number of seconds offset from UTC. <clock offset='variable' adjustment='123456'/> Since last time, I removed the 'timezone' attribute from the existing offset='localtime' option, and introduced the new explicit option offset='timezone'. That way we don't change semantics of the existing options at all.

The XML will soon be extended to allow more than just a simple localtime/utc boolean flag. This change replaces the plain 'int localtime' with a separate struct to prepare for future extension * src/conf/domain_conf.c, src/conf/domain_conf.h: Add a new virDomainClockDef structure * src/libvirt_private.syms: Export virDomainClockOffsetTypeToString and virDomainClockOffsetTypeFromString * src/qemu/qemu_conf.c, src/vbox/vbox_tmpl.c, src/xen/xend_internal.c, src/xen/xm_internal.c: Updated to use new structure for localtime --- src/conf/domain_conf.c | 19 +++++++++++++++---- src/conf/domain_conf.h | 16 +++++++++++++++- src/libvirt_private.syms | 2 ++ src/qemu/qemu_conf.c | 11 +++++++++-- src/vbox/vbox_tmpl.c | 2 +- src/xen/xend_internal.c | 16 +++++++++++----- src/xen/xm_internal.c | 21 ++++++++++++++++++--- 7 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 561fa22..f86b4eb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -229,6 +229,10 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST, "private", "bridge") +VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST, + "utc", + "localtime"); + #define virDomainReportError(code, fmt...) \ virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) @@ -3478,9 +3482,16 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, tmp = virXPathString("string(./clock/@offset)", ctxt); - if (tmp && STREQ(tmp, "localtime")) - def->localtime = 1; - VIR_FREE(tmp); + if (tmp) { + if ((def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown clock offset '%s'"), tmp); + goto error; + } + VIR_FREE(tmp); + } else { + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; + } def->os.bootloader = virXPathString("string(./bootloader)", ctxt); def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt); @@ -5389,7 +5400,7 @@ char *virDomainDefFormat(virDomainDefPtr def, goto cleanup; virBufferVSprintf(&buf, " <clock offset='%s'/>\n", - def->localtime ? "localtime" : "utc"); + virDomainClockOffsetTypeToString(def->clock.offset)); if (virDomainLifecycleDefFormat(&buf, def->onPoweroff, "on_poweroff") < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 231d8c8..fbbe683 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -609,6 +609,19 @@ struct _virSecurityLabelDef { int type; }; +enum virDomainClockOffsetType { + VIR_DOMAIN_CLOCK_OFFSET_UTC = 0, + VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1, + + VIR_DOMAIN_CLOCK_OFFSET_LAST, +}; + +typedef struct _virDomainClockDef virDomainClockDef; +typedef virDomainClockDef *virDomainClockDefPtr; +struct _virDomainClockDef { + int offset; +}; + #define VIR_DOMAIN_CPUMASK_LEN 1024 /* Guest VM main configuration */ @@ -637,7 +650,7 @@ struct _virDomainDef { char *emulator; int features; - int localtime; + virDomainClockDef clock; int ngraphics; virDomainGraphicsDefPtr *graphics; @@ -911,6 +924,7 @@ VIR_ENUM_DECL(virDomainGraphics) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainSeclabel) +VIR_ENUM_DECL(virDomainClockOffset) VIR_ENUM_DECL(virDomainNetdevMacvtap) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index aa826d6..1af34bd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -190,6 +190,8 @@ virDomainDefAddDiskControllers; virDomainDefClearPCIAddresses; virDomainDefClearDeviceAliases; virDomainDeviceInfoIterate; +virDomainClockOffsetTypeToString; +virDomainClockOffsetTypeFromString; # domain_event.h diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index c9fe55b..a207fc7 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -3400,8 +3400,14 @@ int qemudBuildCommandLine(virConnectPtr conn, } } - if (def->localtime) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) ADD_ARG_LIT("-localtime"); + else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + } if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART) @@ -5218,6 +5224,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, def->id = -1; def->memory = def->maxmem = 64 * 1024; def->vcpus = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; def->features = (1 << VIR_DOMAIN_FEATURE_ACPI) /*| (1 << VIR_DOMAIN_FEATURE_APIC)*/; def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART; @@ -5397,7 +5404,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, } else if (STREQ(arg, "-full-screen")) { fullscreen = 1; } else if (STREQ(arg, "-localtime")) { - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; } else if (STREQ(arg, "-kernel")) { WANT_VALUE(); if (!(def->os.kernel = strdup(val))) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8a9af52..c414fb8 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -2051,7 +2051,7 @@ static char *vboxDomainDumpXML(virDomainPtr dom, int flags) { /* Currently VirtualBox always uses locatime * so locatime is always true here */ - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; /* dump video options vram/2d/3d/directx/etc. */ { diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 88923c8..c88ea64 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -2451,7 +2451,7 @@ xenDaemonParseSxpr(virConnectPtr conn, } else def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY; - + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; if (hvm) { if (sexpr_int(root, "domain/image/hvm/acpi")) def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI); @@ -2462,12 +2462,12 @@ xenDaemonParseSxpr(virConnectPtr conn, /* Old XenD only allows localtime here for HVM */ if (sexpr_int(root, "domain/image/hvm/localtime")) - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; } /* Current XenD allows localtime here, for PV and HVM */ if (sexpr_int(root, "domain/localtime")) - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; if (sexpr_node_copy(root, hvm ? "domain/image/hvm/device_model" : @@ -5846,8 +5846,14 @@ xenDaemonFormatSxpr(virConnectPtr conn, virBufferVSprintf(&buf, "(on_crash '%s')", tmp); /* Set localtime here for current XenD (both PV & HVM) */ - if (def->localtime) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) virBufferAddLit(&buf, "(localtime 1)"); + else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { + virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + } if (!def->os.bootloader) { if (STREQ(def->os.type, "hvm")) @@ -5965,7 +5971,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, } /* Set localtime here to keep old XenD happy for HVM */ - if (def->localtime) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) virBufferAddLit(&buf, "(localtime 1)"); if (def->sounds) { diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 8d48eda..4c20666 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -683,6 +683,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { virDomainHostdevDefPtr hostdev = NULL; int i; const char *defaultArch, *defaultMachine; + int vmlocaltime = 0; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -830,9 +831,13 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { else if (val) def->features |= (1 << VIR_DOMAIN_FEATURE_APIC); } - if (xenXMConfigGetBool(conn, conf, "localtime", &def->localtime, 0) < 0) + if (xenXMConfigGetBool(conn, conf, "localtime", &vmlocaltime, 0) < 0) goto cleanup; + def->clock.offset = vmlocaltime ? + VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME : + VIR_DOMAIN_CLOCK_OFFSET_UTC; + if (xenXMConfigCopyStringOpt(conn, conf, "device_model", &def->emulator) < 0) goto cleanup; @@ -2323,8 +2328,18 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, goto no_memory; - if (xenXMConfigSetInt(conf, "localtime", def->localtime ? 1 : 0) < 0) - goto no_memory; + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME || + def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) { + if (xenXMConfigSetInt(conf, "localtime", + def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME ? + 1 : 0) < 0) + goto no_memory; + } else { + xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto cleanup; + } if (priv->xendConfigVersion == 1) { for (i = 0 ; i < def->ndisks ; i++) { -- 1.6.6

On Thu, Feb 18, 2010 at 05:54:27PM +0000, Daniel P. Berrange wrote:
The XML will soon be extended to allow more than just a simple localtime/utc boolean flag. This change replaces the plain 'int localtime' with a separate struct to prepare for future extension
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add a new virDomainClockDef structure * src/libvirt_private.syms: Export virDomainClockOffsetTypeToString and virDomainClockOffsetTypeFromString * src/qemu/qemu_conf.c, src/vbox/vbox_tmpl.c, src/xen/xend_internal.c, src/xen/xm_internal.c: Updated to use new structure for localtime --- src/conf/domain_conf.c | 19 +++++++++++++++---- src/conf/domain_conf.h | 16 +++++++++++++++- src/libvirt_private.syms | 2 ++ src/qemu/qemu_conf.c | 11 +++++++++-- src/vbox/vbox_tmpl.c | 2 +- src/xen/xend_internal.c | 16 +++++++++++----- src/xen/xm_internal.c | 21 ++++++++++++++++++--- 7 files changed, 71 insertions(+), 16 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 561fa22..f86b4eb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -229,6 +229,10 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST, "private", "bridge")
+VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST, + "utc", + "localtime"); + #define virDomainReportError(code, fmt...) \ virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) @@ -3478,9 +3482,16 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
tmp = virXPathString("string(./clock/@offset)", ctxt); - if (tmp && STREQ(tmp, "localtime")) - def->localtime = 1; - VIR_FREE(tmp); + if (tmp) { + if ((def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown clock offset '%s'"), tmp); + goto error; + } + VIR_FREE(tmp); + } else { + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; + }
def->os.bootloader = virXPathString("string(./bootloader)", ctxt); def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt); @@ -5389,7 +5400,7 @@ char *virDomainDefFormat(virDomainDefPtr def, goto cleanup;
virBufferVSprintf(&buf, " <clock offset='%s'/>\n", - def->localtime ? "localtime" : "utc"); + virDomainClockOffsetTypeToString(def->clock.offset));
if (virDomainLifecycleDefFormat(&buf, def->onPoweroff, "on_poweroff") < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 231d8c8..fbbe683 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -609,6 +609,19 @@ struct _virSecurityLabelDef { int type; };
+enum virDomainClockOffsetType { + VIR_DOMAIN_CLOCK_OFFSET_UTC = 0, + VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1, + + VIR_DOMAIN_CLOCK_OFFSET_LAST, +}; + +typedef struct _virDomainClockDef virDomainClockDef; +typedef virDomainClockDef *virDomainClockDefPtr; +struct _virDomainClockDef { + int offset; +}; + #define VIR_DOMAIN_CPUMASK_LEN 1024
/* Guest VM main configuration */ @@ -637,7 +650,7 @@ struct _virDomainDef { char *emulator; int features;
- int localtime; + virDomainClockDef clock;
int ngraphics; virDomainGraphicsDefPtr *graphics; @@ -911,6 +924,7 @@ VIR_ENUM_DECL(virDomainGraphics) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainSeclabel) +VIR_ENUM_DECL(virDomainClockOffset)
VIR_ENUM_DECL(virDomainNetdevMacvtap)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index aa826d6..1af34bd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -190,6 +190,8 @@ virDomainDefAddDiskControllers; virDomainDefClearPCIAddresses; virDomainDefClearDeviceAliases; virDomainDeviceInfoIterate; +virDomainClockOffsetTypeToString; +virDomainClockOffsetTypeFromString;
# domain_event.h diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index c9fe55b..a207fc7 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -3400,8 +3400,14 @@ int qemudBuildCommandLine(virConnectPtr conn, } }
- if (def->localtime) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) ADD_ARG_LIT("-localtime"); + else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + }
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART) @@ -5218,6 +5224,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, def->id = -1; def->memory = def->maxmem = 64 * 1024; def->vcpus = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; def->features = (1 << VIR_DOMAIN_FEATURE_ACPI) /*| (1 << VIR_DOMAIN_FEATURE_APIC)*/; def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART; @@ -5397,7 +5404,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, } else if (STREQ(arg, "-full-screen")) { fullscreen = 1; } else if (STREQ(arg, "-localtime")) { - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; } else if (STREQ(arg, "-kernel")) { WANT_VALUE(); if (!(def->os.kernel = strdup(val))) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8a9af52..c414fb8 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -2051,7 +2051,7 @@ static char *vboxDomainDumpXML(virDomainPtr dom, int flags) {
/* Currently VirtualBox always uses locatime * so locatime is always true here */ - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
/* dump video options vram/2d/3d/directx/etc. */ { diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 88923c8..c88ea64 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -2451,7 +2451,7 @@ xenDaemonParseSxpr(virConnectPtr conn, } else def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
- + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; if (hvm) { if (sexpr_int(root, "domain/image/hvm/acpi")) def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI); @@ -2462,12 +2462,12 @@ xenDaemonParseSxpr(virConnectPtr conn,
/* Old XenD only allows localtime here for HVM */ if (sexpr_int(root, "domain/image/hvm/localtime")) - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; }
/* Current XenD allows localtime here, for PV and HVM */ if (sexpr_int(root, "domain/localtime")) - def->localtime = 1; + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
if (sexpr_node_copy(root, hvm ? "domain/image/hvm/device_model" : @@ -5846,8 +5846,14 @@ xenDaemonFormatSxpr(virConnectPtr conn, virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
/* Set localtime here for current XenD (both PV & HVM) */ - if (def->localtime) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) virBufferAddLit(&buf, "(localtime 1)"); + else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { + virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + }
if (!def->os.bootloader) { if (STREQ(def->os.type, "hvm")) @@ -5965,7 +5971,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, }
/* Set localtime here to keep old XenD happy for HVM */ - if (def->localtime) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) virBufferAddLit(&buf, "(localtime 1)");
if (def->sounds) { diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 8d48eda..4c20666 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -683,6 +683,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { virDomainHostdevDefPtr hostdev = NULL; int i; const char *defaultArch, *defaultMachine; + int vmlocaltime = 0;
if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -830,9 +831,13 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { else if (val) def->features |= (1 << VIR_DOMAIN_FEATURE_APIC); } - if (xenXMConfigGetBool(conn, conf, "localtime", &def->localtime, 0) < 0) + if (xenXMConfigGetBool(conn, conf, "localtime", &vmlocaltime, 0) < 0) goto cleanup;
+ def->clock.offset = vmlocaltime ? + VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME : + VIR_DOMAIN_CLOCK_OFFSET_UTC; + if (xenXMConfigCopyStringOpt(conn, conf, "device_model", &def->emulator) < 0) goto cleanup;
@@ -2323,8 +2328,18 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, goto no_memory;
- if (xenXMConfigSetInt(conf, "localtime", def->localtime ? 1 : 0) < 0) - goto no_memory; + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME || + def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) { + if (xenXMConfigSetInt(conf, "localtime", + def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME ? + 1 : 0) < 0) + goto no_memory; + } else { + xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto cleanup; + }
if (priv->xendConfigVersion == 1) { for (i = 0 ; i < def->ndisks ; i++) {
Okay, def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC is the old equivalent of def->localtime == 0 i.e. the default, ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

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

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@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Mon, Mar 01, 2010 at 03:02:06PM +0100, Daniel Veillard wrote:
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).
libvirt would be responsible for doing the right thing during migration - its only the persistent config on disk that apps are responsible for.
* 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 :-) ?
Hmm, our syntax-check only seems to validate no-TABS for source code files, not schemas/docs
<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 -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Daniel P. Berrange wrote: ...
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 :-) ?
Hmm, our syntax-check only seems to validate no-TABS for source code files, not schemas/docs
Here's the change to the syntax-check rule, followed by the change to the code to make those files comply. If everyone agrees, I'll reverse the order before pushing, so that make syntax-check passes after each commit.
From a5a73e3ec03deed1e411b05e3e32ef4194acbf16 Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyering@redhat.com> Date: Mon, 1 Mar 2010 20:05:06 +0100 Subject: [PATCH 1/2] maint: disallow TAB-in-indentation also in *.rng files
* cfg.mk (sc_TAB_in_indentation): Also check .rng files. --- cfg.mk | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/cfg.mk b/cfg.mk index 8317ae2..680c312 100644 --- a/cfg.mk +++ b/cfg.mk @@ -132,7 +132,7 @@ sc_prohibit_ctype_h: sc_TAB_in_indentation: @grep -lE '^ * ' /dev/null \ $$($(VC_LIST_EXCEPT) \ - | grep -E '\.[ch](\.in)?$$' \ + | grep -E '\.(rng|[ch](\.in)?)$$' \ | grep -v '^gnulib/') && \ { echo '$(ME): found TAB(s) used for indentation in C sources;'\ 'use spaces' 1>&2; exit 1; } || : -- 1.7.0.1.414.g89213d
From 87e8002f2f18a0295f2c2dd7c39c5e937585ffea Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyering@redhat.com> Date: Mon, 1 Mar 2010 20:09:26 +0100 Subject: [PATCH 2/2] maint: convert leading TABs in *.rng files to equivalent spaces
* docs/schemas/capability.rng: Likewise. * docs/schemas/network.rng: Likewise. * docs/schemas/nodedev.rng: Likewise. * docs/schemas/storagepool.rng: Likewise. * docs/schemas/storagevol.rng: Likewise. Use these commands: t=$'\t' git ls-files | grep '\.rng$' | xargs grep -lE "^ *$t" \ | xargs perl -MText::Tabs -ni -le \ '$m=/^( *\t[ \t]*)(.*)/; print $m ? expand($1) . $2 : $_' --- docs/schemas/capability.rng | 188 +++++++++++++++++++++--------------------- docs/schemas/network.rng | 16 ++-- docs/schemas/nodedev.rng | 94 +++++++++++----------- docs/schemas/storagepool.rng | 172 +++++++++++++++++++------------------- docs/schemas/storagevol.rng | 88 ++++++++++---------- 5 files changed, 279 insertions(+), 279 deletions(-) diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng index 378652e..eb3c50a 100644 --- a/docs/schemas/capability.rng +++ b/docs/schemas/capability.rng @@ -11,7 +11,7 @@ <ref name='hostcaps'/> <zeroOrMore> - <ref name='guestcaps'/> + <ref name='guestcaps'/> </zeroOrMore> </element> </define> @@ -19,24 +19,24 @@ <define name='hostcaps'> <element name='host'> <element name='cpu'> - <element name='arch'> - <ref name='archnames'/> - </element> - <optional> - <ref name='cpufeatures'/> - </optional> - <optional> - <ref name='cpuspec'/> - </optional> + <element name='arch'> + <ref name='archnames'/> + </element> + <optional> + <ref name='cpufeatures'/> + </optional> + <optional> + <ref name='cpuspec'/> + </optional> </element> <optional> - <ref name='migration'/> + <ref name='migration'/> </optional> <optional> - <ref name='topology'/> + <ref name='topology'/> </optional> <optional> - <ref name='secmodel'/> + <ref name='secmodel'/> </optional> </element> </define> @@ -56,16 +56,16 @@ <define name='cpufeatures'> <element name='features'> <optional> - <element name='pae'><empty/></element> + <element name='pae'><empty/></element> </optional> <optional> - <element name='nonpae'><empty/></element> + <element name='nonpae'><empty/></element> </optional> <optional> - <element name='vmx'><empty/></element> + <element name='vmx'><empty/></element> </optional> <optional> - <element name='svm'><empty/></element> + <element name='svm'><empty/></element> </optional> </element> </define> @@ -98,22 +98,22 @@ <define name='migration'> <element name='migration_features'> <optional> - <element name='live'> - <empty/> - </element> + <element name='live'> + <empty/> + </element> </optional> <optional> - <element name='uri_transports'> - <oneOrMore> - <element name='uri_transport'> - <choice> - <value>esx</value> - <value>tcp</value> - <value>xenmigr</value> - </choice> - </element> - </oneOrMore> - </element> + <element name='uri_transports'> + <oneOrMore> + <element name='uri_transport'> + <choice> + <value>esx</value> + <value>tcp</value> + <value>xenmigr</value> + </choice> + </element> + </oneOrMore> + </element> </optional> </element> </define> @@ -121,12 +121,12 @@ <define name='topology'> <element name='topology'> <element name='cells'> - <attribute name='num'> - <ref name='uint'/> - </attribute> - <oneOrMore> - <ref name='cell'/> - </oneOrMore> + <attribute name='num'> + <ref name='uint'/> + </attribute> + <oneOrMore> + <ref name='cell'/> + </oneOrMore> </element> </element> </define> @@ -134,18 +134,18 @@ <define name='cell'> <element name='cell'> <attribute name='id'> - <ref name='uint'/> + <ref name='uint'/> </attribute> <optional> - <element name='cpus'> - <attribute name='num'> - <ref name='uint'/> - </attribute> - <oneOrMore> - <ref name='cpu'/> - </oneOrMore> - </element> + <element name='cpus'> + <attribute name='num'> + <ref name='uint'/> + </attribute> + <oneOrMore> + <ref name='cpu'/> + </oneOrMore> + </element> </optional> </element> </define> @@ -153,7 +153,7 @@ <define name='cpu'> <element name='cpu'> <attribute name='id'> - <ref name='uint'/> + <ref name='uint'/> </attribute> </element> </define> @@ -163,7 +163,7 @@ <ref name='ostype'/> <ref name='arch'/> <optional> - <ref name='features'/> + <ref name='features'/> </optional> </element> </define> @@ -171,11 +171,11 @@ <define name='ostype'> <element name='os_type'> <choice> - <value>xen</value> <!-- Xen 3.0 pv --> - <value>linux</value> <!-- same as 'xen' - legacy --> - <value>hvm</value> <!-- unmodified OS --> - <value>exe</value> <!-- For container based virt --> - <value>uml</value> <!-- user mode linux --> + <value>xen</value> <!-- Xen 3.0 pv --> + <value>linux</value> <!-- same as 'xen' - legacy --> + <value>hvm</value> <!-- unmodified OS --> + <value>exe</value> <!-- For container based virt --> + <value>uml</value> <!-- user mode linux --> </choice> </element> </define> @@ -183,20 +183,20 @@ <define name='arch'> <element name='arch'> <attribute name='name'> - <ref name='archnames'/> + <ref name='archnames'/> </attribute> <ref name='wordsize'/> <optional> - <ref name='emulator'/> + <ref name='emulator'/> </optional> <optional> - <ref name='loader'/> + <ref name='loader'/> </optional> <zeroOrMore> - <ref name='machine'/> + <ref name='machine'/> </zeroOrMore> <oneOrMore> - <ref name='domain'/> + <ref name='domain'/> </oneOrMore> </element> </define> @@ -216,9 +216,9 @@ <define name='wordsize'> <element name='wordsize'> <choice> - <value>31</value> - <value>32</value> - <value>64</value> + <value>31</value> + <value>32</value> + <value>64</value> </choice> </element> </define> @@ -237,23 +237,23 @@ <define name='domain'> <element name='domain'> <attribute name='type'> - <choice> - <value>qemu</value> - <value>kqemu</value> - <value>kvm</value> - <value>xen</value> - <value>uml</value> - <value>lxc</value> - <value>openvz</value> - <value>test</value> - </choice> + <choice> + <value>qemu</value> + <value>kqemu</value> + <value>kvm</value> + <value>xen</value> + <value>uml</value> + <value>lxc</value> + <value>openvz</value> + <value>test</value> + </choice> </attribute> <optional> - <ref name='emulator'/> + <ref name='emulator'/> </optional> <zeroOrMore> - <ref name='machine'/> + <ref name='machine'/> </zeroOrMore> </element> </define> @@ -261,31 +261,31 @@ <define name='features'> <element name='features'> <optional> - <element name='pae'> - <empty/> - </element> + <element name='pae'> + <empty/> + </element> </optional> <optional> - <element name='nonpae'> - <empty/> - </element> + <element name='nonpae'> + <empty/> + </element> </optional> <optional> - <element name='ia64_be'> - <empty/> - </element> + <element name='ia64_be'> + <empty/> + </element> </optional> <optional> - <element name='acpi'> - <ref name='featuretoggle'/> - <empty/> - </element> + <element name='acpi'> + <ref name='featuretoggle'/> + <empty/> + </element> </optional> <optional> - <element name='apic'> - <ref name='featuretoggle'/> - <empty/> - </element> + <element name='apic'> + <ref name='featuretoggle'/> + <empty/> + </element> </optional> <optional> <element name='cpuselection'> @@ -298,14 +298,14 @@ <define name='featuretoggle'> <attribute name='toggle'> <choice> - <value>yes</value> - <value>no</value> + <value>yes</value> + <value>no</value> </choice> </attribute> <attribute name='default'> <choice> - <value>on</value> - <value>off</value> + <value>on</value> + <value>off</value> </choice> </attribute> </define> diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index adef792..33994bc 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -86,9 +86,9 @@ <attribute name="netmask"><text/></attribute> </optional> <optional> - <element name="tftp"> - <attribute name="root"><text/></attribute> - </element> + <element name="tftp"> + <attribute name="root"><text/></attribute> + </element> </optional> <!-- Define the range(s) of IP addresses that the DHCP server should hand out --> @@ -106,14 +106,14 @@ <attribute name="ip"><text/></attribute> </element> </zeroOrMore> - <optional> - <element name="bootp"> - <attribute name="file"><text/></attribute> + <optional> + <element name="bootp"> + <attribute name="file"><text/></attribute> <optional> <attribute name="server"><text/></attribute> </optional> - </element> - </optional> + </element> + </optional> </element> </element> </optional> diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 797b1af..55191d9 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -15,7 +15,7 @@ </optional> <zeroOrMore> - <ref name="capability"/> + <ref name="capability"/> </zeroOrMore> </element> </define> @@ -23,14 +23,14 @@ <define name='capability'> <element name="capability"> <choice> - <ref name="capsystem"/> - <ref name="cappcidev"/> - <ref name="capusbdev"/> - <ref name="capusbinterface"/> - <ref name="capnet"/> - <ref name="capscsihost"/> - <ref name="capscsi"/> - <ref name="capstorage"/> + <ref name="capsystem"/> + <ref name="cappcidev"/> + <ref name="capusbdev"/> + <ref name="capusbinterface"/> + <ref name="capnet"/> + <ref name="capscsihost"/> + <ref name="capscsi"/> + <ref name="capstorage"/> </choice> </element> </define> @@ -46,30 +46,30 @@ <element name='hardware'> <optional> - <element name='vendor'><text/></element> + <element name='vendor'><text/></element> </optional> <optional> - <element name='version'><text/></element> + <element name='version'><text/></element> </optional> <optional> - <element name='serial'><text/></element> + <element name='serial'><text/></element> </optional> <element name='uuid'> - <ref name='uuid'/> + <ref name='uuid'/> </element> </element> <element name='firmware'> <optional> - <element name='vendor'><text/></element> + <element name='vendor'><text/></element> </optional> <optional> - <element name='version'><text/></element> + <element name='version'><text/></element> </optional> <optional> - <element name='release_date'><text/></element> + <element name='release_date'><text/></element> </optional> </element> </define> @@ -94,23 +94,23 @@ <element name='product'> <attribute name='id'> - <ref name='hexuint'/> + <ref name='hexuint'/> </attribute> <choice> - <text/> - <empty/> + <text/> + <empty/> </choice> </element> <element name='vendor'> <attribute name='id'> - <ref name='hexuint'/> + <ref name='hexuint'/> </attribute> <choice> - <text/> - <empty/> + <text/> + <empty/> </choice> </element> @@ -130,23 +130,23 @@ <element name='product'> <attribute name='id'> - <ref name='hexuint'/> + <ref name='hexuint'/> </attribute> <choice> - <text/> - <empty/> + <text/> + <empty/> </choice> </element> <element name='vendor'> <attribute name='id'> - <ref name='hexuint'/> + <ref name='hexuint'/> </attribute> <choice> - <text/> - <empty/> + <text/> + <empty/> </choice> </element> </define> @@ -171,7 +171,7 @@ <optional> <element name='description'> - <text/> + <text/> </element> </optional> </define> @@ -186,7 +186,7 @@ </element> <optional> <element name='address'> - <ref name='mac'/> + <ref name='mac'/> </element> </optional> @@ -198,8 +198,8 @@ <define name='subcapnet'> <element name='capability'> <choice> - <ref name='subcapnet80203'/> - <ref name='subcapnet80211'/> + <ref name='subcapnet80203'/> + <ref name='subcapnet80211'/> </choice> </element> </define> @@ -261,27 +261,27 @@ <optional> <element name='bus'> - <text/> + <text/> </element> </optional> <optional> <element name='drive_type'> - <text/> + <text/> </element> </optional> <optional> <element name='model'> - <text/> - </element> + <text/> + </element> </optional> <optional> <element name='vendor'> - <text/> + <text/> </element> </optional> <optional> <element name='serial'> - <text/> + <text/> </element> </optional> @@ -292,9 +292,9 @@ <optional> <element name='capability'> - <attribute name='type'> - <value>hotpluggable</value> - </attribute> + <attribute name='type'> + <value>hotpluggable</value> + </attribute> </element> </optional> </define> @@ -302,17 +302,17 @@ <define name='capstorageremoveable'> <element name='capability'> <attribute name='type'> - <value>removable</value> + <value>removable</value> </attribute> <element name='media_available'> - <choice> - <value>1</value> - <value>0</value> - </choice> + <choice> + <value>1</value> + <value>0</value> + </choice> </element> <element name='media_size'> - <ref name='uint'/> + <ref name='uint'/> </element> <optional> <element name='media_label'> diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng index 247664e..cfcf9a6 100644 --- a/docs/schemas/storagepool.rng +++ b/docs/schemas/storagepool.rng @@ -9,14 +9,14 @@ <define name='pool'> <element name='pool'> <choice> - <ref name='pooldir'/> - <ref name='poolfs'/> - <ref name='poolnetfs'/> - <ref name='poollogical'/> - <ref name='pooldisk'/> - <ref name='pooliscsi'/> - <ref name='poolscsi'/> - <ref name='poolmpath'/> + <ref name='pooldir'/> + <ref name='poolfs'/> + <ref name='poolnetfs'/> + <ref name='poollogical'/> + <ref name='pooldisk'/> + <ref name='pooliscsi'/> + <ref name='poolscsi'/> + <ref name='poolmpath'/> </choice> </element> </define> @@ -109,7 +109,7 @@ </element> <optional> <element name='uuid'> - <ref name='uuid'/> + <ref name='uuid'/> </element> </optional> </define> @@ -117,17 +117,17 @@ <define name='sizing'> <optional> <element name='capacity'> - <ref name='uint'/> + <ref name='uint'/> </element> </optional> <optional> <element name='allocation'> - <ref name='uint'/> + <ref name='uint'/> </element> </optional> <optional> <element name='available'> - <ref name='uint'/> + <ref name='uint'/> </element> </optional> </define> @@ -135,20 +135,20 @@ <define name='permissions'> <optional> <element name='permissions'> - <element name='mode'> - <ref name='uint'/> - </element> - <element name='owner'> - <ref name='uint'/> - </element> - <element name='group'> - <ref name='uint'/> - </element> - <optional> - <element name='label'> - <text/> - </element> - </optional> + <element name='mode'> + <ref name='uint'/> + </element> + <element name='owner'> + <ref name='uint'/> + </element> + <element name='group'> + <ref name='uint'/> + </element> + <optional> + <element name='label'> + <text/> + </element> + </optional> </element> </optional> </define> @@ -156,9 +156,9 @@ <define name='target'> <element name='target'> <optional> - <element name='path'> - <ref name='path'/> - </element> + <element name='path'> + <ref name='path'/> + </element> </optional> <ref name='permissions'/> </element> @@ -167,7 +167,7 @@ <define name='sourceinfohost'> <element name='host'> <attribute name='name'> - <text/> + <text/> </attribute> <empty/> </element> @@ -176,14 +176,14 @@ <define name='sourceinfodev'> <element name='device'> <attribute name='path'> - <choice> - <ref name='path'/> - <ref name='name'/> - </choice> + <choice> + <ref name='path'/> + <ref name='name'/> + </choice> </attribute> <choice> - <empty/> - <ref name='devextents'/> + <empty/> + <ref name='devextents'/> </choice> </element> </define> @@ -191,7 +191,7 @@ <define name='initiatorinfoiqn'> <element name='iqn'> <attribute name='name'> - <text/> + <text/> </attribute> <empty/> </element> @@ -200,12 +200,12 @@ <define name='devextents'> <oneOrMore> <element name='freeExtent'> - <attribute name='start'> - <ref name='uint'/> - </attribute> - <attribute name='end'> - <ref name='uint'/> - </attribute> + <attribute name='start'> + <ref name='uint'/> + </attribute> + <attribute name='end'> + <ref name='uint'/> + </attribute> </element> </oneOrMore> </define> @@ -213,7 +213,7 @@ <define name='sourceinfodir'> <element name='dir'> <attribute name='path'> - <ref name='path'/> + <ref name='path'/> </attribute> <empty/> </element> @@ -222,7 +222,7 @@ <define name='sourceinfoadapter'> <element name='adapter'> <attribute name='name'> - <text/> + <text/> </attribute> <empty/> </element> @@ -253,23 +253,23 @@ <define name='sourcefmtfs'> <optional> <element name='format'> - <attribute name='type'> - <choice> - <value>auto</value> - <value>ext2</value> - <value>ext3</value> + <attribute name='type'> + <choice> + <value>auto</value> + <value>ext2</value> + <value>ext3</value> <value>ext4</value> - <value>ufs</value> - <value>iso9660</value> - <value>udf</value> + <value>ufs</value> + <value>iso9660</value> + <value>udf</value> <value>gfs</value> - <value>gfs2</value> - <value>vfat</value> - <value>hfs+</value> - <value>xfs</value> - <value>ocfs2</value> - </choice> - </attribute> + <value>gfs2</value> + <value>vfat</value> + <value>hfs+</value> + <value>xfs</value> + <value>ocfs2</value> + </choice> + </attribute> </element> </optional> </define> @@ -278,12 +278,12 @@ <define name='sourcefmtnetfs'> <optional> <element name='format'> - <attribute name='type'> - <choice> - <value>auto</value> - <value>nfs</value> - </choice> - </attribute> + <attribute name='type'> + <choice> + <value>auto</value> + <value>nfs</value> + </choice> + </attribute> </element> </optional> </define> @@ -292,19 +292,19 @@ <define name='sourcefmtdisk'> <optional> <element name='format'> - <attribute name='type'> - <choice> - <value>none</value> - <value>dos</value> - <value>dvh</value> - <value>gpt</value> - <value>mac</value> - <value>bsd</value> - <value>pc98</value> - <value>sun</value> - <value>lvm2</value> - </choice> - </attribute> + <attribute name='type'> + <choice> + <value>none</value> + <value>dos</value> + <value>dvh</value> + <value>gpt</value> + <value>mac</value> + <value>bsd</value> + <value>pc98</value> + <value>sun</value> + <value>lvm2</value> + </choice> + </attribute> </element> </optional> </define> @@ -313,12 +313,12 @@ <define name='sourcefmtlogical'> <optional> <element name='format'> - <attribute name='type'> - <choice> - <value>auto</value> - <value>lvm2</value> - </choice> - </attribute> + <attribute name='type'> + <choice> + <value>auto</value> + <value>lvm2</value> + </choice> + </attribute> </element> </optional> </define> @@ -327,7 +327,7 @@ <define name='sourcedir'> <optional> <element name='source'> - <empty/> + <empty/> </element> </optional> </define> diff --git a/docs/schemas/storagevol.rng b/docs/schemas/storagevol.rng index 287db85..994004d 100644 --- a/docs/schemas/storagevol.rng +++ b/docs/schemas/storagevol.rng @@ -11,18 +11,18 @@ <define name='vol'> <element name='volume'> <element name='name'> - <ref name='name'/> + <ref name='name'/> </element> <optional> - <element name='key'> - <text/> - </element> + <element name='key'> + <text/> + </element> </optional> <ref name='source'/> <ref name='sizing'/> <ref name='target'/> <optional> - <ref name='backingStore'/> + <ref name='backingStore'/> </optional> </element> </define> @@ -31,16 +31,16 @@ <optional> <element name='capacity'> <optional> - <attribute name='unit'> - <ref name='unit'/> - </attribute> + <attribute name='unit'> + <ref name='unit'/> + </attribute> </optional> - <ref name='uint'/> + <ref name='uint'/> </element> </optional> <optional> <element name='allocation'> - <ref name='uint'/> + <ref name='uint'/> </element> </optional> </define> @@ -48,20 +48,20 @@ <define name='permissions'> <optional> <element name='permissions'> - <element name='mode'> - <ref name='uint'/> - </element> - <element name='owner'> - <ref name='uint'/> - </element> - <element name='group'> - <ref name='uint'/> - </element> - <optional> - <element name='label'> - <text/> - </element> - </optional> + <element name='mode'> + <ref name='uint'/> + </element> + <element name='owner'> + <ref name='uint'/> + </element> + <element name='group'> + <ref name='uint'/> + </element> + <optional> + <element name='label'> + <text/> + </element> + </optional> </element> </optional> </define> @@ -69,9 +69,9 @@ <define name='target'> <element name='target'> <optional> - <element name='path'> - <ref name='path'/> - </element> + <element name='path'> + <ref name='path'/> + </element> </optional> <ref name='format'/> <ref name='permissions'/> @@ -84,7 +84,7 @@ <define name='backingStore'> <element name='backingStore'> <element name='path'> - <ref name='path'/> + <ref name='path'/> </element> <ref name='format'/> <ref name='permissions'/> @@ -95,7 +95,7 @@ <define name='source'> <element name='source'> <zeroOrMore> - <ref name='sourcedev'/> + <ref name='sourcedev'/> </zeroOrMore> </element> </define> @@ -103,11 +103,11 @@ <define name='sourcedev'> <element name='device'> <attribute name='path'> - <ref name='path'/> + <ref name='path'/> </attribute> <choice> - <empty/> - <ref name='devextents'/> + <empty/> + <ref name='devextents'/> </choice> </element> </define> @@ -115,12 +115,12 @@ <define name='devextents'> <oneOrMore> <element name='extent'> - <attribute name='start'> - <ref name='uint'/> - </attribute> - <attribute name='end'> - <ref name='uint'/> - </attribute> + <attribute name='start'> + <ref name='uint'/> + </attribute> + <attribute name='end'> + <ref name='uint'/> + </attribute> </element> </oneOrMore> </define> @@ -164,12 +164,12 @@ <define name='format'> <optional> <element name='format'> - <attribute name='type'> - <choice> - <ref name='formatfile'/> - <ref name='formatdev'/> - </choice> - </attribute> + <attribute name='type'> + <choice> + <ref name='formatfile'/> + <ref name='formatdev'/> + </choice> + </attribute> </element> </optional> </define> -- 1.7.0.1.414.g89213d

On Mon, Mar 01, 2010 at 08:12:23PM +0100, Jim Meyering wrote:
Daniel P. Berrange wrote: ...
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 :-) ?
Hmm, our syntax-check only seems to validate no-TABS for source code files, not schemas/docs
Here's the change to the syntax-check rule, followed by the change to the code to make those files comply. If everyone agrees, I'll reverse the order before pushing, so that make syntax-check passes after each commit.
ACK, this makes sense - since we clearly keep re-introducing tabs in these files. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Daniel P. Berrange wrote:
Here's the change to the syntax-check rule, followed by the change to the code to make those files comply. If everyone agrees, I'll reverse the order before pushing, so that make syntax-check passes after each commit.
ACK, this makes sense - since we clearly keep re-introducing tabs in these files.
Thanks for the quick ACK. Pushed.

This allows QEMU guests to be started with an arbitrary clock offset The test case can't actually be enabled, since QEMU argv expects an absolute timestring, and this will obviously change every time the test runs :-( Hopefully QEMU will allow a relative time offset in the future. * src/qemu/qemu_conf.c, src/qemu/qemu_conf.h: Use the -rtc arg if available to support variable clock offset mode * tests/qemuhelptest.c: Add QEMUD_CMD_FLAG_RTC for qemu 0.12.1 * qemuxml2argvdata/qemuxml2argv-clock-variable.args, qemuxml2argvdata/qemuxml2argv-clock-variable.xml, qemuxml2argvtest.c: Test case, except we can't actually enable it yet. --- src/qemu/qemu_conf.c | 82 ++++++++++++++++++-- src/qemu/qemu_conf.h | 1 + tests/qemuhelptest.c | 3 +- .../qemuxml2argv-clock-variable.args | 1 + .../qemuxml2argv-clock-variable.xml | 24 ++++++ tests/qemuxml2argvtest.c | 4 + 6 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index a207fc7..112a7c2 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1155,6 +1155,9 @@ static unsigned long long qemudComputeCmdFlags(const char *help, flags |= QEMUD_CMD_FLAG_BALLOON; if (strstr(help, "-device")) flags |= QEMUD_CMD_FLAG_DEVICE; + /* The trailing ' ' is important to avoid a bogus match */ + if (strstr(help, "-rtc ")) + flags |= QEMUD_CMD_FLAG_RTC; /* Keep disabled till we're actually ready to turn on netdev mode * The plan is todo it in 0.13.0 QEMU, but lets wait & see... */ #if 0 @@ -2969,6 +2972,56 @@ error: } +static char * +qemuBuildClockArgStr(virDomainClockDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + switch (def->offset) { + case VIR_DOMAIN_CLOCK_OFFSET_UTC: + virBufferAddLit(&buf, "base=utc"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + virBufferAddLit(&buf, "base=localtime"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: { + time_t now = time(NULL); + struct tm nowbits; + + now += def->adjustment; + gmtime_r(&now, &nowbits); + + virBufferVSprintf(&buf, "base=%d-%d-%dT%d:%d:%d", + nowbits.tm_year, + nowbits.tm_mon, + nowbits.tm_mday, + nowbits.tm_hour, + nowbits.tm_min, + nowbits.tm_sec); + } break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->offset)); + goto error; + } + + if (virBufferError(&buf)) { + virReportOOMError(); + goto error; + } + + return virBufferContentAndReset(&buf); + +error: + virBufferFreeAndReset(&buf); + return NULL; +} + + static int qemuBuildCpuArgStr(const struct qemud_driver *driver, const virDomainDefPtr def, @@ -3400,13 +3453,28 @@ int qemudBuildCommandLine(virConnectPtr conn, } } - if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) - ADD_ARG_LIT("-localtime"); - else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported clock offset '%s'"), - virDomainClockOffsetTypeToString(def->clock.offset)); - goto error; + if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC) { + const char *rtcopt; + ADD_ARG_LIT("-rtc"); + if (!(rtcopt = qemuBuildClockArgStr(&def->clock))) + goto error; + ADD_ARG(rtcopt); + } else { + switch (def->clock.offset) { + case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + ADD_ARG_LIT("-localtime"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_UTC: + /* Nothing, its the default */ + break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + } } if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 7041489..e32a3d7 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -82,6 +82,7 @@ enum qemud_cmd_flags { QEMUD_CMD_FLAG_SDL = (1 << 27), /* Is the new -sdl arg available */ QEMUD_CMD_FLAG_SMP_TOPOLOGY = (1 << 28), /* Is sockets=s,cores=c,threads=t available for -smp? */ QEMUD_CMD_FLAG_NETDEV = (1 << 29), /* The -netdev flag & netdev_add/remove monitor commands */ + QEMUD_CMD_FLAG_RTC = (1 << 30), /* The -rtc flag for clock options */ }; /* Main driver state */ diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 0f2b509..619d7cc 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -225,7 +225,8 @@ mymain(int argc, char **argv) QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_BALLOON | QEMUD_CMD_FLAG_DEVICE | - QEMUD_CMD_FLAG_SMP_TOPOLOGY, + QEMUD_CMD_FLAG_SMP_TOPOLOGY | + QEMUD_CMD_FLAG_RTC, 12001, 0, 0); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args new file mode 100644 index 0000000..09a9197 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -rtc base=2010-2-2T18:22:10 -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml new file mode 100644 index 0000000..fa20b27 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml @@ -0,0 +1,24 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='variable' adjustment='123456'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index aa42f99..510176c 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -226,6 +226,10 @@ mymain(int argc, char **argv) DO_TEST("bootloader", QEMUD_CMD_FLAG_DOMID); DO_TEST("clock-utc", 0); DO_TEST("clock-localtime", 0); + /* + * Can't be enabled since the absolute timestamp changes every time + DO_TEST("clock-variable", QEMUD_CMD_FLAG_RTC); + */ DO_TEST("hugepages", QEMUD_CMD_FLAG_MEM_PATH); DO_TEST("disk-cdrom", 0); DO_TEST("disk-cdrom-empty", QEMUD_CMD_FLAG_DRIVE); -- 1.6.6

On Thu, Feb 18, 2010 at 05:54:29PM +0000, Daniel P. Berrange wrote:
This allows QEMU guests to be started with an arbitrary clock offset
The test case can't actually be enabled, since QEMU argv expects an absolute timestring, and this will obviously change every time the test runs :-( Hopefully QEMU will allow a relative time offset in the future.
* src/qemu/qemu_conf.c, src/qemu/qemu_conf.h: Use the -rtc arg if available to support variable clock offset mode * tests/qemuhelptest.c: Add QEMUD_CMD_FLAG_RTC for qemu 0.12.1 * qemuxml2argvdata/qemuxml2argv-clock-variable.args, qemuxml2argvdata/qemuxml2argv-clock-variable.xml, qemuxml2argvtest.c: Test case, except we can't actually enable it yet. --- src/qemu/qemu_conf.c | 82 ++++++++++++++++++-- src/qemu/qemu_conf.h | 1 + tests/qemuhelptest.c | 3 +- .../qemuxml2argv-clock-variable.args | 1 + .../qemuxml2argv-clock-variable.xml | 24 ++++++ tests/qemuxml2argvtest.c | 4 + 6 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index a207fc7..112a7c2 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1155,6 +1155,9 @@ static unsigned long long qemudComputeCmdFlags(const char *help, flags |= QEMUD_CMD_FLAG_BALLOON; if (strstr(help, "-device")) flags |= QEMUD_CMD_FLAG_DEVICE; + /* The trailing ' ' is important to avoid a bogus match */ + if (strstr(help, "-rtc ")) + flags |= QEMUD_CMD_FLAG_RTC; /* Keep disabled till we're actually ready to turn on netdev mode * The plan is todo it in 0.13.0 QEMU, but lets wait & see... */ #if 0 @@ -2969,6 +2972,56 @@ error: }
+static char * +qemuBuildClockArgStr(virDomainClockDefPtr def) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + switch (def->offset) { + case VIR_DOMAIN_CLOCK_OFFSET_UTC: + virBufferAddLit(&buf, "base=utc"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + virBufferAddLit(&buf, "base=localtime"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: { + time_t now = time(NULL); + struct tm nowbits; + + now += def->adjustment; + gmtime_r(&now, &nowbits); + + virBufferVSprintf(&buf, "base=%d-%d-%dT%d:%d:%d", + nowbits.tm_year, + nowbits.tm_mon, + nowbits.tm_mday, + nowbits.tm_hour, + nowbits.tm_min, + nowbits.tm_sec); + } break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->offset)); + goto error; + } + + if (virBufferError(&buf)) { + virReportOOMError(); + goto error; + } + + return virBufferContentAndReset(&buf); + +error: + virBufferFreeAndReset(&buf); + return NULL; +} + + static int qemuBuildCpuArgStr(const struct qemud_driver *driver, const virDomainDefPtr def, @@ -3400,13 +3453,28 @@ int qemudBuildCommandLine(virConnectPtr conn, } }
- if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) - ADD_ARG_LIT("-localtime"); - else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { - qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported clock offset '%s'"), - virDomainClockOffsetTypeToString(def->clock.offset)); - goto error; + if (qemuCmdFlags & QEMUD_CMD_FLAG_RTC) { + const char *rtcopt; + ADD_ARG_LIT("-rtc"); + if (!(rtcopt = qemuBuildClockArgStr(&def->clock))) + goto error; + ADD_ARG(rtcopt); + } else { + switch (def->clock.offset) { + case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + ADD_ARG_LIT("-localtime"); + break; + + case VIR_DOMAIN_CLOCK_OFFSET_UTC: + /* Nothing, its the default */ + break; + + default: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported clock offset '%s'"), + virDomainClockOffsetTypeToString(def->clock.offset)); + goto error; + } }
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 7041489..e32a3d7 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -82,6 +82,7 @@ enum qemud_cmd_flags { QEMUD_CMD_FLAG_SDL = (1 << 27), /* Is the new -sdl arg available */ QEMUD_CMD_FLAG_SMP_TOPOLOGY = (1 << 28), /* Is sockets=s,cores=c,threads=t available for -smp? */ QEMUD_CMD_FLAG_NETDEV = (1 << 29), /* The -netdev flag & netdev_add/remove monitor commands */ + QEMUD_CMD_FLAG_RTC = (1 << 30), /* The -rtc flag for clock options */ };
/* Main driver state */ diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 0f2b509..619d7cc 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -225,7 +225,8 @@ mymain(int argc, char **argv) QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_BALLOON | QEMUD_CMD_FLAG_DEVICE | - QEMUD_CMD_FLAG_SMP_TOPOLOGY, + QEMUD_CMD_FLAG_SMP_TOPOLOGY | + QEMUD_CMD_FLAG_RTC, 12001, 0, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args new file mode 100644 index 0000000..09a9197 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -rtc base=2010-2-2T18:22:10 -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml new file mode 100644 index 0000000..fa20b27 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-variable.xml @@ -0,0 +1,24 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='variable' adjustment='123456'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index aa42f99..510176c 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -226,6 +226,10 @@ mymain(int argc, char **argv) DO_TEST("bootloader", QEMUD_CMD_FLAG_DOMID); DO_TEST("clock-utc", 0); DO_TEST("clock-localtime", 0); + /* + * Can't be enabled since the absolute timestamp changes every time + DO_TEST("clock-variable", QEMUD_CMD_FLAG_RTC); + */ DO_TEST("hugepages", QEMUD_CMD_FLAG_MEM_PATH); DO_TEST("disk-cdrom", 0); DO_TEST("disk-cdrom-empty", QEMUD_CMD_FLAG_DRIVE);
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This extends the XML to allow for <clock offset='timezone' timezone='Europe/Paris'/> This is useful if the admin has not configured any timezone on the host OS, but still wants to synchronize a guest to a specific one. * src/conf/domain_conf.h, src/conf/domain_conf.c: Support extra 'timezone' attribute on clock configuration * docs/schemas/domain.rng: Add 'timezone' attribute * src/xen/xend_internal.c, src/xen/xm_internal.c: Reject configs with a configurable timezone --- docs/schemas/domain.rng | 18 +++++++++++++++--- src/conf/domain_conf.c | 24 ++++++++++++++++++++---- src/conf/domain_conf.h | 13 ++++++++++--- src/qemu/qemu_conf.c | 2 +- src/xen/xend_internal.c | 10 ++++++++-- src/xen/xm_internal.c | 17 ++++++++++++----- 6 files changed, 66 insertions(+), 18 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index d295bfe..4a36a97 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -298,9 +298,16 @@ <optional> <element name="clock"> <choice> - <attribute name="offset"> - <value>localtime</value> - </attribute> + <group> + <attribute name="offset"> + <value>localtime</value> + </attribute> + <optional> + <attribute name="timezone"> + <ref name="timeZone"/> + </attribute> + </optional> + </group> <attribute name="offset"> <value>utc</value> </attribute> @@ -1584,4 +1591,9 @@ <param name="pattern">(-|\+)?[0-9]+</param> </data> </define> + <define name="timeZone"> + <data type="string"> + <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param> + </data> + </define> </grammar> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 49d5d19..ed5d9fd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -232,7 +232,8 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST, VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST, "utc", "localtime", - "variable"); + "variable", + "timezone"); #define virDomainReportError(code, fmt...) \ virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ @@ -650,6 +651,9 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->os.bootloader); VIR_FREE(def->os.bootloaderArgs); + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE) + VIR_FREE(def->clock.data.timezone); + VIR_FREE(def->name); VIR_FREE(def->cpumask); VIR_FREE(def->emulator); @@ -3496,8 +3500,17 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: if (virXPathLongLong("./clock/@adjustment", ctxt, - &def->clock.adjustment) < 0) - def->clock.adjustment = 0; + &def->clock.data.adjustment) < 0) + def->clock.data.adjustment = 0; + break; + + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: + def->clock.data.timezone = virXPathString("string(./clock/@timezone)", ctxt); + if (!def->clock.data.timezone) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing 'timezone' attribute for clock with offset='timezone'")); + goto error; + } break; } @@ -5411,7 +5424,10 @@ char *virDomainDefFormat(virDomainDefPtr def, virDomainClockOffsetTypeToString(def->clock.offset)); switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: - virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.adjustment); + virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.data.adjustment); + break; + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: + virBufferEscapeString(&buf, " timezone='%s'", def->clock.data.timezone); break; } virBufferAddLit(&buf, "/>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f5fe016..1dcfaa5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -613,6 +613,7 @@ enum virDomainClockOffsetType { VIR_DOMAIN_CLOCK_OFFSET_UTC = 0, VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1, VIR_DOMAIN_CLOCK_OFFSET_VARIABLE = 2, + VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE = 3, VIR_DOMAIN_CLOCK_OFFSET_LAST, }; @@ -622,9 +623,15 @@ typedef virDomainClockDef *virDomainClockDefPtr; struct _virDomainClockDef { int offset; - /* Adjustment in seconds, relative to UTC, when - * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */ - long long adjustment; + union { + /* Adjustment in seconds, relative to UTC, when + * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */ + long long adjustment; + + /* Timezone name, when + * offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME */ + char *timezone; + } data; }; #define VIR_DOMAIN_CPUMASK_LEN 1024 diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 112a7c2..cd0dd7f 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -2990,7 +2990,7 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) time_t now = time(NULL); struct tm nowbits; - now += def->adjustment; + now += def->data.adjustment; gmtime_r(&now, &nowbits); virBufferVSprintf(&buf, "base=%d-%d-%dT%d:%d:%d", diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index c88ea64..3a14d91 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -5846,9 +5846,15 @@ xenDaemonFormatSxpr(virConnectPtr conn, virBufferVSprintf(&buf, "(on_crash '%s')", tmp); /* Set localtime here for current XenD (both PV & HVM) */ - if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) { + if (def->clock.data.timezone) { + virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("configurable timezones are not supported")); + goto error; + } + virBufferAddLit(&buf, "(localtime 1)"); - else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { + } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported clock offset '%s'"), virDomainClockOffsetTypeToString(def->clock.offset)); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 4c20666..014cbfc 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -2328,13 +2328,20 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, goto no_memory; - if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME || - def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) { - if (xenXMConfigSetInt(conf, "localtime", - def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME ? - 1 : 0) < 0) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) { + if (def->clock.data.timezone) { + xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("configurable timezones are not supported")); + goto cleanup; + } + + if (xenXMConfigSetInt(conf, "localtime", 1) < 0) + goto no_memory; + } else if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) { + if (xenXMConfigSetInt(conf, "localtime", 0) < 0) goto no_memory; } else { + /* XXX We could support Xen's rtc clock offset */ xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported clock offset '%s'"), virDomainClockOffsetTypeToString(def->clock.offset)); -- 1.6.6

On Thu, Feb 18, 2010 at 05:54:30PM +0000, Daniel P. Berrange wrote:
This extends the XML to allow for
<clock offset='timezone' timezone='Europe/Paris'/>
This is useful if the admin has not configured any timezone on the host OS, but still wants to synchronize a guest to a specific one.
* src/conf/domain_conf.h, src/conf/domain_conf.c: Support extra 'timezone' attribute on clock configuration * docs/schemas/domain.rng: Add 'timezone' attribute * src/xen/xend_internal.c, src/xen/xm_internal.c: Reject configs with a configurable timezone --- docs/schemas/domain.rng | 18 +++++++++++++++--- src/conf/domain_conf.c | 24 ++++++++++++++++++++---- src/conf/domain_conf.h | 13 ++++++++++--- src/qemu/qemu_conf.c | 2 +- src/xen/xend_internal.c | 10 ++++++++-- src/xen/xm_internal.c | 17 ++++++++++++----- 6 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index d295bfe..4a36a97 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -298,9 +298,16 @@ <optional> <element name="clock"> <choice> - <attribute name="offset"> - <value>localtime</value> - </attribute> + <group> + <attribute name="offset"> + <value>localtime</value> + </attribute> + <optional> + <attribute name="timezone"> + <ref name="timeZone"/> + </attribute> + </optional> + </group> <attribute name="offset"> <value>utc</value> </attribute> @@ -1584,4 +1591,9 @@ <param name="pattern">(-|\+)?[0-9]+</param> </data> </define> + <define name="timeZone"> + <data type="string"> + <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param>
Hum ... I wonder if we should not add ':' as it's used for POSIX TZ
+ </data> + </define> </grammar> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 49d5d19..ed5d9fd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -232,7 +232,8 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VIR_DOMAIN_NETDEV_MACVTAP_MODE_LAST, VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST, "utc", "localtime", - "variable"); + "variable", + "timezone");
#define virDomainReportError(code, fmt...) \ virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ @@ -650,6 +651,9 @@ void virDomainDefFree(virDomainDefPtr def) VIR_FREE(def->os.bootloader); VIR_FREE(def->os.bootloaderArgs);
+ if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE) + VIR_FREE(def->clock.data.timezone); + VIR_FREE(def->name); VIR_FREE(def->cpumask); VIR_FREE(def->emulator); @@ -3496,8 +3500,17 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: if (virXPathLongLong("./clock/@adjustment", ctxt, - &def->clock.adjustment) < 0) - def->clock.adjustment = 0; + &def->clock.data.adjustment) < 0) + def->clock.data.adjustment = 0; + break; + + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: + def->clock.data.timezone = virXPathString("string(./clock/@timezone)", ctxt); + if (!def->clock.data.timezone) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing 'timezone' attribute for clock with offset='timezone'")); + goto error; + } break; }
@@ -5411,7 +5424,10 @@ char *virDomainDefFormat(virDomainDefPtr def, virDomainClockOffsetTypeToString(def->clock.offset)); switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: - virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.adjustment); + virBufferVSprintf(&buf, " adjustment='%lld'", def->clock.data.adjustment); + break; + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: + virBufferEscapeString(&buf, " timezone='%s'", def->clock.data.timezone); break; } virBufferAddLit(&buf, "/>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f5fe016..1dcfaa5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -613,6 +613,7 @@ enum virDomainClockOffsetType { VIR_DOMAIN_CLOCK_OFFSET_UTC = 0, VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME = 1, VIR_DOMAIN_CLOCK_OFFSET_VARIABLE = 2, + VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE = 3,
VIR_DOMAIN_CLOCK_OFFSET_LAST, }; @@ -622,9 +623,15 @@ typedef virDomainClockDef *virDomainClockDefPtr; struct _virDomainClockDef { int offset;
- /* Adjustment in seconds, relative to UTC, when - * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */ - long long adjustment; + union { + /* Adjustment in seconds, relative to UTC, when + * offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE */ + long long adjustment; + + /* Timezone name, when + * offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME */ + char *timezone; + } data; };
#define VIR_DOMAIN_CPUMASK_LEN 1024 diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 112a7c2..cd0dd7f 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -2990,7 +2990,7 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) time_t now = time(NULL); struct tm nowbits;
- now += def->adjustment; + now += def->data.adjustment; gmtime_r(&now, &nowbits);
virBufferVSprintf(&buf, "base=%d-%d-%dT%d:%d:%d", diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index c88ea64..3a14d91 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -5846,9 +5846,15 @@ xenDaemonFormatSxpr(virConnectPtr conn, virBufferVSprintf(&buf, "(on_crash '%s')", tmp);
/* Set localtime here for current XenD (both PV & HVM) */ - if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) { + if (def->clock.data.timezone) { + virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("configurable timezones are not supported")); + goto error; + } + virBufferAddLit(&buf, "(localtime 1)"); - else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { + } else if (def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_UTC) { virXendError(conn, VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported clock offset '%s'"), virDomainClockOffsetTypeToString(def->clock.offset)); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 4c20666..014cbfc 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -2328,13 +2328,20 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, goto no_memory;
- if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME || - def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) { - if (xenXMConfigSetInt(conf, "localtime", - def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME ? - 1 : 0) < 0) + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME) { + if (def->clock.data.timezone) { + xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED, + _("configurable timezones are not supported")); + goto cleanup; + } + + if (xenXMConfigSetInt(conf, "localtime", 1) < 0) + goto no_memory; + } else if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) { + if (xenXMConfigSetInt(conf, "localtime", 0) < 0) goto no_memory; } else { + /* XXX We could support Xen's rtc clock offset */ xenXMError(conn, VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported clock offset '%s'"), virDomainClockOffsetTypeToString(def->clock.offset));
ACK, looks fine, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Mon, Mar 01, 2010 at 03:14:48PM +0100, Daniel Veillard wrote:
On Thu, Feb 18, 2010 at 05:54:30PM +0000, Daniel P. Berrange wrote:
This extends the XML to allow for
<clock offset='timezone' timezone='Europe/Paris'/>
This is useful if the admin has not configured any timezone on the host OS, but still wants to synchronize a guest to a specific one.
* src/conf/domain_conf.h, src/conf/domain_conf.c: Support extra 'timezone' attribute on clock configuration * docs/schemas/domain.rng: Add 'timezone' attribute * src/xen/xend_internal.c, src/xen/xm_internal.c: Reject configs with a configurable timezone --- docs/schemas/domain.rng | 18 +++++++++++++++--- src/conf/domain_conf.c | 24 ++++++++++++++++++++---- src/conf/domain_conf.h | 13 ++++++++++--- src/qemu/qemu_conf.c | 2 +- src/xen/xend_internal.c | 10 ++++++++-- src/xen/xm_internal.c | 17 ++++++++++++----- 6 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index d295bfe..4a36a97 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -298,9 +298,16 @@ <optional> <element name="clock"> <choice> - <attribute name="offset"> - <value>localtime</value> - </attribute> + <group> + <attribute name="offset"> + <value>localtime</value> + </attribute> + <optional> + <attribute name="timezone"> + <ref name="timeZone"/> + </attribute> + </optional> + </group> <attribute name="offset"> <value>utc</value> </attribute> @@ -1584,4 +1591,9 @@ <param name="pattern">(-|\+)?[0-9]+</param> </data> </define> + <define name="timeZone"> + <data type="string"> + <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param>
Hum ... I wonder if we should not add ':' as it's used for POSIX TZ
How is it used ? I looked at /usr/share/zoneinfo and all the files there should be matched by this regex ok without needing ':' Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

According to Daniel P. Berrange on 3/1/2010 11:45 AM:
+ <data type="string"> + <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param>
Hum ... I wonder if we should not add ':' as it's used for POSIX TZ
How is it used ? I looked at /usr/share/zoneinfo and all the files there should be matched by this regex ok without needing ':'
POSIX states that the use of ':' introduces implementation-defined extensions. http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
The value of TZ has one of the two forms (spaces inserted for clarity):
:characters
or:
std offset dst offset, rule
If TZ is of the first format (that is, if the first character is a <colon>), the characters following the <colon> are handled in an implementation-defined manner.
In other words, since "Europe/Paris" is NOT a valid timezone according to POSIX rules, a user concerned about POSIX compliance should be allowed to use TZ=":Europe/Paris" to still get glibc semantics of a named zone. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Mon, Mar 01, 2010 at 06:45:28PM +0000, Daniel P. Berrange wrote:
On Mon, Mar 01, 2010 at 03:14:48PM +0100, Daniel Veillard wrote:
On Thu, Feb 18, 2010 at 05:54:30PM +0000, Daniel P. Berrange wrote:
This extends the XML to allow for
<clock offset='timezone' timezone='Europe/Paris'/>
This is useful if the admin has not configured any timezone on the host OS, but still wants to synchronize a guest to a specific one.
* src/conf/domain_conf.h, src/conf/domain_conf.c: Support extra 'timezone' attribute on clock configuration * docs/schemas/domain.rng: Add 'timezone' attribute * src/xen/xend_internal.c, src/xen/xm_internal.c: Reject configs with a configurable timezone --- docs/schemas/domain.rng | 18 +++++++++++++++--- src/conf/domain_conf.c | 24 ++++++++++++++++++++---- src/conf/domain_conf.h | 13 ++++++++++--- src/qemu/qemu_conf.c | 2 +- src/xen/xend_internal.c | 10 ++++++++-- src/xen/xm_internal.c | 17 ++++++++++++----- 6 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index d295bfe..4a36a97 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -298,9 +298,16 @@ <optional> <element name="clock"> <choice> - <attribute name="offset"> - <value>localtime</value> - </attribute> + <group> + <attribute name="offset"> + <value>localtime</value> + </attribute> + <optional> + <attribute name="timezone"> + <ref name="timeZone"/> + </attribute> + </optional> + </group> <attribute name="offset"> <value>utc</value> </attribute> @@ -1584,4 +1591,9 @@ <param name="pattern">(-|\+)?[0-9]+</param> </data> </define> + <define name="timeZone"> + <data type="string"> + <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param>
Hum ... I wonder if we should not add ':' as it's used for POSIX TZ
How is it used ? I looked at /usr/share/zoneinfo and all the files there should be matched by this regex ok without needing ':'
I looked there http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html seems that the offset allows for : separator for minutes/seconds I'm sure there is at least some places not aligned on hourly boundaries :) But honnestly it's not a big deal ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Mon, Mar 01, 2010 at 10:59:27PM +0100, Daniel Veillard wrote:
On Mon, Mar 01, 2010 at 06:45:28PM +0000, Daniel P. Berrange wrote:
On Mon, Mar 01, 2010 at 03:14:48PM +0100, Daniel Veillard wrote:
On Thu, Feb 18, 2010 at 05:54:30PM +0000, Daniel P. Berrange wrote:
This extends the XML to allow for
<clock offset='timezone' timezone='Europe/Paris'/>
This is useful if the admin has not configured any timezone on the host OS, but still wants to synchronize a guest to a specific one.
* src/conf/domain_conf.h, src/conf/domain_conf.c: Support extra 'timezone' attribute on clock configuration * docs/schemas/domain.rng: Add 'timezone' attribute * src/xen/xend_internal.c, src/xen/xm_internal.c: Reject configs with a configurable timezone --- docs/schemas/domain.rng | 18 +++++++++++++++--- src/conf/domain_conf.c | 24 ++++++++++++++++++++---- src/conf/domain_conf.h | 13 ++++++++++--- src/qemu/qemu_conf.c | 2 +- src/xen/xend_internal.c | 10 ++++++++-- src/xen/xm_internal.c | 17 ++++++++++++----- 6 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index d295bfe..4a36a97 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -298,9 +298,16 @@ <optional> <element name="clock"> <choice> - <attribute name="offset"> - <value>localtime</value> - </attribute> + <group> + <attribute name="offset"> + <value>localtime</value> + </attribute> + <optional> + <attribute name="timezone"> + <ref name="timeZone"/> + </attribute> + </optional> + </group> <attribute name="offset"> <value>utc</value> </attribute> @@ -1584,4 +1591,9 @@ <param name="pattern">(-|\+)?[0-9]+</param> </data> </define> + <define name="timeZone"> + <data type="string"> + <param name="pattern">[a-zA-Z0-9_\.\+\-/]+</param>
Hum ... I wonder if we should not add ':' as it's used for POSIX TZ
How is it used ? I looked at /usr/share/zoneinfo and all the files there should be matched by this regex ok without needing ':'
I looked there http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html seems that the offset allows for : separator for minutes/seconds I'm sure there is at least some places not aligned on hourly boundaries :) But honnestly it's not a big deal !
Well I've pushed the whole series, but we can add a patchto allow ':' in the regex. The actual parser code doesn't validate this strictly anyway Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Allow an arbitrary timezone with QEMU by setting the $TZ environment variable when launching QEMU * src/qemu/qemu_conf.c: Set TZ environment variable if a timezone is requested * tests/qemuxml2argvtest.c: Add test case for timezones * tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml, tests/qemuxml2argvdata/qemuxml2argv-clock-france.args: Data for timezone tests --- src/qemu/qemu_conf.c | 6 +++++ .../qemuxml2argv-clock-france.args | 1 + .../qemuxml2argvdata/qemuxml2argv-clock-france.xml | 24 ++++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + 4 files changed, 33 insertions(+), 0 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-france.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index cd0dd7f..4ed00cb 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -2983,6 +2983,7 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) break; case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: virBufferAddLit(&buf, "base=localtime"); break; @@ -3462,6 +3463,7 @@ int qemudBuildCommandLine(virConnectPtr conn, } else { switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: ADD_ARG_LIT("-localtime"); break; @@ -3476,6 +3478,10 @@ int qemudBuildCommandLine(virConnectPtr conn, goto error; } } + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE && + def->clock.data.timezone) { + ADD_ENV_PAIR("TZ", def->clock.data.timezone); + } if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-france.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.args new file mode 100644 index 0000000..3c57397 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test TZ=Europe/Paris /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -rtc base=localtime -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml new file mode 100644 index 0000000..157fdfb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml @@ -0,0 +1,24 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='timezone' timezone='Europe/Paris'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 510176c..bd41b6c 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -230,6 +230,8 @@ mymain(int argc, char **argv) * Can't be enabled since the absolute timestamp changes every time DO_TEST("clock-variable", QEMUD_CMD_FLAG_RTC); */ + DO_TEST("clock-france", QEMUD_CMD_FLAG_RTC); + DO_TEST("hugepages", QEMUD_CMD_FLAG_MEM_PATH); DO_TEST("disk-cdrom", 0); DO_TEST("disk-cdrom-empty", QEMUD_CMD_FLAG_DRIVE); -- 1.6.6

On Thu, Feb 18, 2010 at 05:54:31PM +0000, Daniel P. Berrange wrote:
Allow an arbitrary timezone with QEMU by setting the $TZ environment variable when launching QEMU
* src/qemu/qemu_conf.c: Set TZ environment variable if a timezone is requested * tests/qemuxml2argvtest.c: Add test case for timezones * tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml, tests/qemuxml2argvdata/qemuxml2argv-clock-france.args: Data for timezone tests --- src/qemu/qemu_conf.c | 6 +++++ .../qemuxml2argv-clock-france.args | 1 + .../qemuxml2argvdata/qemuxml2argv-clock-france.xml | 24 ++++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + 4 files changed, 33 insertions(+), 0 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-france.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index cd0dd7f..4ed00cb 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -2983,6 +2983,7 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) break;
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: virBufferAddLit(&buf, "base=localtime"); break;
@@ -3462,6 +3463,7 @@ int qemudBuildCommandLine(virConnectPtr conn, } else { switch (def->clock.offset) { case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME: + case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE: ADD_ARG_LIT("-localtime"); break;
@@ -3476,6 +3478,10 @@ int qemudBuildCommandLine(virConnectPtr conn, goto error; } } + if (def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE && + def->clock.data.timezone) { + ADD_ENV_PAIR("TZ", def->clock.data.timezone); + }
if ((qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT) && def->onReboot != VIR_DOMAIN_LIFECYCLE_RESTART) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-france.args b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.args new file mode 100644 index 0000000..3c57397 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test TZ=Europe/Paris /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -rtc base=localtime -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml new file mode 100644 index 0000000..157fdfb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-clock-france.xml @@ -0,0 +1,24 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='timezone' timezone='Europe/Paris'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 510176c..bd41b6c 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -230,6 +230,8 @@ mymain(int argc, char **argv) * Can't be enabled since the absolute timestamp changes every time DO_TEST("clock-variable", QEMUD_CMD_FLAG_RTC); */ + DO_TEST("clock-france", QEMUD_CMD_FLAG_RTC); + DO_TEST("hugepages", QEMUD_CMD_FLAG_MEM_PATH); DO_TEST("disk-cdrom", 0); DO_TEST("disk-cdrom-empty", QEMUD_CMD_FLAG_DRIVE);
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

* formatdomain.html.in: Document new clock options --- docs/formatdomain.html.in | 38 +++++++++++++++++++++++++++++++++++--- 1 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 083a80a..55038e2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -393,9 +393,41 @@ <dl> <dt><code>clock</code></dt> - <dd>The <code>offset</code> attribute takes either "utc" or - "localtime" to specify how the guest clock is initialized - in relation to the host OS. + <dd> + <p>The <code>offset</code> attribute takes three possible + values, allowing fine grained control over how the guest + clock is synchronized to the host. NB, not all hypervisors + support all modes.</p> + <dl> + <dt><code>utc</code></dt> + <dd> + The guest clock will always be synchronized to UTC when + booted</dd> + <dt><code>localtime</code></dt> + <dd> + The guest clock will be synchronized to the host's configured + timezone when booted, if any. + </dd> + <dt><code>timezone</code></dt> + <dd> + The guest clock will be synchronized to the requested timezone + using the <code>timezone</code> attribute. + </dd> + <dt><code>variable</code></dt> + <dd> + The guest clock will have an arbitrary offset applied + relative to UTC. The delta relative to UTC is specified + in seconds, using the <code>adjustment</code> attribute. + The guest is free to adjust the RTC over time an expect + that it will be honoured at next reboot. This is in + contrast to 'utc' mode, where the RTC adjustments are + lost at each reboot. + </dd> + </dl> + <p> + NB, at time of writing, only QEMU supports the variable + clock mode, or custom timezones. + </p> </dd> </dl> -- 1.6.6

On Thu, Feb 18, 2010 at 05:54:32PM +0000, Daniel P. Berrange wrote:
* formatdomain.html.in: Document new clock options --- docs/formatdomain.html.in | 38 +++++++++++++++++++++++++++++++++++--- 1 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 083a80a..55038e2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -393,9 +393,41 @@
<dl> <dt><code>clock</code></dt> - <dd>The <code>offset</code> attribute takes either "utc" or - "localtime" to specify how the guest clock is initialized - in relation to the host OS. + <dd> + <p>The <code>offset</code> attribute takes three possible + values, allowing fine grained control over how the guest + clock is synchronized to the host. NB, not all hypervisors + support all modes.</p> + <dl> + <dt><code>utc</code></dt> + <dd> + The guest clock will always be synchronized to UTC when + booted</dd> + <dt><code>localtime</code></dt> + <dd> + The guest clock will be synchronized to the host's configured + timezone when booted, if any. + </dd> + <dt><code>timezone</code></dt> + <dd> + The guest clock will be synchronized to the requested timezone + using the <code>timezone</code> attribute. + </dd> + <dt><code>variable</code></dt> + <dd> + The guest clock will have an arbitrary offset applied + relative to UTC. The delta relative to UTC is specified + in seconds, using the <code>adjustment</code> attribute. + The guest is free to adjust the RTC over time an expect + that it will be honoured at next reboot. This is in + contrast to 'utc' mode, where the RTC adjustments are + lost at each reboot. + </dd> + </dl> + <p> + NB, at time of writing, only QEMU supports the variable + clock mode, or custom timezones. + </p> </dd> </dl>
ACK, too, ACK for the serie a a whole, just a few checks and improvement possible. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

According to Daniel P. Berrange on 2/18/2010 10:54 AM:
* formatdomain.html.in: Document new clock options --- + <dd> + The guest clock will have an arbitrary offset applied + relative to UTC. The delta relative to UTC is specified + in seconds, using the <code>adjustment</code> attribute. + The guest is free to adjust the RTC over time an expect
s/an/and/
+ that it will be honoured at next reboot. This is in
Regarding "honoured": Is there a policy on American vs. British English in the documentation? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Thu, Feb 18, 2010 at 05:54:26PM +0000, Daniel P. Berrange wrote:
An update of
http://www.redhat.com/archives/libvir-list/2010-February/msg00104.html
The two current options are:
<clock offset='utc'/> <clock offset='localtime'/>
This introduces a way to set a specific timezone
<clock offset='timezone' timezone='Europe/Paris'/>
And a way to set a completely arbitrary time, by giving the number of seconds offset from UTC.
<clock offset='variable' adjustment='123456'/>
Since last time, I removed the 'timezone' attribute from the existing offset='localtime' option, and introduced the new explicit option offset='timezone'. That way we don't change semantics of the existing options at all.
Sounds fine to me, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (4)
-
Daniel P. Berrange
-
Daniel Veillard
-
Eric Blake
-
Jim Meyering