summaryrefslogtreecommitdiff
path: root/ovsdb
diff options
context:
space:
mode:
authorAndy Zhou <azhou@nicira.com>2015-10-15 14:09:07 -0700
committerAndy Zhou <azhou@ovn.org>2015-12-11 14:22:33 -0800
commit85226894ddec78f5aa7b7ab5dd8e8d11cc0fbde0 (patch)
treeee3afd26032d5febd87f269f620877e28f502be1 /ovsdb
parent92f8d65b1fa02c8bc0714e57ce6378e1a521a1a6 (diff)
downloadopenvswitch-85226894ddec78f5aa7b7ab5dd8e8d11cc0fbde0.tar.gz
ovsdb-client: support monitor2
Add monitor2 option to ovsdb-client. See ovsdb-client(1) manpage patch for details. Signed-off-by: Andy Zhou <azhou@nicira.com> Acked-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ovsdb')
-rw-r--r--ovsdb/monitor.h1
-rw-r--r--ovsdb/ovsdb-client.1.in29
-rw-r--r--ovsdb/ovsdb-client.c151
3 files changed, 168 insertions, 13 deletions
diff --git a/ovsdb/monitor.h b/ovsdb/monitor.h
index b1a5146b6..d6e9635e6 100644
--- a/ovsdb/monitor.h
+++ b/ovsdb/monitor.h
@@ -18,6 +18,7 @@
#define OVSDB_MONITOR_H
struct ovsdb_monitor;
+struct ovsdb_jsonrpc_monitor;
enum ovsdb_monitor_selection {
OJMS_INITIAL = 1 << 0, /* All rows when monitor is created. */
diff --git a/ovsdb/ovsdb-client.1.in b/ovsdb/ovsdb-client.1.in
index abad99c1b..5d99f5979 100644
--- a/ovsdb/ovsdb-client.1.in
+++ b/ovsdb/ovsdb-client.1.in
@@ -33,6 +33,11 @@ ovsdb\-client \- command-line interface to \fBovsdb-server\fR(1)
.br
\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor\fI \fR[\fIserver\fR] \fR[\fIdatabase\fR] \fBALL\fR
.br
+\fBovsdb\-client \fR[\fIoptions\fR] \fBmonitor2\fI \fR[\fIserver\fR] \fR[\fIdatabase\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
\fBovsdb\-client help\fR
.IP "Output formatting options:"
[\fB\-\-format=\fIformat\fR]
@@ -108,6 +113,7 @@ specified, only that table is retrieved. If at least one \fIcolumn\fR
is specified, only those columns are retrieved.
.
.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]...]..."
Connects to \fIserver\fR and monitors the contents of \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
@@ -130,16 +136,25 @@ each group. Whether multiple groups or only a single group is
specified, any given column may only be mentioned once on the command
line.
.IP
-If \fB\-\-detach\fR is used with \fBmonitor\fR, then \fBovsdb\-client\fR
-detaches after it has successfully received and printed the initial
-contents of \fItable\fR.
+If \fB\-\-detach\fR is used with \fBmonitor\fR or \fBmointor2\fR, then
+\fBovsdb\-client\fR detaches after it has successfully received and
+printed the initial contents of \fItable\fR.
+.IP
+The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
+session with the server. The \fBmonitor2\fR command uses RFC 7047
+extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
.
.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
\fIdatabase\fR. Prints initial values and all kinds of changes to all
columns in the database. The \fB\-\-detach\fR option causes
\fBovsdb\-client\fR to detach after it successfully receives and
prints the initial database contents.
+.IP
+The \fBmonitor\fR command uses RFC 7047 "monitor" method to open a monitor
+session with the server. The \fBmonitor2\fR command uses RFC 7047
+extension "monitor2" method. See \fBovsdb\-server\fR(1) for details.
.
.SH OPTIONS
.SS "Output Formatting Options"
@@ -150,14 +165,14 @@ The following options controlling output formatting:
.so lib/table.man
.
.IP "\fB\-\-timestamp\fR"
-For the \fBmonitor\fR command, adds a timestamp to each table
-update. Most output formats add the timestamp on a line of its own
+For the \fBmonitor\fR and \fBmonitor2\fR commands, add a timestamp to each
+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
member of the top-level JSON object named \fBtime\fR.
.
.SS "Daemon Options"
-The daemon options apply only to the \fBmonitor\fR command. With any
-other command, they have no effect.
+The daemon options apply only to the \fBmonitor\fR and \fBmonitor2\fR commands.
+With any other command, they have no effect.
.ds DD
.so lib/daemon.man
.SS "Logging Options"
diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
index 8d2063041..83cc81d92 100644
--- a/ovsdb/ovsdb-client.c
+++ b/ovsdb/ovsdb-client.c
@@ -44,6 +44,7 @@
#include "stream.h"
#include "stream-ssl.h"
#include "table.h"
+#include "monitor.h"
#include "timeval.h"
#include "unixctl.h"
#include "util.h"
@@ -256,7 +257,10 @@ usage(void)
"\n monitor [SERVER] [DATABASE] ALL\n"
" monitor all changes to all columns in all tables\n"
" in DATBASE on SERVER.\n"
- "\n dump [SERVER] [DATABASE] [TABLE [COLUMN]...]\n"
+ "\n monitor2 [SERVER] [DATABASE] ALL\n"
+ " same usage as monitor, but uses \"monitor2\" method over"
+ " the wire."
+ "\n dump [SERVER] [DATABASE]\n"
" dump contents of DATABASE on SERVER to stdout\n"
"\nThe default SERVER is unix:%s/db.sock.\n"
"The default DATABASE is Open_vSwitch.\n",
@@ -617,6 +621,101 @@ monitor_print(struct json *table_updates,
}
static void
+monitor2_print_row(struct json *row, const char *type, const char *uuid,
+ const struct ovsdb_column_set *columns, struct table *t)
+{
+ if (!strcmp(type, "delete")) {
+ if (row->type != JSON_NULL) {
+ ovs_error(0, "delete method does not expect <row>");
+ return;
+ }
+
+ table_add_row(t);
+ table_add_cell(t)->text = xstrdup(uuid);
+ table_add_cell(t)->text = xstrdup(type);
+ } else {
+ if (!row || row->type != JSON_OBJECT) {
+ ovs_error(0, "<row> is not object");
+ return;
+ }
+ monitor_print_row(row, type, uuid, columns, t);
+ }
+}
+
+static void
+monitor2_print_table(struct json *table_update2,
+ const struct monitored_table *mt, char *caption)
+{
+ const struct ovsdb_table_schema *table = mt->table;
+ const struct ovsdb_column_set *columns = &mt->columns;
+ struct shash_node *node;
+ struct table t;
+ size_t i;
+
+ if (table_update2->type != JSON_OBJECT) {
+ ovs_error(0, "<table-update> for table %s is not object", table->name);
+ return;
+ }
+
+ table_init(&t);
+ table_set_timestamp(&t, timestamp);
+ table_set_caption(&t, caption);
+
+ table_add_column(&t, "row");
+ table_add_column(&t, "action");
+ for (i = 0; i < columns->n_columns; i++) {
+ table_add_column(&t, "%s", columns->columns[i]->name);
+ }
+ SHASH_FOR_EACH (node, json_object(table_update2)) {
+ struct json *row_update2 = node->data;
+ const char *operation;
+ struct json *row;
+ const char *ops[] = {"delete", "initial", "modify", "insert"};
+
+ if (row_update2->type != JSON_OBJECT) {
+ ovs_error(0, "<row-update2> is not object");
+ continue;
+ }
+
+ /* row_update2 contains one of objects indexed by ops[] */
+ for (int i = 0; i < ARRAY_SIZE(ops); i++) {
+ operation = ops[i];
+ row = shash_find_data(json_object(row_update2), operation);
+
+ if (row) {
+ monitor2_print_row(row, operation, node->name, columns, &t);
+ break;
+ }
+ }
+ }
+ table_print(&t, &table_style);
+ table_destroy(&t);
+}
+
+static void
+monitor2_print(struct json *table_updates2,
+ const struct monitored_table *mts, size_t n_mts)
+{
+ size_t i;
+
+ if (table_updates2->type != JSON_OBJECT) {
+ ovs_error(0, "<table-updates2> is not object");
+ return;
+ }
+
+ for (i = 0; i < n_mts; i++) {
+ const struct monitored_table *mt = &mts[i];
+ struct json *table_update = shash_find_data(
+ json_object(table_updates2),
+ mt->table->name);
+ if (table_update) {
+ monitor2_print_table(table_update, mt,
+ n_mts > 1 ? xstrdup(mt->table->name) : NULL);
+ }
+ }
+}
+
+static void
add_column(const char *server, const struct ovsdb_column *column,
struct ovsdb_column_set *columns, struct json *columns_json)
{
@@ -776,8 +875,9 @@ add_monitored_table(int argc, char *argv[],
}
static void
-do_monitor(struct jsonrpc *rpc, const char *database,
- int argc, char *argv[])
+do_monitor__(struct jsonrpc *rpc, const char *database,
+ enum ovsdb_monitor_version version,
+ int argc, char *argv[])
{
const char *server = jsonrpc_get_name(rpc);
const char *table_name = argv[0];
@@ -791,6 +891,8 @@ do_monitor(struct jsonrpc *rpc, const char *database,
struct monitored_table *mts;
size_t n_mts, allocated_mts;
+ ovs_assert(version < OVSDB_MONITOR_VERSION_MAX);
+
daemon_save_fd(STDOUT_FILENO);
daemonize_start(false);
if (get_detach()) {
@@ -845,7 +947,10 @@ do_monitor(struct jsonrpc *rpc, const char *database,
monitor = json_array_create_3(json_string_create(database),
json_null_create(), monitor_requests);
- request = jsonrpc_create_request("monitor", monitor, NULL);
+ const char *method = version == OVSDB_MONITOR_V2 ? "monitor2"
+ : "monitor";
+
+ request = jsonrpc_create_request(method, monitor, NULL);
request_id = json_clone(request->id);
jsonrpc_send(rpc, request);
@@ -867,7 +972,17 @@ do_monitor(struct jsonrpc *rpc, const char *database,
msg->id));
} else if (msg->type == JSONRPC_REPLY
&& json_equal(msg->id, request_id)) {
- monitor_print(msg->result, mts, n_mts, true);
+ switch(version) {
+ case OVSDB_MONITOR_V1:
+ monitor_print(msg->result, mts, n_mts, true);
+ break;
+ case OVSDB_MONITOR_V2:
+ monitor2_print(msg->result, mts, n_mts);
+ break;
+ case OVSDB_MONITOR_VERSION_MAX:
+ default:
+ OVS_NOT_REACHED();
+ }
fflush(stdout);
daemonize_complete();
} else if (msg->type == JSONRPC_NOTIFY
@@ -879,6 +994,16 @@ do_monitor(struct jsonrpc *rpc, const char *database,
monitor_print(params->u.array.elems[1], mts, n_mts, false);
fflush(stdout);
}
+ } else if (msg->type == JSONRPC_NOTIFY
+ && version == OVSDB_MONITOR_V2
+ && !strcmp(msg->method, "update2")) {
+ struct json *params = msg->params;
+ if (params->type == JSON_ARRAY
+ && params->u.array.n == 2
+ && params->u.array.elems[0]->type == JSON_NULL) {
+ monitor2_print(params->u.array.elems[1], mts, n_mts);
+ fflush(stdout);
+ }
}
jsonrpc_msg_destroy(msg);
}
@@ -897,6 +1022,20 @@ do_monitor(struct jsonrpc *rpc, const char *database,
}
}
+static void
+do_monitor(struct jsonrpc *rpc, const char *database,
+ int argc, char *argv[])
+{
+ do_monitor__(rpc, database, OVSDB_MONITOR_V1, argc, argv);
+}
+
+static void
+do_monitor2(struct jsonrpc *rpc, const char *database,
+ int argc, char *argv[])
+{
+ do_monitor__(rpc, database, OVSDB_MONITOR_V2, argc, argv);
+}
+
struct dump_table_aux {
struct ovsdb_datum **data;
const struct ovsdb_column **columns;
@@ -1167,8 +1306,8 @@ static const struct ovsdb_client_command all_commands[] = {
{ "list-columns", NEED_DATABASE, 0, 1, do_list_columns },
{ "transact", NEED_RPC, 1, 1, do_transact },
{ "monitor", NEED_DATABASE, 1, INT_MAX, do_monitor },
+ { "monitor2", NEED_DATABASE, 1, INT_MAX, do_monitor2 },
{ "dump", NEED_DATABASE, 0, INT_MAX, do_dump },
-
{ "help", NEED_NONE, 0, INT_MAX, do_help },
{ NULL, 0, 0, 0, NULL },