summaryrefslogtreecommitdiff
path: root/ovsdb/ovsdb-client.c
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/ovsdb-client.c
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/ovsdb-client.c')
-rw-r--r--ovsdb/ovsdb-client.c151
1 files changed, 145 insertions, 6 deletions
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 },