summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--ovsdb/jsonrpc-server.c7
-rw-r--r--ovsdb/jsonrpc-server.h1
-rw-r--r--ovsdb/ovsdb-server.1.in2
-rw-r--r--ovsdb/ovsdb-server.c15
-rw-r--r--tests/ovsdb-server.at67
6 files changed, 92 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index d07ec4593..865713415 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ Post-v2.6.0
release.
* New unixctl "ofctl/packet-out" command, which can be used to
instruct a flow monitor to issue OpenFlow packet-out messages.
+ - ovsdb-server:
+ * Remote connections can now be made read-only (see ovsdb-server(1)).
- Tunnels:
* TLV mappings for protocols such as Geneve are now segregated on
a per-OpenFlow bridge basis rather than globally. (The interface
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 87fc240b7..fa589b5e6 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 f04b1e977..f72f88487 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 e2e96ae92..0faf84406 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 0e3f9ac05..bc71fd11a 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 d04941bc6..ae1aab8b5 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