[PATCH v2 2/9] rpc: virnetserverclient: Introduce new attribute conn_time to client

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Besides ID, libvirt should provide several parameters to help the user
distinguish two clients from each other. One of them is the connection
timestamp. This patch also adds a testcase for proper JSON formatting of the
new attribute too (proper formatting of older clients that did not support
this attribute yet is included in the existing tests) - in order to
testGenerateJSON to work, a mock of time_t time(time_t *timer) needed to be
created.

Signed-off-by: Erik Skultety <eskultet@xxxxxxxxxx>
---
 src/rpc/virnetserverclient.c                       | 46 +++++++++++++-
 src/rpc/virnetserverclient.h                       |  1 +
 tests/Makefile.am                                  |  7 +++
 .../input-data-client-timestamp.json               | 70 ++++++++++++++++++++++
 .../output-data-client-timestamp.json              | 70 ++++++++++++++++++++++
 tests/virnetdaemonmock.c                           | 34 +++++++++++
 tests/virnetdaemontest.c                           |  4 +-
 7 files changed, 228 insertions(+), 4 deletions(-)
 create mode 100644 tests/virnetdaemondata/input-data-client-timestamp.json
 create mode 100644 tests/virnetdaemondata/output-data-client-timestamp.json
 create mode 100644 tests/virnetdaemonmock.c

diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index 7233773..a1543b9 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -85,6 +85,13 @@ struct _virNetServerClient
 
     virIdentityPtr identity;
 
+    /* Connection timestamp, i.e. when a client connected to the daemon (UTC).
+     * For old clients restored by post-exec-restart, which did not have this
+     * attribute, value of 0 (epoch time) is used to indicate we have no
+     * information about their connection time.
+     */
+    time_t conn_time;
+
     /* Count of messages in the 'tx' queue,
      * and the server worker pool queue
      * ie RPC calls in progress. Does not count
@@ -355,7 +362,8 @@ virNetServerClientNewInternal(unsigned long long id,
                               virNetTLSContextPtr tls,
 #endif
                               bool readonly,
-                              size_t nrequests_max)
+                              size_t nrequests_max,
+                              time_t timestamp)
 {
     virNetServerClientPtr client;
 
@@ -373,6 +381,7 @@ virNetServerClientNewInternal(unsigned long long id,
     client->tlsCtxt = virObjectRef(tls);
 #endif
     client->nrequests_max = nrequests_max;
+    client->conn_time = timestamp;
 
     client->sockTimer = virEventAddTimeout(-1, virNetServerClientSockTimerFunc,
                                            client, NULL);
@@ -413,6 +422,7 @@ virNetServerClientPtr virNetServerClientNew(unsigned long long id,
                                             void *privOpaque)
 {
     virNetServerClientPtr client;
+    time_t now;
 
     VIR_DEBUG("sock=%p auth=%d tls=%p", sock, auth,
 #ifdef WITH_GNUTLS
@@ -422,11 +432,17 @@ virNetServerClientPtr virNetServerClientNew(unsigned long long id,
 #endif
         );
 
+    if ((now = time(NULL)) == (time_t) - 1) {
+        virReportSystemError(errno, "%s", _("failed to get current time"));
+        return NULL;
+    }
+
     if (!(client = virNetServerClientNewInternal(id, sock, auth,
 #ifdef WITH_GNUTLS
                                                  tls,
 #endif
-                                                 readonly, nrequests_max)))
+                                                 readonly, nrequests_max,
+                                                 now)))
         return NULL;
 
     if (privNew) {
@@ -456,6 +472,7 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
     bool readonly;
     unsigned int nrequests_max;
     unsigned long long id;
+    time_t timestamp;
 
     if (virJSONValueObjectGetNumberInt(object, "auth", &auth) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -492,6 +509,18 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
         }
     }
 
+    if (!virJSONValueObjectHasKey(object, "conn_time")) {
+        timestamp = 0;
+    } else {
+        if (virJSONValueObjectGetNumberLong(object, "conn_time",
+                                            (long long *) &timestamp) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Malformed conn_time field in JSON "
+                             "state document"));
+            return NULL;
+        }
+    }
+
     if (!(sock = virNetSocketNewPostExecRestart(child))) {
         virObjectUnref(sock);
         return NULL;
@@ -504,7 +533,8 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec
                                                  NULL,
 #endif
                                                  readonly,
-                                                 nrequests_max))) {
+                                                 nrequests_max,
+                                                 timestamp))) {
         virObjectUnref(sock);
         return NULL;
     }
@@ -552,6 +582,11 @@ virJSONValuePtr virNetServerClientPreExecRestart(virNetServerClientPtr client)
     if (virJSONValueObjectAppendNumberUint(object, "nrequests_max", client->nrequests_max) < 0)
         goto error;
 
+    if (client->conn_time &&
+        virJSONValueObjectAppendNumberLong(object, "conn_time",
+                                           client->conn_time) < 0)
+        goto error;
+
     if (!(child = virNetSocketPreExecRestart(client->sock)))
         goto error;
 
@@ -610,6 +645,11 @@ unsigned long long virNetServerClientGetID(virNetServerClientPtr client)
     return client->id;
 }
 
+long long virNetServerClientGetTimestamp(virNetServerClientPtr client)
+{
+    return client->conn_time;
+}
+
 #ifdef WITH_GNUTLS
 bool virNetServerClientHasTLSSession(virNetServerClientPtr client)
 {
diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h
index 95edb06..e68ef76 100644
--- a/src/rpc/virnetserverclient.h
+++ b/src/rpc/virnetserverclient.h
@@ -82,6 +82,7 @@ int virNetServerClientGetAuth(virNetServerClientPtr client);
 void virNetServerClientSetAuth(virNetServerClientPtr client, int auth);
 bool virNetServerClientGetReadonly(virNetServerClientPtr client);
 unsigned long long virNetServerClientGetID(virNetServerClientPtr client);
+long long virNetServerClientGetTimestamp(virNetServerClientPtr client);
 
 # ifdef WITH_GNUTLS
 bool virNetServerClientHasTLSSession(virNetServerClientPtr client);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8cf53bf..6d8fa00 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -408,6 +408,7 @@ EXTRA_DIST += $(test_scripts)
 
 test_libraries = libshunload.la \
 		virportallocatormock.la \
+		virnetdaemonmock.la \
 		virnetserverclientmock.la \
 		vircgroupmock.la \
 		virpcimock.la \
@@ -927,6 +928,12 @@ virnetdaemontest_SOURCES = \
 virnetdaemontest_CFLAGS = $(XDR_CFLAGS) $(AM_CFLAGS)
 virnetdaemontest_LDADD = $(LDADDS)
 
+virnetdaemonmock_la_SOURCES = \
+	virnetdaemonmock.c
+virnetdaemonmock_la_CFLAGS = $(AM_CFLAGS)
+virnetdaemonmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
+virnetdaemonmock_la_LIBADD = $(MOCKLIBS_LIBS)
+
 virnetserverclienttest_SOURCES = \
 	virnetserverclienttest.c \
 	testutils.h testutils.c
diff --git a/tests/virnetdaemondata/input-data-client-timestamp.json b/tests/virnetdaemondata/input-data-client-timestamp.json
new file mode 100644
index 0000000..d069997
--- /dev/null
+++ b/tests/virnetdaemondata/input-data-client-timestamp.json
@@ -0,0 +1,70 @@
+{
+    "servers": {
+        "testServer0": {
+            "min_workers": 10,
+            "max_workers": 50,
+            "priority_workers": 5,
+            "max_clients": 100,
+            "max_anonymous_clients": 10,
+            "keepaliveInterval": 120,
+            "keepaliveCount": 5,
+            "next_client_id": 3,
+            "services": [
+                {
+                    "auth": 0,
+                    "readonly": true,
+                    "nrequests_client_max": 2,
+                    "socks": [
+                        {
+                            "fd": 100,
+                            "errfd": -1,
+                            "pid": 0,
+                            "isClient": false
+                        }
+                    ]
+                },
+                {
+                    "auth": 2,
+                    "readonly": false,
+                    "nrequests_client_max": 5,
+                    "socks": [
+                        {
+                            "fd": 101,
+                            "errfd": -1,
+                            "pid": 0,
+                            "isClient": false
+                        }
+                    ]
+                }
+            ],
+            "clients": [
+                {
+                    "id": 1,
+                    "auth": 1,
+                    "readonly": true,
+                    "nrequests_max": 15,
+                    "conn_time": 1234567890,
+                    "sock": {
+                        "fd": 102,
+                        "errfd": -1,
+                        "pid": -1,
+                        "isClient": true
+                    }
+                },
+                {
+                    "id": 2,
+                    "auth": 2,
+                    "readonly": true,
+                    "nrequests_max": 66,
+                    "conn_time": 1234567890,
+                    "sock": {
+                        "fd": 103,
+                        "errfd": -1,
+                        "pid": -1,
+                        "isClient": true
+                    }
+                }
+            ]
+        }
+    }
+}
diff --git a/tests/virnetdaemondata/output-data-client-timestamp.json b/tests/virnetdaemondata/output-data-client-timestamp.json
new file mode 100644
index 0000000..d069997
--- /dev/null
+++ b/tests/virnetdaemondata/output-data-client-timestamp.json
@@ -0,0 +1,70 @@
+{
+    "servers": {
+        "testServer0": {
+            "min_workers": 10,
+            "max_workers": 50,
+            "priority_workers": 5,
+            "max_clients": 100,
+            "max_anonymous_clients": 10,
+            "keepaliveInterval": 120,
+            "keepaliveCount": 5,
+            "next_client_id": 3,
+            "services": [
+                {
+                    "auth": 0,
+                    "readonly": true,
+                    "nrequests_client_max": 2,
+                    "socks": [
+                        {
+                            "fd": 100,
+                            "errfd": -1,
+                            "pid": 0,
+                            "isClient": false
+                        }
+                    ]
+                },
+                {
+                    "auth": 2,
+                    "readonly": false,
+                    "nrequests_client_max": 5,
+                    "socks": [
+                        {
+                            "fd": 101,
+                            "errfd": -1,
+                            "pid": 0,
+                            "isClient": false
+                        }
+                    ]
+                }
+            ],
+            "clients": [
+                {
+                    "id": 1,
+                    "auth": 1,
+                    "readonly": true,
+                    "nrequests_max": 15,
+                    "conn_time": 1234567890,
+                    "sock": {
+                        "fd": 102,
+                        "errfd": -1,
+                        "pid": -1,
+                        "isClient": true
+                    }
+                },
+                {
+                    "id": 2,
+                    "auth": 2,
+                    "readonly": true,
+                    "nrequests_max": 66,
+                    "conn_time": 1234567890,
+                    "sock": {
+                        "fd": 103,
+                        "errfd": -1,
+                        "pid": -1,
+                        "isClient": true
+                    }
+                }
+            ]
+        }
+    }
+}
diff --git a/tests/virnetdaemonmock.c b/tests/virnetdaemonmock.c
new file mode 100644
index 0000000..6d807a5
--- /dev/null
+++ b/tests/virnetdaemonmock.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Erik Skultety <eskultet@xxxxxxxxxx>
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include <time.h>
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+time_t time(time_t *t)
+{
+    const time_t ret = 1234567890;
+    if (t)
+        *t = ret;
+    return ret;
+}
diff --git a/tests/virnetdaemontest.c b/tests/virnetdaemontest.c
index b98c148..714f8d7 100644
--- a/tests/virnetdaemontest.c
+++ b/tests/virnetdaemontest.c
@@ -339,15 +339,17 @@ mymain(void)
     EXEC_RESTART_TEST("admin-server-names", 2);
     EXEC_RESTART_TEST("no-keepalive-required", 2);
     EXEC_RESTART_TEST("client-ids", 1);
+    EXEC_RESTART_TEST("client-timestamp", 1);
     EXEC_RESTART_TEST_FAIL("anon-clients", 2);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
+VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virnetdaemonmock.so")
 #else
 static int
 mymain(void)
 {
     return EXIT_AM_SKIP;
 }
-#endif
 VIRT_TEST_MAIN(mymain);
+#endif
-- 
2.4.11

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]