These APIs allow users to get or set time in a domain, which may come
handy if the domain has been resumed just recently and NTP is not
configured or hasn't kicked in yet and the guest is running
something time critical. In addition, NTP may refuse to re-set the clock
if the skew is too big.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
include/libvirt/libvirt.h.in | 13 +++++++
src/driver.h | 13 +++++++
src/libvirt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 6 +++
4 files changed, 123 insertions(+)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 295d551..3bbd4df 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -5245,6 +5245,19 @@ int virDomainFSTrim(virDomainPtr dom,
unsigned long long minimum,
unsigned int flags);
+int virDomainGetTime(virDomainPtr dom,
+ long long *time,
+ unsigned int flags);
+
+typedef enum {
+ VIR_DOMAIN_TIME_SYNC = (1 << 0), /* Re-sync domain time from domain's RTC
*/
+} virDomainSetTimeFlags;
+
+int virDomainSetTime(virDomainPtr dom,
+ long long time,
+ const char *timezone,
+ unsigned int flags);
+
/**
* virSchedParameterType:
*
diff --git a/src/driver.h b/src/driver.h
index 5f4cd8d..a825434 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1064,6 +1064,17 @@ typedef int
unsigned int flags);
typedef int
+(*virDrvDomainGetTime)(virDomainPtr dom,
+ long long *time,
+ unsigned int flags);
+
+typedef int
+(*virDrvDomainSetTime)(virDomainPtr dom,
+ long long time,
+ const char *timezone,
+ unsigned int flags);
+
+typedef int
(*virDrvDomainLxcOpenNamespace)(virDomainPtr dom,
int **fdlist,
unsigned int flags);
@@ -1340,6 +1351,8 @@ struct _virDriver {
virDrvDomainMigrateFinish3Params domainMigrateFinish3Params;
virDrvDomainMigrateConfirm3Params domainMigrateConfirm3Params;
virDrvConnectGetCPUModelNames connectGetCPUModelNames;
+ virDrvDomainGetTime domainGetTime;
+ virDrvDomainSetTime domainSetTime;
};
diff --git a/src/libvirt.c b/src/libvirt.c
index 666ab1e..aa063fd 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -20547,3 +20547,94 @@ error:
virDispatchError(dom->conn);
return -1;
}
+
+
+/**
+ * virDomainGetTime:
+ * @dom: a domain object
+ * @time: where to store the domain's time
+ * @flags: extra flags, not used yet, so callers should always pass 0
+ *
+ * Get the information about guest time relative to the Epoch of
+ * 1970-01-01 in UTC. The returned time is in seconds.
+ *
+ * Please note that some hypoervisors may require guest agent to
+ * be configured and running in order to be able to run this API.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int
+virDomainGetTime(virDomainPtr dom,
+ long long *time,
+ unsigned int flags)
+{
+ VIR_DOMAIN_DEBUG(dom, "time=%p, flags=%x",
+ time, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(dom, -1);
+ virCheckReadOnlyGoto(dom->conn->flags, error);
+
+ if (dom->conn->driver->domainGetTime) {
+ int ret = dom->conn->driver->domainGetTime(dom, time, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+error:
+ virDispatchError(dom->conn);
+ return -1;
+}
+
+
+/**
+ * virDomainSetTime:
+ * @dom: a domain object
+ * @time: time to set in the domain
+ * @timezone: timezone of @time, currently not used, always pass NULL
+ * @flags: extra flags, not used yet, so callers should always pass 0
+ *
+ * When a domain is suspended or restored from a file the
+ * domain's OS has no idea that there was a big gap in the time.
+ * Depending on how long the gap was, NTP might not be able to
+ * resynchronize the guest.
+ *
+ * This API tries to set guest time to the given value. The time
+ * should be in seconds, relative to the Epoch of 1970-01-01 in UTC.
+ *
+ * Please note that some hypoervisors may require guest agent to
+ * be configured and running in order to be able to run this API.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int
+virDomainSetTime(virDomainPtr dom,
+ long long time,
+ const char *timezone,
+ unsigned int flags)
+{
+ VIR_DOMAIN_DEBUG(dom, "time=%lld, timezone=%s, flags=%x",
+ time, NULLSTR(timezone), flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(dom, -1);
+ virCheckReadOnlyGoto(dom->conn->flags, error);
+
+ if (dom->conn->driver->domainSetTime) {
+ int ret = dom->conn->driver->domainSetTime(dom, time, timezone, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+error:
+ virDispatchError(dom->conn);
+ return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 6ed6ce6..2cb3fae 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -645,5 +645,11 @@ LIBVIRT_1.2.1 {
virConnectNetworkEventDeregisterAny;
} LIBVIRT_1.1.3;
+LIBVIRT_1.2.2 {
+ global:
+ virDomainGetTime;
+ virDomainSetTime;
+} LIBVIRT_1.2.1;
+
# .... define new API here using predicted next version number ....
--
1.8.5.3