This change set adds a new optional access-type specifier to remote connection descriptors for ovsdb-server.
Examples: --remote=ptcp:ro:0:192.168.0.10 --remote=punix:ro:asocket.sock --remote=pssl:ro:0:192.168.0.10 --remote=tcp:ro:192.168.0.99:4444 --remote=unix:ro:asocket.sock --remote=ssl:ro:192.168.0.10:4444 Operations that would alter the state of the database are not permitted on connections for which the "ro" access-type is specified. Signed-off-by: Lance Richardson <lrich...@redhat.com> --- RFC->v1: - Added autotest keywords for ssl tests. - Changed active tcp and ssl tests to find an unused TCP port instead of using hardcoded values (approach borrowed from ovsdb-idl.at). - Updated ovsdb-server.1 man page to add "ro:" connection types. - Fixed line length issue (identified by checkpatch.py) in jsonrpc-server.c. - Removed references to "read-write" connection type (still wondering "rw:" should be supported where "ro:" is allowed for symmetry). lib/stream-ssl.c | 11 +- lib/stream-tcp.c | 21 +-- lib/stream.c | 94 ++++++++++++- lib/stream.h | 4 +- manpages.mk | 2 + ovn/controller-vtep/ovn-controller-vtep.c | 2 +- ovn/controller/ovn-controller.c | 2 +- ovn/northd/ovn-northd.c | 2 +- ovn/utilities/ovn-sbctl.c | 2 +- ovn/utilities/ovn-trace.c | 2 +- ovsdb/automake.mk | 2 + ovsdb/jsonrpc-server.c | 11 +- ovsdb/ovsdb-client.c | 2 +- ovsdb/ovsdb-server.1.in | 2 + ovsdb/ovsdb-server.c | 2 +- ovsdb/remote-active-ro.man | 28 ++++ ovsdb/remote-passive-ro.man | 35 +++++ tests/ovsdb-server.at | 224 ++++++++++++++++++++++++++++++ tests/test-jsonrpc.c | 2 +- utilities/ovs-vsctl.c | 2 +- vswitchd/ovs-vswitchd.c | 2 +- vtep/vtep-ctl.c | 2 +- 22 files changed, 422 insertions(+), 34 deletions(-) create mode 100644 ovsdb/remote-active-ro.man create mode 100644 ovsdb/remote-passive-ro.man diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c index a5c32a1..2443005 100644 --- a/lib/stream-ssl.c +++ b/lib/stream-ssl.c @@ -778,13 +778,14 @@ pssl_pstream_cast(struct pstream *pstream) } static int -pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp, +pssl_open(const char *name, char *suffix, struct pstream **pstreamp, uint8_t dscp) { char bound_name[SS_NTOP_BUFSIZE + 16]; char addrbuf[SS_NTOP_BUFSIZE]; struct sockaddr_storage ss; struct pssl_pstream *pssl; + const char *access = ""; uint16_t port; int retval; int fd; @@ -799,9 +800,13 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp, return -fd; } + if (!strncmp(name, "pssl:ro:", 8)) { + access = "ro:"; + } + port = ss_get_port(&ss); - snprintf(bound_name, sizeof bound_name, "pssl:%"PRIu16":%s", - port, ss_format_address(&ss, addrbuf, sizeof addrbuf)); + snprintf(bound_name, sizeof bound_name, "pssl:%s%"PRIu16":%s", + access, port, ss_format_address(&ss, addrbuf, sizeof addrbuf)); pssl = xmalloc(sizeof *pssl); pstream_init(&pssl->pstream, &pssl_pstream_class, bound_name); diff --git a/lib/stream-tcp.c b/lib/stream-tcp.c index 1749fad..e0aaa68 100644 --- a/lib/stream-tcp.c +++ b/lib/stream-tcp.c @@ -84,13 +84,13 @@ static int new_pstream(char *suffix, const char *name, struct pstream **pstreamp, int dscp, char *unlink_path, bool kernel_print_port) { - char bound_name[SS_NTOP_BUFSIZE + 16]; + char bound_name[SS_NTOP_BUFSIZE + 20]; char addrbuf[SS_NTOP_BUFSIZE]; struct sockaddr_storage ss; + const char *access = ""; int error; uint16_t port; int fd; - char *conn_name = CONST_CAST(char *, name); fd = inet_open_passive(SOCK_STREAM, suffix, -1, &ss, dscp, kernel_print_port); @@ -98,14 +98,15 @@ new_pstream(char *suffix, const char *name, struct pstream **pstreamp, return -fd; } - port = ss_get_port(&ss); - if (!conn_name) { - snprintf(bound_name, sizeof bound_name, "ptcp:%"PRIu16":%s", - port, ss_format_address(&ss, addrbuf, sizeof addrbuf)); - conn_name = bound_name; + if (!strncmp(name, "ptcp:ro:", 8)) { + access = "ro:"; } - error = new_fd_pstream(conn_name, fd, ptcp_accept, unlink_path, pstreamp); + port = ss_get_port(&ss); + snprintf(bound_name, sizeof bound_name, "ptcp:%s%"PRIu16":%s", + access, port, ss_format_address(&ss, addrbuf, sizeof addrbuf)); + + error = new_fd_pstream(bound_name, fd, ptcp_accept, unlink_path, pstreamp); if (!error) { pstream_set_bound_port(*pstreamp, htons(port)); } @@ -113,10 +114,10 @@ new_pstream(char *suffix, const char *name, struct pstream **pstreamp, } static int -ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp, +ptcp_open(const char *name, char *suffix, struct pstream **pstreamp, uint8_t dscp) { - return new_pstream(suffix, NULL, pstreamp, dscp, NULL, true); + return new_pstream(suffix, name, pstreamp, dscp, NULL, true); } static int diff --git a/lib/stream.c b/lib/stream.c index f6ea849..47cd0fb 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -116,7 +116,7 @@ check_stream_classes(void) * connection methods supported by the stream. */ void stream_usage(const char *name, bool active, bool passive, - bool bootstrap OVS_UNUSED) + bool bootstrap OVS_UNUSED, bool access) { /* Really this should be implemented via callbacks into the stream * providers, but that seems too heavy-weight to bother with at the @@ -135,6 +135,17 @@ stream_usage(const char *name, bool active, bool passive, "Unix domain socket named FILE\n"); } + if (active && access) { + printf(" tcp:ro:IP:PORT " + "PORT at remote IP (read-only access)\n"); +#ifdef HAVE_OPENSSL + printf(" ssl:ro:IP:PORT " + "SSL PORT at remote IP (read-only access)\n"); +#endif + printf(" unix:FILE " + "Unix domain socket named FILE (read-only access)\n"); + } + if (passive) { printf("Passive %s connection methods:\n", name); printf(" ptcp:PORT[:IP] " @@ -147,6 +158,17 @@ stream_usage(const char *name, bool active, bool passive, "listen on Unix domain socket FILE\n"); } + if (passive && access) { + printf(" ptcp:ro:PORT[:IP] " + "listen to TCP PORT on IP (read-only access)\n"); +#ifdef HAVE_OPENSSL + printf(" pssl:ro:PORT[:IP] " + "listen for SSL on PORT on IP (read-only access)\n"); +#endif + printf(" punix:ro:FILE " + "listen on Unix domain socket FILE (read-only access)\n"); + } + #ifdef HAVE_OPENSSL printf("PKI configuration (required to use SSL):\n" " -p, --private-key=FILE file with private key\n" @@ -209,6 +231,7 @@ stream_open(const char *name, struct stream **streamp, uint8_t dscp) const struct stream_class *class; struct stream *stream; char *suffix_copy; + const char *next; int error; COVERAGE_INC(stream_open); @@ -219,8 +242,14 @@ stream_open(const char *name, struct stream **streamp, uint8_t dscp) goto error; } + /* Check for read-only access specifier */ + next = strchr(name, ':') + 1; + if (!strncmp(next, "ro:", 3)) { + next += 3; + } + /* Call class's "open" function. */ - suffix_copy = xstrdup(strchr(name, ':') + 1); + suffix_copy = xstrdup(next); error = class->open(name, suffix_copy, &stream, dscp); free(suffix_copy); if (error) { @@ -486,6 +515,30 @@ stream_or_pstream_needs_probes(const char *name) } } +/* Returns 1 if the stream or pstream specified by 'name' includes a read- + * only access specification. */ +int +stream_or_pstream_is_read_only(const char *name) +{ + const struct pstream_class *pclass; + const struct stream_class *class; + const char *next; + + if (!stream_lookup_class(name, &class)) { + next = strchr(name, ':') + 1; + if (!strncmp(next, "ro:", 3)) { + return true; + } + } else if (!pstream_lookup_class(name, &pclass)) { + next = strchr(name, ':') + 1; + if (!strncmp(next, "ro:", 3)) { + return true; + } + } + + return false; +} + /* Attempts to start listening for remote stream connections. 'name' is a * connection name in the form "TYPE:ARGS", where TYPE is an passive stream * class's name and ARGS are stream class-specific. @@ -499,6 +552,7 @@ pstream_open(const char *name, struct pstream **pstreamp, uint8_t dscp) const struct pstream_class *class; struct pstream *pstream; char *suffix_copy; + const char *next; int error; COVERAGE_INC(pstream_open); @@ -509,8 +563,14 @@ pstream_open(const char *name, struct pstream **pstreamp, uint8_t dscp) goto error; } + /* Check for read-only access specifier */ + next = strchr(name, ':') + 1; + if (!strncmp(next, "ro:", 3)) { + next += 3; + } + /* Call class's "open" function. */ - suffix_copy = xstrdup(strchr(name, ':') + 1); + suffix_copy = xstrdup(next); error = class->listen(name, suffix_copy, &pstream, dscp); free(suffix_copy); if (error) { @@ -674,7 +734,19 @@ stream_open_with_default_port(const char *name_, char *name; int error; - if ((!strncmp(name_, "tcp:", 4) || !strncmp(name_, "ssl:", 4)) + if ((!strncmp(name_, "tcp:ro:", 7) || !strncmp(name_, "ssl:ro:", 7)) + && count_fields(name_) < 4) { + if (default_port == OFP_PORT) { + VLOG_WARN_ONCE("The default OpenFlow port number has changed " + "from %d to %d", + OFP_OLD_PORT, OFP_PORT); + } else if (default_port == OVSDB_PORT) { + VLOG_WARN_ONCE("The default OVSDB port number has changed " + "from %d to %d", + OVSDB_OLD_PORT, OVSDB_PORT); + } + name = xasprintf("%s:%d", name_, default_port); + } else if ((!strncmp(name_, "tcp:", 4) || !strncmp(name_, "ssl:", 4)) && count_fields(name_) < 3) { if (default_port == OFP_PORT) { VLOG_WARN_ONCE("The default OpenFlow port number has changed " @@ -706,7 +778,10 @@ pstream_open_with_default_port(const char *name_, char *name; int error; - if ((!strncmp(name_, "ptcp:", 5) || !strncmp(name_, "pssl:", 5)) + if ((!strncmp(name_, "ptcp:ro:", 8) || !strncmp(name_, "pssl:ro:", 8)) + && count_fields(name_) < 3) { + name = xasprintf("%s%d", name_, default_port); + } else if ((!strncmp(name_, "ptcp:", 5) || !strncmp(name_, "pssl:", 5)) && count_fields(name_) < 2) { name = xasprintf("%s%d", name_, default_port); } else { @@ -731,8 +806,13 @@ stream_parse_target_with_default_port(const char *target, uint16_t default_port, struct sockaddr_storage *ss) { - return ((!strncmp(target, "tcp:", 4) || !strncmp(target, "ssl:", 4)) - && inet_parse_active(target + 4, default_port, ss)); + if (!strncmp(target, "tcp:ro:", 7) || !strncmp(target, "ssl:ro:", 7)) { + return inet_parse_active(target + 7, default_port, ss); + } else if (!strncmp(target, "tcp:", 4) || !strncmp(target, "ssl:", 4)) { + return inet_parse_active(target + 4, default_port, ss); + } else { + return false; + } } /* Attempts to guess the content type of a stream whose first few bytes were diff --git a/lib/stream.h b/lib/stream.h index f8e1891..bded34d 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -29,7 +29,8 @@ struct pstream; struct stream; struct vlog_module; -void stream_usage(const char *name, bool active, bool passive, bool bootstrap); +void stream_usage(const char *name, bool active, bool passive, + bool bootstrap, bool access); /* Bidirectional byte streams. */ int stream_verify_name(const char *name); @@ -79,6 +80,7 @@ bool stream_parse_target_with_default_port(const char *target, uint16_t default_port, struct sockaddr_storage *ss); int stream_or_pstream_needs_probes(const char *name); +int stream_or_pstream_is_read_only(const char *name); /* Error reporting. */ diff --git a/manpages.mk b/manpages.mk index fa9e59b..d7aeb12 100644 --- a/manpages.mk +++ b/manpages.mk @@ -64,7 +64,9 @@ ovsdb/ovsdb-server.1: \ lib/vlog-unixctl.man \ lib/vlog.man \ ovsdb/remote-active.man \ + ovsdb/remote-active-ro.man \ ovsdb/remote-passive.man \ + ovsdb/remote-passive-ro.man \ ovsdb/replication-syn.man \ ovsdb/replication.man ovsdb/ovsdb-server.1.in: diff --git a/ovn/controller-vtep/ovn-controller-vtep.c b/ovn/controller-vtep/ovn-controller-vtep.c index baee789..9c2ed75 100644 --- a/ovn/controller-vtep/ovn-controller-vtep.c +++ b/ovn/controller-vtep/ovn-controller-vtep.c @@ -256,7 +256,7 @@ Options:\n\ -o, --options list available options\n\ -V, --version display version information\n\ ", program_name, program_name, default_db(), default_db()); - stream_usage("database", true, false, false); + stream_usage("database", true, false, false, false); daemon_usage(); vlog_usage(); exit(EXIT_SUCCESS); diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 4ac1425..2c7d743 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -749,7 +749,7 @@ usage(void) "usage %s [OPTIONS] [OVS-DATABASE]\n" "where OVS-DATABASE is a socket on which the OVS OVSDB server is listening.\n", program_name, program_name); - stream_usage("OVS-DATABASE", true, false, false); + stream_usage("OVS-DATABASE", true, false, false, false); daemon_usage(); vlog_usage(); printf("\nOther options:\n" diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 281dc62..b0da206 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -223,7 +223,7 @@ Options:\n\ ", program_name, program_name, default_nb_db(), default_sb_db()); daemon_usage(); vlog_usage(); - stream_usage("database", true, true, false); + stream_usage("database", true, true, false, false); } struct tnlid_node { diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c index b894b8b..e064330 100644 --- a/ovn/utilities/ovn-sbctl.c +++ b/ovn/utilities/ovn-sbctl.c @@ -326,7 +326,7 @@ Options:\n\ Other options:\n\ -h, --help display this help message\n\ -V, --version display version information\n"); - stream_usage("database", true, true, false); + stream_usage("database", true, true, false, false); exit(EXIT_SUCCESS); } diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index 7863f70..7b0eb2a 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -255,7 +255,7 @@ Other options:\n\ --unixctl=SOCKET set control socket name\n\ -h, --help display this help message\n\ -V, --version display version information\n"); - stream_usage("database", true, true, false); + stream_usage("database", true, true, false, false); exit(EXIT_SUCCESS); } diff --git a/ovsdb/automake.mk b/ovsdb/automake.mk index 099ed3c..112cc9b 100644 --- a/ovsdb/automake.mk +++ b/ovsdb/automake.mk @@ -44,7 +44,9 @@ pkgconfig_DATA += \ MAN_FRAGMENTS += \ ovsdb/remote-active.man \ + ovsdb/remote-active-ro.man \ ovsdb/remote-passive.man \ + ovsdb/remote-passive-ro.man \ ovsdb/replication.man \ ovsdb/replication-syn.man diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c index 87fc240..9252a20 100644 --- a/ovsdb/jsonrpc-server.c +++ b/ovsdb/jsonrpc-server.c @@ -272,7 +272,8 @@ ovsdb_jsonrpc_server_add_remote(struct ovsdb_jsonrpc_server *svr, if (!listener) { ovsdb_jsonrpc_session_create(remote, jsonrpc_session_open(name, true), - svr->read_only); + svr->read_only || + stream_or_pstream_is_read_only(name)); } return remote; } @@ -364,9 +365,15 @@ ovsdb_jsonrpc_server_run(struct ovsdb_jsonrpc_server *svr) error = pstream_accept(remote->listener, &stream); if (!error) { struct jsonrpc_session *js; + const char *stream_name; + bool read_only; + js = jsonrpc_session_open_unreliably(jsonrpc_open(stream), remote->dscp); - ovsdb_jsonrpc_session_create(remote, js, svr->read_only); + stream_name = pstream_get_name(remote->listener); + read_only = svr->read_only || + stream_or_pstream_is_read_only(stream_name); + ovsdb_jsonrpc_session_create(remote, js, read_only); } else if (error != EAGAIN) { VLOG_WARN_RL(&rl, "%s: accept failed: %s", pstream_get_name(remote->listener), diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index 5f569e8..3bc4898 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -278,7 +278,7 @@ usage(void) "\nThe default SERVER is unix:%s/db.sock.\n" "The default DATABASE is Open_vSwitch.\n", program_name, program_name, ovs_rundir()); - stream_usage("SERVER", true, true, true); + stream_usage("SERVER", true, true, true, false); printf("\nOutput formatting options:\n" " -f, --format=FORMAT set output formatting to FORMAT\n" " (\"table\", \"html\", \"csv\", " diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in index e2e96ae..7ed9ea3 100644 --- a/ovsdb/ovsdb-server.1.in +++ b/ovsdb/ovsdb-server.1.in @@ -61,7 +61,9 @@ Adds \fIremote\fR as a connection method used by \fBovsdb\-server\fR. . .RS .so ovsdb/remote-passive.man +.so ovsdb/remote-passive-ro.man .so ovsdb/remote-active.man +.so ovsdb/remote-active-ro.man . .IP "\fBdb:\fIdb\fB,\fItable\fB,\fIcolumn\fR" Reads additional connection methods from \fIcolumn\fR in all of the diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 0e3f9ac..ab284b8 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -1623,7 +1623,7 @@ usage(void) program_name, program_name, ovs_dbdir()); printf("\nJSON-RPC options (may be specified any number of times):\n" " --remote=REMOTE connect or listen to REMOTE\n"); - stream_usage("JSON-RPC", true, true, true); + stream_usage("JSON-RPC", true, true, true, true); daemon_usage(); vlog_usage(); replication_usage(); diff --git a/ovsdb/remote-active-ro.man b/ovsdb/remote-active-ro.man new file mode 100644 index 0000000..ff6b089 --- /dev/null +++ b/ovsdb/remote-active-ro.man @@ -0,0 +1,28 @@ +.IP "\fBssl:ro:\fIip\fB:\fIport\fR" +Connect to the specified SSL \fIport\fR on the host at the given \fIip\fR, which +must be expressed as an IP address (not a DNS name) in IPv4 or IPv6 address +format. If \fIip\fR is an IPv6 address, then wrap \fIip\fR with square +brackets, e.g.: \fBssl:[::1]:6640\fR. +The \fB\-\-private\-key\fR, \fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR +options are mandatory when this form is used. +.IP +The \fBro:\fR element indicates that database modifications are not allowed +on this connection. +. +.IP "\fBtcp:ro:\fIip\fB:\fIport\fR" +Connect to the given TCP \fIport\fR on \fIip\fR, where \fIip\fR can be IPv4 +or IPv6 address. If \fIip\fR is an IPv6 address, then wrap \fIip\fR with +square brackets, e.g.: \fBtcp:[::1]:6640\fR. +.IP +The \fBro:\fR element indicates that database modifications are not allowed +on this connection. +. +.IP "\fBunix:ro:\fIfile\fR" +On POSIX, connect to the Unix domain server socket named \fIfile\fR. +.IP +On Windows, connect to a local named pipe that is represented by a file +created in the path \fIfile\fR to mimic the behavior of a Unix domain +socket. +.IP +The \fBro:\fR element indicates that database modifications are not allowed +on this connection. diff --git a/ovsdb/remote-passive-ro.man b/ovsdb/remote-passive-ro.man new file mode 100644 index 0000000..4e47a97 --- /dev/null +++ b/ovsdb/remote-passive-ro.man @@ -0,0 +1,35 @@ +.IP "\fBpssl:ro:\fIport\fR[\fB:\fIip\fR]" +Listen on the given SSL \fIport\fR for a connection. By default, +connections are not bound to a particular local IP address and +it listens only on IPv4 (but not IPv6) addresses, but +specifying \fIip\fR limits connections to those from the given +\fIip\fR, either IPv4 or IPv6 address. If \fIip\fR is +an IPv6 address, then wrap \fIip\fR with square brackets, e.g.: +\fBpssl:6640:[::1]\fR. The \fB\-\-private\-key\fR, +\fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR options are mandatory +when this form is used. +.IP +The \fBro:\fR element indicates that database modifications are not allowed +on this connection. +. +.IP "\fBptcp:ro:\fIport\fR[\fB:\fIip\fR]" +Listen on the given TCP \fIport\fR for a connection. By default, +connections are not bound to a particular local IP address and +it listens only on IPv4 (but not IPv6) addresses, but +\fIip\fR may be specified to listen only for connections to the given +\fIip\fR, either IPv4 or IPv6 address. If \fIip\fR is +an IPv6 address, then wrap \fIip\fR with square brackets, e.g.: +\fBptcp:6640:[::1]\fR. +.IP +The \fBro:\fR element indicates that database modifications are not allowed +on this connection. +. +.IP "\fBpunix:ro:\fIfile\fR" +On POSIX, listen on the Unix domain server socket named \fIfile\fR for a +connection. +.IP +On Windows, listen on a local named pipe. A file is created in the +path \fIfile\fR to mimic the behavior of a Unix domain socket. +.IP +The \fBro:\fR element indicates that database modifications are not allowed +on this connection. diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at index 89a5bf9..3e0416a 100644 --- a/tests/ovsdb-server.at +++ b/tests/ovsdb-server.at @@ -1367,3 +1367,227 @@ AT_CHECK([diff dump1 dump2]) dnl OVSDB_SERVER_SHUTDOWN dnl OVSDB_SERVER_SHUTDOWN2 AT_CLEANUP + +AT_SETUP([ovsdb-server/read-only ptcp connection]) +AT_KEYWORDS([ovsdb server read-only]) +ordinal_schema > schema +AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=ptcp:ro:0:127.0.0.1 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 ordinals], [0], [5.1.3 +]) + +AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT \ + ['["ordinals", + {"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 + +AT_SETUP([ovsdb-server/read-only punix connection]) +AT_KEYWORDS([ovsdb server read-only]) +ordinal_schema > schema +AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=punix:ro:test-socket db], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client get-schema-version unix:test-socket ordinals], [0], [5.1.3 +]) + +AT_CHECK([ovsdb-client transact unix:test-socket \ + ['["ordinals", + {"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 + +AT_SETUP([ovsdb-server/read-only pssl connection]) +AT_KEYWORDS([ovsdb server read-only]) +AT_SKIP_IF([test "$HAVE_OPENSSL" = no]) +PKIDIR="$(cd $abs_top_builddir/tests && pwd)" +AT_SKIP_IF([expr "$PKIDIR" : ".*[ '\" +\\]"]) +AT_DATA([schema], + [[{"name": "mydb", + "tables": { + "SSL": { + "columns": { + "private_key": {"type": "string"}, + "certificate": {"type": "string"}, + "ca_cert": {"type": "string"}}}, + "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], [stdout], [ignore]) +AT_CHECK( + [[ovsdb-tool transact db \ + '["mydb", + {"op": "insert", + "table": "SSL", + "row": {"private_key": "'"$PKIDIR/testpki-privkey2.pem"'", + "certificate": "'"$PKIDIR/testpki-cert2.pem"'", + "ca_cert": "'"$PKIDIR/testpki-cacert.pem"'"}}]']], + [0], [ignore], [ignore]) +AT_CHECK( + [ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid \ + --private-key=db:mydb,SSL,private_key \ + --certificate=db:mydb,SSL,certificate \ + --ca-cert=db:mydb,SSL,ca_cert \ + --remote=pssl:ro:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], + [0], [ignore], [ignore]) +PARSE_LISTENING_PORT([ovsdb-server.log], [SSL_PORT]) +AT_CHECK([ovsdb-client \ + --private-key=$PKIDIR/testpki-privkey.pem \ + --certificate=$PKIDIR/testpki-cert.pem \ + --ca-cert=$PKIDIR/testpki-cacert.pem \ + get-schema-version ssl:127.0.0.1:$SSL_PORT mydb], \ + [0], [5.1.3 +]) +AT_CHECK([ovsdb-client \ + --private-key=$PKIDIR/testpki-privkey.pem \ + --certificate=$PKIDIR/testpki-cert.pem \ + --ca-cert=$PKIDIR/testpki-cacert.pem \ + transact ssl:127.0.0.1:$SSL_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 + +AT_SETUP([ovsdb-server/read-only tcp connection]) +AT_KEYWORDS([ovsdb server read-only]) +ordinal_schema > schema +AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) + +# find a free TCP port +AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore]) +on_exit 'kill `cat pid`' +PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT]) +OVSDB_SERVER_SHUTDOWN + +AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=tcp:ro:127.0.0.1:$TCP_PORT db], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client -vwarn get-schema-version ptcp:$TCP_PORT:127.0.0.1 ordinals], [0], [5.1.3 +]) + +AT_CHECK([ovsdb-client transact ptcp:$TCP_PORT:127.0.0.1 \ + ['["ordinals", + {"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 + +AT_SETUP([ovsdb-server/read-only unix connection]) +AT_KEYWORDS([ovsdb server read-only]) +ordinal_schema > schema +AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --unixctl="`pwd`"/unixctl --remote=unix:ro:test-socket db], [0], [ignore], [ignore]) +ovsdb-client -v get-schema-version punix:test-socket ordinals +AT_CHECK([ovsdb-client -vwarn get-schema-version punix:test-socket ordinals], [0], [5.1.3 +]) + +AT_CHECK([ovsdb-client transact punix:test-socket \ + ['["ordinals", + {"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 + +AT_SETUP([ovsdb-server/read-only ssl connection]) +AT_KEYWORDS([ovsdb server read-only]) +AT_SKIP_IF([test "$HAVE_OPENSSL" = no]) +PKIDIR="$(cd $abs_top_builddir/tests && pwd)" +AT_SKIP_IF([expr "$PKIDIR" : ".*[ '\" +\\]"]) +AT_DATA([schema], + [[{"name": "mydb", + "tables": { + "SSL": { + "columns": { + "private_key": {"type": "string"}, + "certificate": {"type": "string"}, + "ca_cert": {"type": "string"}}}, + "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], [stdout], [ignore]) +AT_CHECK( + [[ovsdb-tool transact db \ + '["mydb", + {"op": "insert", + "table": "SSL", + "row": {"private_key": "'"$PKIDIR/testpki-privkey2.pem"'", + "certificate": "'"$PKIDIR/testpki-cert2.pem"'", + "ca_cert": "'"$PKIDIR/testpki-cacert.pem"'"}}]']], + [0], [ignore], [ignore]) + +# find a free TCP port +AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore]) +on_exit 'kill `cat pid`' +PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT]) +OVSDB_SERVER_SHUTDOWN + +AT_CHECK( + [ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid \ + --private-key=db:mydb,SSL,private_key \ + --certificate=db:mydb,SSL,certificate \ + --ca-cert=db:mydb,SSL,ca_cert \ + --remote=ssl:ro:127.0.0.1:$TCP_PORT --unixctl="`pwd`"/unixctl db], + [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client -vwarn \ + --private-key=$PKIDIR/testpki-privkey.pem \ + --certificate=$PKIDIR/testpki-cert.pem \ + --ca-cert=$PKIDIR/testpki-cacert.pem \ + get-schema-version pssl:$TCP_PORT:127.0.0.1 mydb], \ + [0], [5.1.3 +]) +AT_CHECK([ovsdb-client \ + --private-key=$PKIDIR/testpki-privkey.pem \ + --certificate=$PKIDIR/testpki-cert.pem \ + --ca-cert=$PKIDIR/testpki-cacert.pem \ + transact pssl:$TCP_PORT:127.0.0.1 \ + ['["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 + diff --git a/tests/test-jsonrpc.c b/tests/test-jsonrpc.c index 684601a..7ee0681 100644 --- a/tests/test-jsonrpc.c +++ b/tests/test-jsonrpc.c @@ -108,7 +108,7 @@ usage(void) " request REMOTE METHOD PARAMS send request, print reply\n" " notify REMOTE METHOD PARAMS send notification and exit\n", program_name, program_name); - stream_usage("JSON-RPC", true, true, true); + stream_usage("JSON-RPC", true, true, true, false); daemon_usage(); vlog_usage(); printf("\nOther options:\n" diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index e710095..c61f7df 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -424,7 +424,7 @@ Options:\n\ vlog_usage(); printf("\ --no-syslog equivalent to --verbose=vsctl:syslog:warn\n"); - stream_usage("database", true, true, false); + stream_usage("database", true, true, false, false); printf("\n\ Other options:\n\ -h, --help display this help message\n\ diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c index 72448bb..ebc8d12 100644 --- a/vswitchd/ovs-vswitchd.c +++ b/vswitchd/ovs-vswitchd.c @@ -250,7 +250,7 @@ usage(void) "where DATABASE is a socket on which ovsdb-server is listening\n" " (default: \"unix:%s/db.sock\").\n", program_name, program_name, ovs_rundir()); - stream_usage("DATABASE", true, false, true); + stream_usage("DATABASE", true, false, true, false); daemon_usage(); vlog_usage(); printf("\nDPDK options:\n" diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c index 245ba0d..01586ac 100644 --- a/vtep/vtep-ctl.c +++ b/vtep/vtep-ctl.c @@ -370,7 +370,7 @@ Options:\n\ vlog_usage(); printf("\ --no-syslog equivalent to --verbose=vtep_ctl:syslog:warn\n"); - stream_usage("database", true, true, false); + stream_usage("database", true, true, false, false); printf("\n\ Other options:\n\ -h, --help display this help message\n\ -- 2.5.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev