2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00

ovsdb-server: Implement read-only remote connection type.

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@redhat.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Lance Richardson 2016-10-25 12:38:48 -04:00 committed by Ben Pfaff
parent 2fd72a63aa
commit 9c1a11820e
6 changed files with 92 additions and 2 deletions

2
NEWS
View File

@ -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

View File

@ -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),

View File

@ -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 *

View File

@ -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.

View File

@ -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");

View File

@ -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