[ovs-dev] [PATCH 1/2] ovsdb: implement read-only remote connection type

Lance Richardson lrichard at redhat.com
Tue Oct 25 16:38:48 UTC 2016


Adds a new "read_only" column for remote connections.

Operations that would alter the state of the database are not
permitted on connections for which the "read_only" column is set
to "true".

Signed-off-by: Lance Richardson <lrichard at redhat.com>
---
 ovsdb/jsonrpc-server.c  |  7 ++++--
 ovsdb/jsonrpc-server.h  |  1 +
 ovsdb/ovsdb-server.1.in |  2 ++
 ovsdb/ovsdb-server.c    | 15 +++++++++++
 tests/ovsdb-server.at   | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 87fc240..fa589b5 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -127,6 +127,7 @@ struct ovsdb_jsonrpc_remote {
     struct pstream *listener;   /* Listener, if passive. */
     struct ovs_list sessions;   /* List of "struct ovsdb_jsonrpc_session"s. */
     uint8_t dscp;
+    bool read_only;
 };
 
 static struct ovsdb_jsonrpc_remote *ovsdb_jsonrpc_server_add_remote(
@@ -268,11 +269,12 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr,
     remote->listener = listener;
     ovs_list_init(&remote->sessions);
     remote->dscp = options->dscp;
+    remote->read_only = options->read_only;
     shash_add(&svr->remotes, name, remote);
 
     if (!listener) {
         ovsdb_jsonrpc_session_create(remote, jsonrpc_session_open(name, true),
-                                      svr->read_only);
+                                      svr->read_only || remote->read_only);
     }
     return remote;
 }
@@ -366,7 +368,8 @@ ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *svr)
                 struct jsonrpc_session *js;
                 js = jsonrpc_session_open_unreliably(jsonrpc_open(stream),
                                                      remote->dscp);
-                ovsdb_jsonrpc_session_create(remote, js, svr->read_only);
+                ovsdb_jsonrpc_session_create(remote, js, svr->read_only ||
+                                                         remote->read_only);
             } else if (error != EAGAIN) {
                 VLOG_WARN_RL(&rl, "%s: accept failed: %s",
                              pstream_get_name(remote->listener),
diff --git a/ovsdb/jsonrpc-server.h b/ovsdb/jsonrpc-server.h
index f04b1e9..f72f884 100644
--- a/ovsdb/jsonrpc-server.h
+++ b/ovsdb/jsonrpc-server.h
@@ -34,6 +34,7 @@ void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *);
 struct ovsdb_jsonrpc_options {
     int max_backoff;            /* Maximum reconnection backoff, in msec. */
     int probe_interval;         /* Max idle time before probing, in msec. */
+    bool read_only;             /* Only read-only transactions are allowed. */
     int dscp;                   /* Dscp value for manager connections */
 };
 struct ovsdb_jsonrpc_options *
diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in
index e2e96ae..0faf844 100644
--- a/ovsdb/ovsdb-server.1.in
+++ b/ovsdb/ovsdb-server.1.in
@@ -86,6 +86,8 @@ Maximum number of milliseconds to wait between connection attempts.
 .IP "\fBinactivity_probe\fR (integer)"
 Maximum number of milliseconds of idle time on connection to
 client before sending an inactivity probe message.
+.IP "\fBread_only\fR (boolean)"
+If true, only read-only transactions are allowed on this connection.
 .RE
 .IP
 It is an error for \fIcolumn\fR to have another type.
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 0e3f9ac..bc71fd1 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -781,6 +781,17 @@ read_string_column(const struct ovsdb_row *row, const char *column_name,
     return atom != NULL;
 }
 
+static bool
+read_bool_column(const struct ovsdb_row *row, const char *column_name,
+                   bool *boolp)
+{
+    const union ovsdb_atom *atom;
+
+    atom = read_column(row, column_name, OVSDB_TYPE_BOOLEAN);
+    *boolp = atom ? atom->boolean : false;
+    return atom != NULL;
+}
+
 static void
 write_bool_column(struct ovsdb_row *row, const char *column_name, bool value)
 {
@@ -849,6 +860,7 @@ add_manager_options(struct shash *remotes, const struct ovsdb_row *row)
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
     struct ovsdb_jsonrpc_options *options;
     long long int max_backoff, probe_interval;
+    bool read_only;
     const char *target, *dscp_string;
 
     if (!read_string_column(row, "target", &target) || !target) {
@@ -864,6 +876,9 @@ add_manager_options(struct shash *remotes, const struct ovsdb_row *row)
     if (read_integer_column(row, "inactivity_probe", &probe_interval)) {
         options->probe_interval = probe_interval;
     }
+    if (read_bool_column(row, "read_only", &read_only)) {
+        options->read_only = read_only;
+    }
 
     options->dscp = DSCP_DEFAULT;
     dscp_string = read_map_string_column(row, "other_config", "dscp");
diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index d04941b..ae1aab8 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -1367,3 +1367,70 @@ AT_CHECK([diff dump1 dump2])
 dnl OVSDB_SERVER_SHUTDOWN
 dnl OVSDB_SERVER_SHUTDOWN2
 AT_CLEANUP
+
+AT_SETUP([ovsdb-server/read-only db:ptcp connection])
+AT_KEYWORDS([ovsdb server read-only])
+AT_DATA([schema],
+  [[{"name": "mydb",
+     "tables": {
+       "Root": {
+         "columns": {
+           "managers": {
+             "type": {
+               "key": {"type": "uuid", "refTable": "Manager"},
+               "min": 0,
+               "max": "unlimited"}}}},
+       "Manager": {
+         "columns": {
+           "target": {
+             "type": "string"},
+           "read_only": {
+             "type": {
+               "key": "boolean",
+               "min": 0,
+               "max": 1}},
+           "is_connected": {
+             "type": {
+               "key": "boolean",
+               "min": 0,
+               "max": 1}}}},
+       "ordinals": {
+         "columns": {
+           "number": {"type": "integer"},
+           "name": {"type": "string"}},
+         "indexes": [["number"]]}
+    },
+     "version": "5.1.3",
+     "cksum": "12345678 9"
+}
+]])
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+AT_CHECK(
+  [[ovsdb-tool transact db \
+     '["mydb",
+       {"op": "insert",
+        "table": "Root",
+        "row": {
+          "managers": ["set", [["named-uuid", "x"]]]}},
+       {"op": "insert",
+        "table": "Manager",
+        "uuid-name": "x",
+        "row": {"target": "ptcp:0:127.0.0.1",
+               "read_only": true}}]']], [0], [ignore], [ignore])
+
+AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile --remote=db:mydb,Root,managers db], [0], [ignore], [ignore])
+PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
+AT_CHECK([ovsdb-client get-schema-version tcp:127.0.0.1:$TCP_PORT mydb], [0], [5.1.3
+])
+
+AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT \
+        ['["mydb",
+         {"op": "insert",
+          "table": "ordinals",
+          "row": {"name": "two", "number": '2'}}
+         ]']], [0], [stdout], [ignore])
+cat stdout >> output
+AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [[[{"details":"insert operation not allowed when database server is in read only mode","error":"not allowed"}]]
+], [ignore])
+OVSDB_SERVER_SHUTDOWN
+AT_CLEANUP
-- 
2.5.5




More information about the dev mailing list