]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce virDomain{Get,Set}Time APIs
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 2 Apr 2014 16:25:07 +0000 (18:25 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 15 May 2014 14:15:54 +0000 (16:15 +0200)
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.

In addition, new ACL attribute is introduced 'set_time'.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
daemon/remote.c
include/libvirt/libvirt.h.in
src/access/viraccessperm.c
src/access/viraccessperm.h
src/driver.h
src/libvirt.c
src/libvirt_public.syms
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs

index 8476961fbf5f87f4e863d8a9014c55366964a035..34c96c96f31caae438cfcaa3d87ce27e81efcaa7 100644 (file)
@@ -6077,6 +6077,43 @@ qemuDispatchConnectDomainMonitorEventDeregister(virNetServerPtr server ATTRIBUTE
     return rv;
 }
 
+static int
+remoteDispatchDomainGetTime(virNetServerPtr server ATTRIBUTE_UNUSED,
+                            virNetServerClientPtr client,
+                            virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                            virNetMessageErrorPtr rerr,
+                            remote_domain_get_time_args *args,
+                            remote_domain_get_time_ret *ret)
+{
+    int rv = -1;
+    virDomainPtr dom = NULL;
+    long long seconds;
+    unsigned int nseconds;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+        goto cleanup;
+
+    if (virDomainGetTime(dom, &seconds, &nseconds, args->flags) < 0)
+        goto cleanup;
+
+    ret->seconds = seconds;
+    ret->nseconds = nseconds;
+    rv = 0;
+
+ cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+    if (dom)
+        virDomainFree(dom);
+    return rv;
+}
 
 /*----- Helpers. -----*/
 
index 337ad71db2e1a79c213e8714d077e53d87693ce9..260c97115af9c64fbd9ab8946509ce45a5e75fea 100644 (file)
@@ -5289,6 +5289,20 @@ int virDomainFSThaw(virDomainPtr dom,
                     unsigned int nmountpoints,
                     unsigned int flags);
 
+int virDomainGetTime(virDomainPtr dom,
+                     long long *seconds,
+                     unsigned int *nseconds,
+                     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 seconds,
+                     unsigned int nseconds,
+                     unsigned int flags);
+
 /**
  * virSchedParameterType:
  *
index 8ca1edf1476a420da24914d021f1b800c1db1390..90071863be31b66ea2e76c55a001966f1934af6f 100644 (file)
@@ -43,7 +43,7 @@ VIR_ENUM_IMPL(virAccessPermDomain,
               "fs_trim", "fs_freeze",
               "block_read", "block_write", "mem_read",
               "open_graphics", "open_device", "screenshot",
-              "open_namespace");
+              "open_namespace", "set_time");
 
 VIR_ENUM_IMPL(virAccessPermInterface,
               VIR_ACCESS_PERM_INTERFACE_LAST,
index 50cea1e671ed1eddfeb604333fd306d629cb28f3..8ccbbad5d6cddd58e3a945b2841f978674ce233e 100644 (file)
@@ -288,13 +288,18 @@ typedef enum {
      */
     VIR_ACCESS_PERM_DOMAIN_SCREENSHOT,    /* Trigger a screen shot */
 
-
     /**
      * @desc: Open domain namespace
      * @message: Opening domain namespaces requires authorization
      */
     VIR_ACCESS_PERM_DOMAIN_OPEN_NAMESPACE,
 
+    /**
+     * @desc: Write domain time
+     * @message: Setting the domain time requires authorization
+     */
+    VIR_ACCESS_PERM_DOMAIN_SET_TIME,
+
     VIR_ACCESS_PERM_DOMAIN_LAST,
 } virAccessPermDomain;
 
index 502f30eb7bcae31c394d09f7a29bdfff1b139329..5ac89d61065632d7be7b707f650eae8368001feb 100644 (file)
@@ -1083,6 +1083,18 @@ typedef int
                       unsigned long long minimum,
                       unsigned int flags);
 
+typedef int
+(*virDrvDomainGetTime)(virDomainPtr dom,
+                       long long *seconds,
+                       unsigned int *nseconds,
+                       unsigned int flags);
+
+typedef int
+(*virDrvDomainSetTime)(virDomainPtr dom,
+                       long long seconds,
+                       unsigned int nseconds,
+                       unsigned int flags);
+
 typedef int
 (*virDrvDomainLxcOpenNamespace)(virDomainPtr dom,
                                 int **fdlist,
@@ -1377,6 +1389,8 @@ struct _virDriver {
     virDrvConnectGetCPUModelNames connectGetCPUModelNames;
     virDrvDomainFSFreeze domainFSFreeze;
     virDrvDomainFSThaw domainFSThaw;
+    virDrvDomainGetTime domainGetTime;
+    virDrvDomainSetTime domainSetTime;
 };
 
 
index 2cd793cb9dcdc3cbf89124bec04d0c488bd9bdd0..ccb71138921d3bb1013bc14de9c56fbc4f5d61b4 100644 (file)
@@ -20791,3 +20791,97 @@ virDomainFSThaw(virDomainPtr dom,
     virDispatchError(dom->conn);
     return -1;
 }
+
+/**
+ * virDomainGetTime:
+ * @dom: a domain object
+ * @seconds: domain's time in seconds
+ * @nseconds: the nanoscond part of @seconds
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Extract information about guest time and store it into
+ * @seconds and @nseconds. The @seconds represents the number of
+ * seconds since the UNIX Epoch of 1970-01-01 00:00:00 in UTC.
+ *
+ * Please note that some hypervisors may require guest agent to
+ * be configured and running in order to run this API.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int
+virDomainGetTime(virDomainPtr dom,
+                 long long *seconds,
+                 unsigned int *nseconds,
+                 unsigned int flags)
+{
+    VIR_DOMAIN_DEBUG(dom, "seconds=%p, nseconds=%p, flags=%x",
+                     seconds, nseconds, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(dom, -1);
+
+    if (dom->conn->driver->domainGetTime) {
+        int ret = dom->conn->driver->domainGetTime(dom, seconds,
+                                                   nseconds, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(dom->conn);
+    return -1;
+}
+
+/**
+ * virDomainSetTime:
+ * @dom: a domain object
+ * @seconds: time to set
+ * @nseconds: the nanosecond part of @seconds
+ * @flags: bitwise-OR of virDomainSetTimeFlags
+ *
+ * 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
+ * to set (@seconds and @nseconds) should be in seconds relative
+ * to the Epoch of 1970-01-01 00:00:00 in UTC.
+ *
+ * Please note that some hypervisors 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 seconds,
+                 unsigned int nseconds,
+                 unsigned int flags)
+{
+    VIR_DOMAIN_DEBUG(dom, "seconds=%lld, nseconds=%u, flags=%x",
+                     seconds, nseconds, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(dom, -1);
+    virCheckReadOnlyGoto(dom->conn->flags, error);
+
+    if (dom->conn->driver->domainSetTime) {
+        int ret = dom->conn->driver->domainSetTime(dom, seconds,
+                                                   nseconds, flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(dom->conn);
+    return -1;
+}
index f8113f46213b72ce0124f0bf8a3f51857ed0d6f5..cce6bdf80621647e9a52195006e26c2afd882284 100644 (file)
@@ -654,6 +654,8 @@ LIBVIRT_1.2.5 {
     global:
         virDomainFSFreeze;
         virDomainFSThaw;
+        virDomainGetTime;
+        virDomainSetTime;
 } LIBVIRT_1.2.3;
 
 
index 4c3b38aa67dfb84c6998ac2032c8fec7f76e1b2f..85fe597b5e64424577f3a1c7658cb2f5533fb9a5 100644 (file)
@@ -7435,6 +7435,39 @@ remoteDomainCreateWithFiles(virDomainPtr dom,
     return rv;
 }
 
+static int
+remoteDomainGetTime(virDomainPtr dom,
+                    long long *seconds,
+                    unsigned int *nseconds,
+                    unsigned int flags)
+{
+    int rv = -1;
+    struct private_data *priv = dom->conn->privateData;
+    remote_domain_get_time_args args;
+    remote_domain_get_time_ret ret;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_domain(&args.dom, dom);
+    args.flags = flags;
+
+    *seconds = *nseconds = 0;
+
+    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_TIME,
+             (xdrproc_t) xdr_remote_domain_get_time_args, (char *) &args,
+             (xdrproc_t) xdr_remote_domain_get_time_ret, (char *) &ret) == -1)
+        goto cleanup;
+
+    *seconds = ret.seconds;
+    *nseconds = ret.nseconds;
+    xdr_free((xdrproc_t) &xdr_remote_domain_get_time_ret, (char *) &ret);
+    rv = 0;
+
+ cleanup:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
 
 /* get_nonnull_domain and get_nonnull_network turn an on-wire
  * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
@@ -7770,6 +7803,8 @@ static virDriver remote_driver = {
     .connectGetCPUModelNames = remoteConnectGetCPUModelNames, /* 1.1.3 */
     .domainFSFreeze = remoteDomainFSFreeze, /* 1.2.5 */
     .domainFSThaw = remoteDomainFSThaw, /* 1.2.5 */
+    .domainGetTime = remoteDomainGetTime, /* 1.2.5 */
+    .domainSetTime = remoteDomainSetTime, /* 1.2.5 */
 };
 
 static virNetworkDriver network_driver = {
index 608490c6b1786d0c35a4f36cc94178bb6db2aefd..1f9d58307df67627a4e553d8636945fdd0f096d8 100644 (file)
@@ -2855,6 +2855,23 @@ struct remote_domain_fstrim_args {
     unsigned int flags;
 };
 
+struct remote_domain_get_time_args {
+    remote_nonnull_domain dom;
+    unsigned int flags;
+};
+
+struct remote_domain_get_time_ret {
+    hyper seconds;
+    unsigned int nseconds;
+};
+
+struct remote_domain_set_time_args {
+    remote_nonnull_domain dom;
+    hyper seconds;
+    unsigned int nseconds;
+    unsigned int flags;
+};
+
 struct remote_domain_migrate_begin3_params_args {
     remote_nonnull_domain dom;
     remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
@@ -5309,5 +5326,17 @@ enum remote_procedure {
      * @generate: both
      * @acl: domain:fs_freeze
      */
-    REMOTE_PROC_DOMAIN_FSTHAW = 336
+    REMOTE_PROC_DOMAIN_FSTHAW = 336,
+
+    /**
+     * @generate: none
+     * @acl: domain:read
+     */
+    REMOTE_PROC_DOMAIN_GET_TIME = 337,
+
+    /**
+     * @generate: both
+     * @acl: domain:set_time
+     */
+    REMOTE_PROC_DOMAIN_SET_TIME = 338
 };
index b62871f20ed4133f62e2eeeedb576a9a3d1a91a8..5b22049629e0cb4865c83ac9de0d10ffea5bc429 100644 (file)
@@ -2290,6 +2290,20 @@ struct remote_domain_fstrim_args {
         uint64_t                   minimum;
         u_int                      flags;
 };
+struct remote_domain_get_time_args {
+        remote_nonnull_domain      dom;
+        u_int                      flags;
+};
+struct remote_domain_get_time_ret {
+        int64_t                    seconds;
+        u_int                      nseconds;
+};
+struct remote_domain_set_time_args {
+        remote_nonnull_domain      dom;
+        int64_t                    seconds;
+        u_int                      nseconds;
+        u_int                      flags;
+};
 struct remote_domain_migrate_begin3_params_args {
         remote_nonnull_domain      dom;
         struct {
@@ -2786,4 +2800,6 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_CORE_DUMP_WITH_FORMAT = 334,
         REMOTE_PROC_DOMAIN_FSFREEZE = 335,
         REMOTE_PROC_DOMAIN_FSTHAW = 336,
+        REMOTE_PROC_DOMAIN_GET_TIME = 337,
+        REMOTE_PROC_DOMAIN_SET_TIME = 338,
 };