From 85226894ddec78f5aa7b7ab5dd8e8d11cc0fbde0 Mon Sep 17 00:00:00 2001 From: Andy Zhou Date: Thu, 15 Oct 2015 14:09:07 -0700 Subject: ovsdb-client: support monitor2 Add monitor2 option to ovsdb-client. See ovsdb-client(1) manpage patch for details. Signed-off-by: Andy Zhou Acked-by: Ben Pfaff --- ovsdb/ovsdb-client.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 6 deletions(-) (limited to 'ovsdb/ovsdb-client.c') 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", @@ -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 "); + 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, " 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, " 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, " 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, " 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 }, -- cgit v1.2.1