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

ovsdb-client: support monitor-cond method

Add monitor_cond method to ovsdb-client. Enable testing of monitor_cond_change
via unixctl command.Add unit tests for monitor_cond and monitor_cond_change.
See ovsdb-client(1) man page for details.
Replace monitor2 with monitor_cond.

Signed-off-by: Liran Schour <lirans@il.ibm.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Liran Schour 2016-07-18 11:45:55 +03:00 committed by Ben Pfaff
parent f0d7ae1951
commit c383f3bf81
10 changed files with 391 additions and 80 deletions

3
NEWS
View File

@ -1,7 +1,8 @@
Post-v2.5.0 Post-v2.5.0
--------------------- ---------------------
- ovsdb-server: - ovsdb-server:
* New "monitor2" and "update2" extensions to RFC 7047. * New "monitor_cond" "monitor_cond_update" and "update2" extensions to
RFC 7047.
- OpenFlow: - OpenFlow:
* OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY. * OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
* OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported. * OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported.

View File

@ -79,8 +79,8 @@ enum ovsdb_idl_state {
IDL_S_SCHEMA_REQUESTED, IDL_S_SCHEMA_REQUESTED,
IDL_S_MONITOR_REQUESTED, IDL_S_MONITOR_REQUESTED,
IDL_S_MONITORING, IDL_S_MONITORING,
IDL_S_MONITOR2_REQUESTED, IDL_S_MONITOR_COND_REQUESTED,
IDL_S_MONITORING2, IDL_S_MONITORING_COND,
IDL_S_NO_SCHEMA IDL_S_NO_SCHEMA
}; };
@ -154,7 +154,7 @@ static struct vlog_rate_limit semantic_rl = VLOG_RATE_LIMIT_INIT(1, 5);
static void ovsdb_idl_clear(struct ovsdb_idl *); static void ovsdb_idl_clear(struct ovsdb_idl *);
static void ovsdb_idl_send_schema_request(struct ovsdb_idl *); static void ovsdb_idl_send_schema_request(struct ovsdb_idl *);
static void ovsdb_idl_send_monitor_request(struct ovsdb_idl *); static void ovsdb_idl_send_monitor_request(struct ovsdb_idl *);
static void ovsdb_idl_send_monitor2_request(struct ovsdb_idl *); static void ovsdb_idl_send_monitor_cond_request(struct ovsdb_idl *);
static void ovsdb_idl_parse_update(struct ovsdb_idl *, const struct json *, static void ovsdb_idl_parse_update(struct ovsdb_idl *, const struct json *,
enum ovsdb_update_version); enum ovsdb_update_version);
static struct ovsdb_error *ovsdb_idl_parse_update__(struct ovsdb_idl *, static struct ovsdb_error *ovsdb_idl_parse_update__(struct ovsdb_idl *,
@ -413,20 +413,20 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
case IDL_S_SCHEMA_REQUESTED: case IDL_S_SCHEMA_REQUESTED:
/* Reply to our "get_schema" request. */ /* Reply to our "get_schema" request. */
idl->schema = json_clone(msg->result); idl->schema = json_clone(msg->result);
ovsdb_idl_send_monitor2_request(idl); ovsdb_idl_send_monitor_cond_request(idl);
idl->state = IDL_S_MONITOR2_REQUESTED; idl->state = IDL_S_MONITOR_COND_REQUESTED;
break; break;
case IDL_S_MONITOR_REQUESTED: case IDL_S_MONITOR_REQUESTED:
case IDL_S_MONITOR2_REQUESTED: case IDL_S_MONITOR_COND_REQUESTED:
/* Reply to our "monitor" or "monitor2" request. */ /* Reply to our "monitor" or "monitor_cond" request. */
idl->change_seqno++; idl->change_seqno++;
ovsdb_idl_clear(idl); ovsdb_idl_clear(idl);
if (idl->state == IDL_S_MONITOR_REQUESTED) { if (idl->state == IDL_S_MONITOR_REQUESTED) {
idl->state = IDL_S_MONITORING; idl->state = IDL_S_MONITORING;
ovsdb_idl_parse_update(idl, msg->result, OVSDB_UPDATE); ovsdb_idl_parse_update(idl, msg->result, OVSDB_UPDATE);
} else { /* IDL_S_MONITOR2_REQUESTED. */ } else { /* IDL_S_MONITOR_COND_REQUESTED. */
idl->state = IDL_S_MONITORING2; idl->state = IDL_S_MONITORING_COND;
ovsdb_idl_parse_update(idl, msg->result, OVSDB_UPDATE2); ovsdb_idl_parse_update(idl, msg->result, OVSDB_UPDATE2);
} }
@ -437,7 +437,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
break; break;
case IDL_S_MONITORING: case IDL_S_MONITORING:
case IDL_S_MONITORING2: case IDL_S_MONITORING_COND:
case IDL_S_NO_SCHEMA: case IDL_S_NO_SCHEMA:
default: default:
OVS_NOT_REACHED(); OVS_NOT_REACHED();
@ -464,7 +464,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
/* Someone else stole our lock. */ /* Someone else stole our lock. */
ovsdb_idl_parse_lock_notify(idl, msg->params, false); ovsdb_idl_parse_lock_notify(idl, msg->params, false);
} else if (msg->type == JSONRPC_ERROR } else if (msg->type == JSONRPC_ERROR
&& idl->state == IDL_S_MONITOR2_REQUESTED && idl->state == IDL_S_MONITOR_COND_REQUESTED
&& idl->request_id && idl->request_id
&& json_equal(idl->request_id, msg->id)) { && json_equal(idl->request_id, msg->id)) {
if (msg->error && !strcmp(json_string(msg->error), if (msg->error && !strcmp(json_string(msg->error),
@ -1066,9 +1066,9 @@ log_parse_update_error(struct ovsdb_error *error)
} }
static void static void
ovsdb_idl_send_monitor2_request(struct ovsdb_idl *idl) ovsdb_idl_send_monitor_cond_request(struct ovsdb_idl *idl)
{ {
ovsdb_idl_send_monitor_request__(idl, "monitor2"); ovsdb_idl_send_monitor_request__(idl, "monitor_cond");
} }
static void static void
@ -3254,7 +3254,7 @@ ovsdb_idl_update_has_lock(struct ovsdb_idl *idl, bool new_has_lock)
{ {
if (new_has_lock && !idl->has_lock) { if (new_has_lock && !idl->has_lock) {
if (idl->state == IDL_S_MONITORING || if (idl->state == IDL_S_MONITORING ||
idl->state == IDL_S_MONITORING2) { idl->state == IDL_S_MONITORING_COND) {
idl->change_seqno++; idl->change_seqno++;
} else { } else {
/* We're setting up a session, so don't signal that the database /* We're setting up a session, so don't signal that the database

View File

@ -46,9 +46,9 @@ VLOG_DEFINE_THIS_MODULE(ovsdb_jsonrpc_server);
struct ovsdb_jsonrpc_remote; struct ovsdb_jsonrpc_remote;
struct ovsdb_jsonrpc_session; struct ovsdb_jsonrpc_session;
/* Set false to defeature monitor2, causing jsonrpc to respond to monitor2 /* Set false to defeature monitor_cond, causing jsonrpc to respond to
* method with an error. */ * monitor_cond method with an error. */
static bool monitor2_enable__ = true; static bool monitor_cond_enable__ = true;
/* Message rate-limiting. */ /* Message rate-limiting. */
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@ -873,8 +873,8 @@ ovsdb_jsonrpc_session_got_request(struct ovsdb_jsonrpc_session *s,
reply = execute_transaction(s, db, request); reply = execute_transaction(s, db, request);
} }
} else if (!strcmp(request->method, "monitor") || } else if (!strcmp(request->method, "monitor") ||
(monitor2_enable__ && !strcmp(request->method, "monitor2")) || (monitor_cond_enable__ && !strcmp(request->method,
!strcmp(request->method, "monitor_cond")) { "monitor_cond"))) {
struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply); struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply);
if (!reply) { if (!reply) {
int l = strlen(request->method) - strlen("monitor"); int l = strlen(request->method) - strlen("monitor");
@ -1559,8 +1559,8 @@ ovsdb_jsonrpc_monitor_flush_all(struct ovsdb_jsonrpc_session *s)
} }
void void
ovsdb_jsonrpc_disable_monitor2(void) ovsdb_jsonrpc_disable_monitor_cond(void)
{ {
/* Once disabled, it is not possible to re-enable it. */ /* Once disabled, it is not possible to re-enable it. */
monitor2_enable__ = false; monitor_cond_enable__ = false;
} }

View File

@ -71,6 +71,6 @@ void ovsdb_jsonrpc_server_get_memory_usage(const struct ovsdb_jsonrpc_server *,
struct ovsdb_jsonrpc_monitor; struct ovsdb_jsonrpc_monitor;
void ovsdb_jsonrpc_monitor_destroy(struct ovsdb_jsonrpc_monitor *); void ovsdb_jsonrpc_monitor_destroy(struct ovsdb_jsonrpc_monitor *);
void ovsdb_jsonrpc_disable_monitor2(void); void ovsdb_jsonrpc_disable_monitor_cond(void);
#endif /* ovsdb/jsonrpc-server.h */ #endif /* ovsdb/jsonrpc-server.h */

View File

@ -33,10 +33,8 @@ ovsdb\-client \- command-line interface to \fBovsdb-server\fR(1)
.br .br
\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR \fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR
.br .br
\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR \fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor-cond\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fIconditions
[\fIcolumn\fR[\fB,\fIcolumn\fR]...]... \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]...
.br
\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR
.br .br
\fBovsdb\-client help\fR \fBovsdb\-client help\fR
.IP "Output formatting options:" .IP "Output formatting options:"
@ -113,12 +111,12 @@ specified, only that table is retrieved. If at least one \fIcolumn\fR
is specified, only those columns are retrieved. is specified, only those columns are retrieved.
. .
.IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..." .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
.IQ "\fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..." .IQ "\fBmonitor-cond\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fIconditions\fR \fItable\fR [\fIcolumn\fR[\fB,\fIcolumn\fR]...]..."
Connects to \fIserver\fR and monitors the contents of \fItable\fR in Connects to \fIserver\fR and monitors the contents of rows that match conditions in
\fIdatabase\fR. By default, the initial contents of \fItable\fR are \fItable\fR in \fIdatabase\fR. By default, the initial contents of \fItable\fR are
printed, followed by each change as it occurs. If at least one printed, followed by each change as it occurs. If conditions empty,
\fIcolumn\fR is specified, only those columns are monitored. The all rows will be monitored. If at least one \fIcolumn\fR is specified, only those
following \fIcolumn\fR names have special meanings: columns are monitored. The following \fIcolumn\fR names have special meanings:
.RS .RS
.IP "\fB!initial\fR" .IP "\fB!initial\fR"
Do not print the initial contents of the specified columns. Do not print the initial contents of the specified columns.
@ -136,16 +134,18 @@ each group. Whether multiple groups or only a single group is
specified, any given column may only be mentioned once on the command specified, any given column may only be mentioned once on the command
line. line.
.IP .IP
If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmointor2\fR, then \fBconditions\fR is a JSON array of <condition> as defined in RFC 7047 5.1
with the following change: A condition can be either a 3-element JSON array
as deescribed in the RFC or a boolean value..
.IP
If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmonitor-cond\fR, then
\fBovsdb\-client\fR detaches after it has successfully received and \fBovsdb\-client\fR detaches after it has successfully received and
printed the initial contents of \fItable\fR. printed the initial contents of \fItable\fR.
.IP .IP
The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
session with the server. The \fBmonitor2\fR command uses RFC 7047 session with the server. The \fBmonitor-cond\fR command uses RFC 7047
extension "monitor2" method. See \fBovsdb\-server\fR(1) for details. extension "monitor_cond" method. See \fBovsdb\-server\fR(1) for details.
.
.IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR" .IP "\fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR"
.IQ "\fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR"
Connects to \fIserver\fR and monitors the contents of all tables in Connects to \fIserver\fR and monitors the contents of all tables in
\fIdatabase\fR. Prints initial values and all kinds of changes to all \fIdatabase\fR. Prints initial values and all kinds of changes to all
columns in the database. The \fB\-\-detach\fR option causes columns in the database. The \fB\-\-detach\fR option causes
@ -153,8 +153,7 @@ columns in the database. The \fB\-\-detach\fR option causes
prints the initial database contents. prints the initial database contents.
.IP .IP
The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
session with the server. The \fBmonitor2\fR command uses RFC 7047 session with the server.
extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
. .
.SH OPTIONS .SH OPTIONS
.SS "Output Formatting Options" .SS "Output Formatting Options"
@ -165,13 +164,13 @@ The following options controlling output formatting:
.so lib/table.man .so lib/table.man
. .
.IP "\fB\-\-timestamp\fR" .IP "\fB\-\-timestamp\fR"
For the \fBmonitor\fR and \fBmonitor2\fR commands, add a timestamp to each For the \fBmonitor\fR and \fBmonitor-cond\fR commands, add a timestamp to each
table update. Most output formats add the timestamp on a line of its own table update. Most output formats add the timestamp on a line of its own
just above the table. The JSON output format puts the timestamp in a just above the table. The JSON output format puts the timestamp in a
member of the top-level JSON object named \fBtime\fR. member of the top-level JSON object named \fBtime\fR.
. .
.SS "Daemon Options" .SS "Daemon Options"
The daemon options apply only to the \fBmonitor\fR and \fBmonitor2\fR commands. The daemon options apply only to the \fBmonitor\fR and \fBmonitor-cond\fR commands.
With any other command, they have no effect. With any other command, they have no effect.
.ds DD .ds DD
.so lib/daemon.man .so lib/daemon.man

View File

@ -45,6 +45,7 @@
#include "stream-ssl.h" #include "stream-ssl.h"
#include "table.h" #include "table.h"
#include "monitor.h" #include "monitor.h"
#include "condition.h"
#include "timeval.h" #include "timeval.h"
#include "unixctl.h" #include "unixctl.h"
#include "util.h" #include "util.h"
@ -257,12 +258,14 @@ usage(void)
" monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n" " monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
" COLUMNs may include !initial, !insert, !delete, !modify\n" " COLUMNs may include !initial, !insert, !delete, !modify\n"
" to avoid seeing the specified kinds of changes.\n" " to avoid seeing the specified kinds of changes.\n"
"\n monitor-cond [SERVER] [DATABASE] CONDITION TABLE [COLUMN,...]...\n"
" monitor contents that match CONDITION of COLUMNs in TABLE in\n"
" DATABASE on SERVER.\n"
" COLUMNs may include !initial, !insert, !delete, !modify\n"
" to avoid seeing the specified kinds of changes.\n"
"\n monitor [SERVER] [DATABASE] ALL\n" "\n monitor [SERVER] [DATABASE] ALL\n"
" monitor all changes to all columns in all tables\n" " monitor all changes to all columns in all tables\n"
" in DATBASE on SERVER.\n" " in DATBASE on SERVER.\n"
"\n monitor2 [SERVER] [DATABASE] ALL\n"
" same usage as monitor, but uses \"monitor2\" method over"
" the wire."
"\n dump [SERVER] [DATABASE]\n" "\n dump [SERVER] [DATABASE]\n"
" dump contents of DATABASE on SERVER to stdout\n" " dump contents of DATABASE on SERVER to stdout\n"
"\nThe default SERVER is unix:%s/db.sock.\n" "\nThe default SERVER is unix:%s/db.sock.\n"
@ -837,15 +840,42 @@ ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED,
} }
} }
static void
ovsdb_client_cond_change(struct unixctl_conn *conn, int argc OVS_UNUSED,
const char *argv[], void *rpc_)
{
struct jsonrpc *rpc = rpc_;
struct json *monitor_cond_update_requests = json_object_create();
struct json *monitor_cond_update_request = json_object_create();
struct json *params;
struct jsonrpc_msg *request;
json_object_put(monitor_cond_update_request, "where",
json_from_string(argv[2]));
json_object_put(monitor_cond_update_requests,
argv[1],
json_array_create_1(monitor_cond_update_request));
params = json_array_create_3(json_null_create(),json_null_create(),
monitor_cond_update_requests);
request = jsonrpc_create_request("monitor_cond_change", params, NULL);
jsonrpc_send(rpc, request);
VLOG_DBG("cond change %s %s", argv[1], argv[2]);
unixctl_command_reply(conn, "condiiton changed");
}
static void static void
add_monitored_table(int argc, char *argv[], add_monitored_table(int argc, char *argv[],
const char *server, const char *database, const char *server, const char *database,
struct json *condition,
struct ovsdb_table_schema *table, struct ovsdb_table_schema *table,
struct json *monitor_requests, struct json *monitor_requests,
struct monitored_table **mts, struct monitored_table **mts,
size_t *n_mts, size_t *allocated_mts) size_t *n_mts, size_t *allocated_mts)
{ {
struct json *monitor_request_array; struct json *monitor_request_array, *mr;
struct monitored_table *mt; struct monitored_table *mt;
if (*n_mts >= *allocated_mts) { if (*n_mts >= *allocated_mts) {
@ -860,19 +890,24 @@ add_monitored_table(int argc, char *argv[],
int i; int i;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
json_array_add( mr = parse_monitor_columns(argv[i], server, database, table,
monitor_request_array, &mt->columns);
parse_monitor_columns(argv[i], server, database, table, if (i == 1 && condition) {
&mt->columns)); json_object_put(mr, "where", condition);
}
json_array_add(monitor_request_array, mr);
} }
} else { } else {
/* Allocate a writable empty string since parse_monitor_columns() /* Allocate a writable empty string since parse_monitor_columns()
* is going to strtok() it and that's risky with literal "". */ * is going to strtok() it and that's risky with literal "". */
char empty[] = ""; char empty[] = "";
json_array_add(
monitor_request_array, mr = parse_monitor_columns(empty, server, database,
parse_monitor_columns(empty, server, database, table, &mt->columns);
table, &mt->columns)); if (condition) {
json_object_put(mr, "where", condition);
}
json_array_add(monitor_request_array, mr);
} }
json_object_put(monitor_requests, table->name, monitor_request_array); json_object_put(monitor_requests, table->name, monitor_request_array);
@ -894,7 +929,7 @@ destroy_monitored_table(struct monitored_table *mts, size_t n)
static void static void
do_monitor__(struct jsonrpc *rpc, const char *database, do_monitor__(struct jsonrpc *rpc, const char *database,
enum ovsdb_monitor_version version, enum ovsdb_monitor_version version,
int argc, char *argv[]) int argc, char *argv[], struct json *condition)
{ {
const char *server = jsonrpc_get_name(rpc); const char *server = jsonrpc_get_name(rpc);
const char *table_name = argv[0]; const char *table_name = argv[0];
@ -926,6 +961,8 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
ovsdb_client_block, &blocked); ovsdb_client_block, &blocked);
unixctl_command_register("ovsdb-client/unblock", "", 0, 0, unixctl_command_register("ovsdb-client/unblock", "", 0, 0,
ovsdb_client_unblock, &blocked); ovsdb_client_unblock, &blocked);
unixctl_command_register("ovsdb-client/cond_change", "TABLE COND", 2, 2,
ovsdb_client_cond_change, rpc);
} else { } else {
unixctl = NULL; unixctl = NULL;
} }
@ -945,17 +982,21 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
server, database, table_name); server, database, table_name);
} }
add_monitored_table(argc, argv, server, database, table, add_monitored_table(argc, argv, server, database, condition, table,
monitor_requests, &mts, &n_mts, &allocated_mts); monitor_requests, &mts, &n_mts, &allocated_mts);
} else { } else {
size_t n = shash_count(&schema->tables); size_t n = shash_count(&schema->tables);
const struct shash_node **nodes = shash_sort(&schema->tables); const struct shash_node **nodes = shash_sort(&schema->tables);
size_t i; size_t i;
if (condition) {
ovs_fatal(0, "ALL tables are not allowed with condition");
}
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct ovsdb_table_schema *table = nodes[i]->data; struct ovsdb_table_schema *table = nodes[i]->data;
add_monitored_table(argc, argv, server, database, table, add_monitored_table(argc, argv, server, database, NULL, table,
monitor_requests, monitor_requests,
&mts, &n_mts, &allocated_mts); &mts, &n_mts, &allocated_mts);
} }
@ -964,7 +1005,7 @@ do_monitor__(struct jsonrpc *rpc, const char *database,
monitor = json_array_create_3(json_string_create(database), monitor = json_array_create_3(json_string_create(database),
json_null_create(), monitor_requests); json_null_create(), monitor_requests);
const char *method = version == OVSDB_MONITOR_V2 ? "monitor2" const char *method = version == OVSDB_MONITOR_V2 ? "monitor_cond"
: "monitor"; : "monitor";
request = jsonrpc_create_request(method, monitor, NULL); request = jsonrpc_create_request(method, monitor, NULL);
@ -1048,14 +1089,31 @@ static void
do_monitor(struct jsonrpc *rpc, const char *database, do_monitor(struct jsonrpc *rpc, const char *database,
int argc, char *argv[]) int argc, char *argv[])
{ {
do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv); do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv, NULL);
} }
static void static void
do_monitor2(struct jsonrpc *rpc, const char *database, do_monitor_cond(struct jsonrpc *rpc, const char *database,
int argc, char *argv[]) int argc, char *argv[])
{ {
do_monitor__(rpc, database, OVSDB_MONITOR_V2, argc, argv); struct ovsdb_condition cnd;
struct json *condition = NULL;
struct ovsdb_schema *schema;
struct ovsdb_table_schema *table;
const char *table_name = argv[1];
ovs_assert(argc > 1);
schema = fetch_schema(rpc, database);
table = shash_find_data(&schema->tables, table_name);
if (!table) {
ovs_fatal(0, "%s does not have a table named \"%s\"",
database, table_name);
}
condition = parse_json(argv[0]);
check_ovsdb_error(ovsdb_condition_from_json(table, condition,
NULL, &cnd));
ovsdb_condition_destroy(&cnd);
do_monitor__(rpc, database, OVSDB_MONITOR_V2, --argc, ++argv, condition);
} }
struct dump_table_aux { struct dump_table_aux {
@ -1328,7 +1386,7 @@ static const struct ovsdb_client_command all_commands[] = {
{ "list-columns", NEED_DATABASE, 0, 1, do_list_columns }, { "list-columns", NEED_DATABASE, 0, 1, do_list_columns },
{ "transact", NEED_RPC, 1, 1, do_transact }, { "transact", NEED_RPC, 1, 1, do_transact },
{ "monitor", NEED_DATABASE, 1, INT_MAX, do_monitor }, { "monitor", NEED_DATABASE, 1, INT_MAX, do_monitor },
{ "monitor2", NEED_DATABASE, 1, INT_MAX, do_monitor2 }, { "monitor-cond", NEED_DATABASE, 2, 3, do_monitor_cond },
{ "dump", NEED_DATABASE, 0, INT_MAX, do_dump }, { "dump", NEED_DATABASE, 0, INT_MAX, do_dump },
{ "help", NEED_NONE, 0, INT_MAX, do_help }, { "help", NEED_NONE, 0, INT_MAX, do_help },

View File

@ -76,7 +76,7 @@ static unixctl_cb_func ovsdb_server_compact;
static unixctl_cb_func ovsdb_server_reconnect; static unixctl_cb_func ovsdb_server_reconnect;
static unixctl_cb_func ovsdb_server_perf_counters_clear; static unixctl_cb_func ovsdb_server_perf_counters_clear;
static unixctl_cb_func ovsdb_server_perf_counters_show; static unixctl_cb_func ovsdb_server_perf_counters_show;
static unixctl_cb_func ovsdb_server_disable_monitor2; static unixctl_cb_func ovsdb_server_disable_monitor_cond;
struct server_config { struct server_config {
struct sset *remotes; struct sset *remotes;
@ -335,9 +335,9 @@ main(int argc, char *argv[])
ovsdb_server_perf_counters_clear, NULL); ovsdb_server_perf_counters_clear, NULL);
/* Simulate the behavior of OVS release prior to version 2.5 that /* Simulate the behavior of OVS release prior to version 2.5 that
* does not support the monitor2 method. */ * does not support the monitor_cond method. */
unixctl_command_register("ovsdb-server/disable-monitor2", "", 0, 0, unixctl_command_register("ovsdb-server/disable-monitor-cond", "", 0, 0,
ovsdb_server_disable_monitor2, jsonrpc); ovsdb_server_disable_monitor_cond, jsonrpc);
main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting); main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting);
@ -1048,16 +1048,18 @@ ovsdb_server_perf_counters_clear(struct unixctl_conn *conn, int argc OVS_UNUSED,
unixctl_command_reply(conn, NULL); unixctl_command_reply(conn, NULL);
} }
/* "ovsdb-server/disable-monitor2": makes ovsdb-server drop all of its /* "ovsdb-server/disable-monitor-cond": makes ovsdb-server drop all of its
* JSON-RPC connections and reconnect. New sessions will not recognize * JSON-RPC connections and reconnect. New sessions will not recognize
* the 'monitor2' method. */ * the 'monitor_cond' method. */
static void static void
ovsdb_server_disable_monitor2(struct unixctl_conn *conn, int argc OVS_UNUSED, ovsdb_server_disable_monitor_cond(struct unixctl_conn *conn,
const char *argv[] OVS_UNUSED, void *jsonrpc_) int argc OVS_UNUSED,
const char *argv[] OVS_UNUSED,
void *jsonrpc_)
{ {
struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_; struct ovsdb_jsonrpc_server *jsonrpc = jsonrpc_;
ovsdb_jsonrpc_disable_monitor2(); ovsdb_jsonrpc_disable_monitor_cond();
ovsdb_jsonrpc_server_reconnect(jsonrpc); ovsdb_jsonrpc_server_reconnect(jsonrpc);
unixctl_command_reply(conn, NULL); unixctl_command_reply(conn, NULL);
} }

View File

@ -170,14 +170,14 @@ OVS_VSWITCHD_STOP(["/Not adding Unix domain socket controller/d"])
AT_CLEANUP AT_CLEANUP
dnl ---------------------------------------------------------------------- dnl ----------------------------------------------------------------------
dnl OVSDB server before release version 2.5 does not support the monitor2 dnl OVSDB server before release version 2.5 does not support the monitor_cond
dnl method. This test defeatures the OVSDB server to simulate an older dnl method. This test defeatures the OVSDB server to simulate an older
dnl OVSDB server and make sure ovs-vswitchd can still work with it dnl OVSDB server and make sure ovs-vswitchd can still work with it
AT_SETUP([ovs-vswitchd -- Compatible with OVSDB server - w/o monitor2]) AT_SETUP([ovs-vswitchd -- Compatible with OVSDB server - w/o monitor_cond])
OVS_VSWITCHD_START OVS_VSWITCHD_START
dnl defeature OVSDB server -- no monitor2 dnl defeature OVSDB server -- no monitor_cond
AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/disable-monitor2]) AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/disable-monitor-cond])
sleep 1 sleep 1

View File

@ -649,13 +649,13 @@ test-ovsdb|ovsdb_idl|link1 table in idltest database lacks l2 column (database n
# Check that ovsdb-idl sent on "monitor" request and that it didn't # Check that ovsdb-idl sent on "monitor" request and that it didn't
# mention that table or column, and (for paranoia) that it did mention another # mention that table or column, and (for paranoia) that it did mention another
# table and column. # table and column.
AT_CHECK([grep -c '"monitor\|monitor2"' stderr], [0], [1 AT_CHECK([grep -c '"monitor\|monitor_cond"' stderr], [0], [1
]) ])
AT_CHECK([grep '"monitor\|monitor2"' stderr | grep link2], [1]) AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep link2], [1])
AT_CHECK([grep '"monitor\|monitor2"' stderr | grep l2], [1]) AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep l2], [1])
AT_CHECK([grep '"monitor\|monitor2"' stderr | grep -c '"link1"'], [0], [1 AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep -c '"link1"'], [0], [1
]) ])
AT_CHECK([grep '"monitor\|monitor2"' stderr | grep -c '"ua"'], [0], [1 AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep -c '"ua"'], [0], [1
]) ])
OVSDB_SERVER_SHUTDOWN OVSDB_SERVER_SHUTDOWN
AT_CLEANUP AT_CLEANUP

View File

@ -45,6 +45,54 @@ m4_define([OVSDB_CHECK_MONITOR],
AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL} $srcdir/uuidfilt.pl], [0], [$7], [ignore]) AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL} $srcdir/uuidfilt.pl], [0], [$7], [ignore])
AT_CLEANUP]) AT_CLEANUP])
# OVSDB_CHECK_MONITOR_COND(TITLE, SCHEMA, [PRE-MONITOR-TXN], DB, TABLE,
# TRANSACTIONS, OUTPUT, CONDITIONS, [COLUMNS], [KEYWORDS],
# [CONDITIONS_CHANGE])
#
# Creates a database with the given SCHEMA, starts an ovsdb-server on
# that database, and runs each of the TRANSACTIONS (which should be a
# quoted list of quoted strings) against it with ovsdb-client one at a
# time. COLUMNS, if specified, is passed to ovsdb-client as the set
# of columns and operations to select.
#
# Checks that the overall output is OUTPUT, but UUIDs in the output
# are replaced by markers of the form <N> where N is a number. The
# first unique UUID is replaced by <0>, the next by <1>, and so on.
# If a given UUID appears more than once it is always replaced by the
# same marker.
#
# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
m4_define([OVSDB_CHECK_MONITOR_COND],
[AT_SETUP([$1])
AT_KEYWORDS([ovsdb server monitor monitor-cond positive $10])
$2 > schema
AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
m4_foreach([txn], [$3],
[AT_CHECK([ovsdb-tool transact db 'txn'], [0], [ignore], [ignore])])
AT_CAPTURE_FILE([ovsdb-server-log])
AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/server-pid --remote=punix:socket --unixctl="`pwd`"/unixctl --log-file="`pwd`"/ovsdb-server-log db >/dev/null 2>&1],
[0], [], [])
if test "$IS_WIN32" = "yes"; then
AT_CHECK([ovsdb-client -vjsonrpc --pidfile="`pwd`"/client-pid -d json monitor-cond --format=csv unix:socket $4 '[$8]' $5 $9 > output &],
[0], [ignore], [ignore], [kill `cat server-pid`])
sleep 1
else
AT_CHECK([ ovsdb-client -vjsonrpc --detach --no-chdir --pidfile="`pwd`"/client-pid -d json monitor-cond --format=csv unix:socket $4 '[$8]' $5 $9 > output],
[0], [ignore], [ignore], [kill `cat server-pid`])
fi
m4_foreach([txn], [$6],
[AT_CHECK([ovsdb-client transact unix:socket 'txn'], [0],
[ignore], [ignore], [kill `cat server-pid client-pid`])])
CLIENT_PID=`cat "$OVS_RUNDIR"/client-pid 2>/dev/null`
m4_foreach([cond], [$10],
[AT_CHECK([ovs-appctl -t "`pwd`"/ovsdb-client.$CLIENT_PID.ctl ovsdb-client/cond_change $5 'cond'], [0], [ignore], [ignore])])
AT_CHECK([ovsdb-client transact unix:socket '[["$4"]]'], [0],
[ignore], [ignore], [kill `cat server-pid client-pid`])
AT_CHECK([ovs-appctl -t "`pwd`"/unixctl -e exit], [0], [ignore], [ignore])
OVS_WAIT_UNTIL([test ! -e server-pid && test ! -e client-pid])
AT_CHECK([${PERL} $srcdir/ovsdb-monitor-sort.pl < output | ${PERL} $srcdir/uuidfilt.pl], [0], [$7], [ignore])
AT_CLEANUP])
OVSDB_CHECK_MONITOR([monitor insert into empty table], OVSDB_CHECK_MONITOR([monitor insert into empty table],
[ordinal_schema], [ordinal_schema],
[], [],
@ -323,3 +371,206 @@ OVSDB_CHECK_MONITOR([monitor modify only],
<0>,old,"""five""",,"[""uuid"",""<1>""]" <0>,old,"""five""",,"[""uuid"",""<1>""]"
,new,"""FIVE""",5,"[""uuid"",""<2>""]" ,new,"""FIVE""",5,"[""uuid"",""<2>""]"
]], [!initial,!insert,!delete]) ]], [!initial,!insert,!delete])
AT_BANNER([ovsdb -- ovsdb-monitor-cond conditional monitor only some operations])
OVSDB_CHECK_MONITOR_COND([monitor-cond empty condition],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 10, "name": "ten"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 11, "name": "eleven"}}]]]],
[[row,action,name,number,_version
<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
<2>,initial,"""two""",2,"[""uuid"",""<3>""]"
<4>,initial,"""zero""",,"[""uuid"",""<5>""]"
row,action,name,number,_version
<6>,insert,"""eleven""",11,"[""uuid"",""<7>""]"
<8>,insert,"""ten""",10,"[""uuid"",""<9>""]"
]],
[[]])
OVSDB_CHECK_MONITOR_COND([monitor-cond multiple conditions],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 10, "name": "ten"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 11, "name": "eleven"}}]]]],
[[row,action,name,number,_version
<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
row,action,name,number,_version
<2>,insert,"""ten""",10,"[""uuid"",""<3>""]"
]],
[[["name","==","one"],["name","==","ten"]]])
OVSDB_CHECK_MONITOR_COND([monitor-cond delete from populated table],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[[[["ordinals",
{"op": "delete",
"table": "ordinals",
"where": []}]]]],
[[row,action,name,number,_version
<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
row,action,name,number,_version
<0>,delete,,,
]],
[[["name","==","one"],["name","==","ten"]]])
OVSDB_CHECK_MONITOR_COND([monitor-cond insert due to modify],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[[[["ordinals",
{"op": "update",
"table": "ordinals",
"where": [["name", "==", "one"]],
"row": {"name": "ONE"}}]]]],
[[row,action,name,number,_version
<0>,insert,"""ONE""",1,"[""uuid"",""<1>""]"
]],
[[["name","==","ONE"]]],
[!initial,!delete,!modify])
OVSDB_CHECK_MONITOR_COND([monitor-cond delete due to modify],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[[[["ordinals",
{"op": "update",
"table": "ordinals",
"where": [["name", "==", "one"]],
"row": {"name": "ONE"}}]]]],
[[row,action,name,number,_version
<0>,delete,,,
]],
[[["name","==","one"]]],
[!initial,!insert,!modify])
OVSDB_CHECK_MONITOR_COND([monitor-cond condition non-monitored columns],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 10, "name": "ten"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 11, "name": "eleven"}}]]]],
[[row,action,number
<0>,initial,1
row,action,number
<1>,insert,10
]],
[[["name","==","one"],["name","==","ten"]]],
["number"])
OVSDB_CHECK_MONITOR_COND([monitor-cond-change],
[ordinal_schema],
[[[["ordinals",
{"op": "insert",
"table": "ordinals",
"row": {"number": 0, "name": "zero"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 1, "name": "one"}},
{"op": "insert",
"table": "ordinals",
"row": {"number": 2, "name": "two"}}]]]],
[ordinals], [ordinals],
[],
[[row,action,name,number,_version
<0>,initial,"""one""",1,"[""uuid"",""<1>""]"
<2>,initial,"""two""",2,"[""uuid"",""<3>""]"
<4>,initial,"""zero""",,"[""uuid"",""<5>""]"
row,action,name,number,_version
<4>,delete,,,
row,action,name,number,_version
<2>,delete,,,
row,action,name,number,_version
<0>,delete,,,
row,action,name,number,_version
<0>,insert,"""one""",1,"[""uuid"",""<1>""]"
<2>,insert,"""two""",2,"[""uuid"",""<3>""]"
<4>,insert,"""zero""",,"[""uuid"",""<5>""]"
]],
[[]],
[],
[[[[["name","==","one"],["name","==","two"]]]],
[[[["name","==","one"]]]],
[[[false]]],
[[[true]]]])