Skip to content

Commit

Permalink
ovsdb-client: support monitor2
Browse files Browse the repository at this point in the history
Add monitor2 option to ovsdb-client. See ovsdb-client(1) manpage patch
for details.

Signed-off-by: Andy Zhou <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
azhou-nicira committed Dec 11, 2015
1 parent 92f8d65 commit 8522689
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 13 deletions.
1 change: 1 addition & 0 deletions ovsdb/monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
29 changes: 22 additions & 7 deletions ovsdb/ovsdb-client.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand All @@ -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"
Expand All @@ -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"
Expand Down
151 changes: 145 additions & 6 deletions ovsdb/ovsdb-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -616,6 +620,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)
Expand Down Expand Up @@ -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];
Expand All @@ -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()) {
Expand Down Expand Up @@ -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);

Expand All @@ -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
Expand All @@ -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);
}
Expand All @@ -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;
Expand Down Expand Up @@ -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 },
Expand Down

0 comments on commit 8522689

Please sign in to comment.