Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.git] / ovsdb / ovsdb-client.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include <ctype.h>
20 #include <errno.h>
21 #include <getopt.h>
22 #include <limits.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "command-line.h"
29 #include "column.h"
30 #include "compiler.h"
31 #include "daemon.h"
32 #include "dirs.h"
33 #include "dynamic-string.h"
34 #include "fatal-signal.h"
35 #include "json.h"
36 #include "jsonrpc.h"
37 #include "lib/table.h"
38 #include "ovsdb.h"
39 #include "ovsdb-data.h"
40 #include "ovsdb-error.h"
41 #include "poll-loop.h"
42 #include "sort.h"
43 #include "svec.h"
44 #include "stream.h"
45 #include "stream-ssl.h"
46 #include "table.h"
47 #include "timeval.h"
48 #include "unixctl.h"
49 #include "util.h"
50 #include "vlog.h"
51
52 VLOG_DEFINE_THIS_MODULE(ovsdb_client);
53
54 enum args_needed {
55     NEED_NONE,            /* No JSON-RPC connection or database name needed. */
56     NEED_RPC,             /* JSON-RPC connection needed. */
57     NEED_DATABASE         /* JSON-RPC connection and database name needed. */
58 };
59
60 struct ovsdb_client_command {
61     const char *name;
62     enum args_needed need;
63     int min_args;
64     int max_args;
65     void (*handler)(struct jsonrpc *rpc, const char *database,
66                     int argc, char *argv[]);
67 };
68
69 /* --timestamp: Print a timestamp before each update on "monitor" command? */
70 static bool timestamp;
71
72 /* Format for table output. */
73 static struct table_style table_style = TABLE_STYLE_DEFAULT;
74
75 static const struct ovsdb_client_command *get_all_commands(void);
76
77 static void usage(void) NO_RETURN;
78 static void parse_options(int argc, char *argv[]);
79 static struct jsonrpc *open_jsonrpc(const char *server);
80 static void fetch_dbs(struct jsonrpc *, struct svec *dbs);
81
82 int
83 main(int argc, char *argv[])
84 {
85     const struct ovsdb_client_command *command;
86     const char *database;
87     struct jsonrpc *rpc;
88
89     proctitle_init(argc, argv);
90     set_program_name(argv[0]);
91     parse_options(argc, argv);
92     fatal_ignore_sigpipe();
93
94     if (optind >= argc) {
95         ovs_fatal(0, "missing command name; use --help for help");
96     }
97
98     for (command = get_all_commands(); ; command++) {
99         if (!command->name) {
100             VLOG_FATAL("unknown command '%s'; use --help for help",
101                        argv[optind]);
102         } else if (!strcmp(command->name, argv[optind])) {
103             break;
104         }
105     }
106     optind++;
107
108     if (command->need != NEED_NONE) {
109         if (argc - optind > command->min_args
110             && (isalpha((unsigned char) argv[optind][0])
111                 && strchr(argv[optind], ':'))) {
112             rpc = open_jsonrpc(argv[optind++]);
113         } else {
114             char *sock = xasprintf("unix:%s/db.sock", ovs_rundir());
115             rpc = open_jsonrpc(sock);
116             free(sock);
117         }
118     } else {
119         rpc = NULL;
120     }
121
122     if (command->need == NEED_DATABASE) {
123         struct svec dbs;
124
125         svec_init(&dbs);
126         fetch_dbs(rpc, &dbs);
127         if (argc - optind > command->min_args
128             && svec_contains(&dbs, argv[optind])) {
129             database = argv[optind++];
130         } else if (dbs.n == 1) {
131             database = xstrdup(dbs.names[0]);
132         } else if (svec_contains(&dbs, "Open_vSwitch")) {
133             database = "Open_vSwitch";
134         } else {
135             ovs_fatal(0, "no default database for `%s' command, please "
136                       "specify a database name", command->name);
137         }
138         svec_destroy(&dbs);
139     } else {
140         database = NULL;
141     }
142
143     if (argc - optind < command->min_args ||
144         argc - optind > command->max_args) {
145         VLOG_FATAL("invalid syntax for '%s' (use --help for help)",
146                     command->name);
147     }
148
149     command->handler(rpc, database, argc - optind, argv + optind);
150
151     jsonrpc_close(rpc);
152
153     if (ferror(stdout)) {
154         VLOG_FATAL("write to stdout failed");
155     }
156     if (ferror(stderr)) {
157         VLOG_FATAL("write to stderr failed");
158     }
159
160     return 0;
161 }
162
163 static void
164 parse_options(int argc, char *argv[])
165 {
166     enum {
167         OPT_BOOTSTRAP_CA_CERT = UCHAR_MAX + 1,
168         OPT_TIMESTAMP,
169         VLOG_OPTION_ENUMS,
170         DAEMON_OPTION_ENUMS,
171         TABLE_OPTION_ENUMS
172     };
173     static const struct option long_options[] = {
174         {"help", no_argument, NULL, 'h'},
175         {"version", no_argument, NULL, 'V'},
176         {"timestamp", no_argument, NULL, OPT_TIMESTAMP},
177         VLOG_LONG_OPTIONS,
178         DAEMON_LONG_OPTIONS,
179 #ifdef HAVE_OPENSSL
180         {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
181         STREAM_SSL_LONG_OPTIONS,
182 #endif
183         TABLE_LONG_OPTIONS,
184         {NULL, 0, NULL, 0},
185     };
186     char *short_options = long_options_to_short_options(long_options);
187
188     for (;;) {
189         int c;
190
191         c = getopt_long(argc, argv, short_options, long_options, NULL);
192         if (c == -1) {
193             break;
194         }
195
196         switch (c) {
197         case 'h':
198             usage();
199
200         case 'V':
201             ovs_print_version(0, 0);
202             exit(EXIT_SUCCESS);
203
204         VLOG_OPTION_HANDLERS
205         DAEMON_OPTION_HANDLERS
206         TABLE_OPTION_HANDLERS(&table_style)
207         STREAM_SSL_OPTION_HANDLERS
208
209         case OPT_BOOTSTRAP_CA_CERT:
210             stream_ssl_set_ca_cert_file(optarg, true);
211             break;
212
213         case OPT_TIMESTAMP:
214             timestamp = true;
215             break;
216
217         case '?':
218             exit(EXIT_FAILURE);
219
220         case 0:
221             /* getopt_long() already set the value for us. */
222             break;
223
224         default:
225             abort();
226         }
227     }
228     free(short_options);
229 }
230
231 static void
232 usage(void)
233 {
234     printf("%s: Open vSwitch database JSON-RPC client\n"
235            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
236            "\nValid commands are:\n"
237            "\n  list-dbs [SERVER]\n"
238            "    list databases available on SERVER\n"
239            "\n  get-schema [SERVER] [DATABASE]\n"
240            "    retrieve schema for DATABASE from SERVER\n"
241            "\n  get-schema-version [SERVER] [DATABASE]\n"
242            "    retrieve schema for DATABASE from SERVER and report only its\n"
243            "    version number on stdout\n"
244            "\n  list-tables [SERVER] [DATABASE]\n"
245            "    list tables for DATABASE on SERVER\n"
246            "\n  list-columns [SERVER] [DATABASE] [TABLE]\n"
247            "    list columns in TABLE (or all tables) in DATABASE on SERVER\n"
248            "\n  transact [SERVER] TRANSACTION\n"
249            "    run TRANSACTION (a JSON array of operations) on SERVER\n"
250            "    and print the results as JSON on stdout\n"
251            "\n  monitor [SERVER] [DATABASE] TABLE [COLUMN,...]...\n"
252            "    monitor contents of COLUMNs in TABLE in DATABASE on SERVER.\n"
253            "    COLUMNs may include !initial, !insert, !delete, !modify\n"
254            "    to avoid seeing the specified kinds of changes.\n"
255            "\n  monitor [SERVER] [DATABASE] ALL\n"
256            "    monitor all changes to all columns in all tables\n"
257            "    in DATBASE on SERVER.\n"
258            "\n  dump [SERVER] [DATABASE]\n"
259            "    dump contents of DATABASE on SERVER to stdout\n"
260            "\nThe default SERVER is unix:%s/db.sock.\n"
261            "The default DATABASE is Open_vSwitch.\n",
262            program_name, program_name, ovs_rundir());
263     stream_usage("SERVER", true, true, true);
264     printf("\nOutput formatting options:\n"
265            "  -f, --format=FORMAT         set output formatting to FORMAT\n"
266            "                              (\"table\", \"html\", \"csv\", "
267            "or \"json\")\n"
268            "  --no-headings               omit table heading row\n"
269            "  --pretty                    pretty-print JSON in output\n"
270            "  --timestamp                 timestamp \"monitor\" output");
271     daemon_usage();
272     vlog_usage();
273     printf("\nOther options:\n"
274            "  -h, --help                  display this help message\n"
275            "  -V, --version               display version information\n");
276     exit(EXIT_SUCCESS);
277 }
278 \f
279 static void
280 check_txn(int error, struct jsonrpc_msg **reply_)
281 {
282     struct jsonrpc_msg *reply = *reply_;
283
284     if (error) {
285         ovs_fatal(error, "transaction failed");
286     }
287
288     if (reply->error) {
289         ovs_fatal(error, "transaction returned error: %s",
290                   json_to_string(reply->error, table_style.json_flags));
291     }
292 }
293
294 static struct json *
295 parse_json(const char *s)
296 {
297     struct json *json = json_from_string(s);
298     if (json->type == JSON_STRING) {
299         ovs_fatal(0, "\"%s\": %s", s, json->u.string);
300     }
301     return json;
302 }
303
304 static struct jsonrpc *
305 open_jsonrpc(const char *server)
306 {
307     struct stream *stream;
308     int error;
309
310     error = stream_open_block(jsonrpc_stream_open(server, &stream,
311                               DSCP_DEFAULT), &stream);
312     if (error == EAFNOSUPPORT) {
313         struct pstream *pstream;
314
315         error = jsonrpc_pstream_open(server, &pstream, DSCP_DEFAULT);
316         if (error) {
317             ovs_fatal(error, "failed to connect or listen to \"%s\"", server);
318         }
319
320         VLOG_INFO("%s: waiting for connection...", server);
321         error = pstream_accept_block(pstream, &stream);
322         if (error) {
323             ovs_fatal(error, "failed to accept connection on \"%s\"", server);
324         }
325
326         pstream_close(pstream);
327     } else if (error) {
328         ovs_fatal(error, "failed to connect to \"%s\"", server);
329     }
330
331     return jsonrpc_open(stream);
332 }
333
334 static void
335 print_json(struct json *json)
336 {
337     char *string = json_to_string(json, table_style.json_flags);
338     fputs(string, stdout);
339     free(string);
340 }
341
342 static void
343 print_and_free_json(struct json *json)
344 {
345     print_json(json);
346     json_destroy(json);
347 }
348
349 static void
350 check_ovsdb_error(struct ovsdb_error *error)
351 {
352     if (error) {
353         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
354     }
355 }
356
357 static struct ovsdb_schema *
358 fetch_schema(struct jsonrpc *rpc, const char *database)
359 {
360     struct jsonrpc_msg *request, *reply;
361     struct ovsdb_schema *schema;
362
363     request = jsonrpc_create_request("get_schema",
364                                      json_array_create_1(
365                                          json_string_create(database)),
366                                      NULL);
367     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
368     check_ovsdb_error(ovsdb_schema_from_json(reply->result, &schema));
369     jsonrpc_msg_destroy(reply);
370
371     return schema;
372 }
373
374 static void
375 fetch_dbs(struct jsonrpc *rpc, struct svec *dbs)
376 {
377     struct jsonrpc_msg *request, *reply;
378     size_t i;
379
380     request = jsonrpc_create_request("list_dbs", json_array_create_empty(),
381                                      NULL);
382
383     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
384     if (reply->result->type != JSON_ARRAY) {
385         ovs_fatal(0, "list_dbs response is not array");
386     }
387
388     for (i = 0; i < reply->result->u.array.n; i++) {
389         const struct json *name = reply->result->u.array.elems[i];
390
391         if (name->type != JSON_STRING) {
392             ovs_fatal(0, "list_dbs response %"PRIuSIZE" is not string", i);
393         }
394         svec_add(dbs, name->u.string);
395     }
396     jsonrpc_msg_destroy(reply);
397     svec_sort(dbs);
398 }
399 \f
400 static void
401 do_list_dbs(struct jsonrpc *rpc, const char *database OVS_UNUSED,
402             int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
403 {
404     const char *db_name;
405     struct svec dbs;
406     size_t i;
407
408     svec_init(&dbs);
409     fetch_dbs(rpc, &dbs);
410     SVEC_FOR_EACH (i, db_name, &dbs) {
411         puts(db_name);
412     }
413     svec_destroy(&dbs);
414 }
415
416 static void
417 do_get_schema(struct jsonrpc *rpc, const char *database,
418               int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
419 {
420     struct ovsdb_schema *schema = fetch_schema(rpc, database);
421     print_and_free_json(ovsdb_schema_to_json(schema));
422     ovsdb_schema_destroy(schema);
423 }
424
425 static void
426 do_get_schema_version(struct jsonrpc *rpc, const char *database,
427                       int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
428 {
429     struct ovsdb_schema *schema = fetch_schema(rpc, database);
430     puts(schema->version);
431     ovsdb_schema_destroy(schema);
432 }
433
434 static void
435 do_list_tables(struct jsonrpc *rpc, const char *database,
436                int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
437 {
438     struct ovsdb_schema *schema;
439     struct shash_node *node;
440     struct table t;
441
442     schema = fetch_schema(rpc, database);
443     table_init(&t);
444     table_add_column(&t, "Table");
445     SHASH_FOR_EACH (node, &schema->tables) {
446         struct ovsdb_table_schema *ts = node->data;
447
448         table_add_row(&t);
449         table_add_cell(&t)->text = xstrdup(ts->name);
450     }
451     ovsdb_schema_destroy(schema);
452     table_print(&t, &table_style);
453 }
454
455 static void
456 do_list_columns(struct jsonrpc *rpc, const char *database,
457                 int argc OVS_UNUSED, char *argv[])
458 {
459     const char *table_name = argv[0];
460     struct ovsdb_schema *schema;
461     struct shash_node *table_node;
462     struct table t;
463
464     schema = fetch_schema(rpc, database);
465     table_init(&t);
466     if (!table_name) {
467         table_add_column(&t, "Table");
468     }
469     table_add_column(&t, "Column");
470     table_add_column(&t, "Type");
471     SHASH_FOR_EACH (table_node, &schema->tables) {
472         struct ovsdb_table_schema *ts = table_node->data;
473
474         if (!table_name || !strcmp(table_name, ts->name)) {
475             struct shash_node *column_node;
476
477             SHASH_FOR_EACH (column_node, &ts->columns) {
478                 const struct ovsdb_column *column = column_node->data;
479
480                 table_add_row(&t);
481                 if (!table_name) {
482                     table_add_cell(&t)->text = xstrdup(ts->name);
483                 }
484                 table_add_cell(&t)->text = xstrdup(column->name);
485                 table_add_cell(&t)->json = ovsdb_type_to_json(&column->type);
486             }
487         }
488     }
489     ovsdb_schema_destroy(schema);
490     table_print(&t, &table_style);
491 }
492
493 static void
494 do_transact(struct jsonrpc *rpc, const char *database OVS_UNUSED,
495             int argc OVS_UNUSED, char *argv[])
496 {
497     struct jsonrpc_msg *request, *reply;
498     struct json *transaction;
499
500     transaction = parse_json(argv[0]);
501
502     request = jsonrpc_create_request("transact", transaction, NULL);
503     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
504     print_json(reply->result);
505     putchar('\n');
506     jsonrpc_msg_destroy(reply);
507 }
508 \f
509 /* "monitor" command. */
510
511 struct monitored_table {
512     struct ovsdb_table_schema *table;
513     struct ovsdb_column_set columns;
514 };
515
516 static void
517 monitor_print_row(struct json *row, const char *type, const char *uuid,
518                   const struct ovsdb_column_set *columns, struct table *t)
519 {
520     size_t i;
521
522     if (!row) {
523         ovs_error(0, "missing %s row", type);
524         return;
525     } else if (row->type != JSON_OBJECT) {
526         ovs_error(0, "<row> is not object");
527         return;
528     }
529
530     table_add_row(t);
531     table_add_cell(t)->text = xstrdup(uuid);
532     table_add_cell(t)->text = xstrdup(type);
533     for (i = 0; i < columns->n_columns; i++) {
534         const struct ovsdb_column *column = columns->columns[i];
535         struct json *value = shash_find_data(json_object(row), column->name);
536         struct cell *cell = table_add_cell(t);
537         if (value) {
538             cell->json = json_clone(value);
539             cell->type = &column->type;
540         }
541     }
542 }
543
544 static void
545 monitor_print_table(struct json *table_update,
546                     const struct monitored_table *mt, char *caption,
547                     bool initial)
548 {
549     const struct ovsdb_table_schema *table = mt->table;
550     const struct ovsdb_column_set *columns = &mt->columns;
551     struct shash_node *node;
552     struct table t;
553     size_t i;
554
555     if (table_update->type != JSON_OBJECT) {
556         ovs_error(0, "<table-update> for table %s is not object", table->name);
557         return;
558     }
559
560     table_init(&t);
561     table_set_timestamp(&t, timestamp);
562     table_set_caption(&t, caption);
563
564     table_add_column(&t, "row");
565     table_add_column(&t, "action");
566     for (i = 0; i < columns->n_columns; i++) {
567         table_add_column(&t, "%s", columns->columns[i]->name);
568     }
569     SHASH_FOR_EACH (node, json_object(table_update)) {
570         struct json *row_update = node->data;
571         struct json *old, *new;
572
573         if (row_update->type != JSON_OBJECT) {
574             ovs_error(0, "<row-update> is not object");
575             continue;
576         }
577         old = shash_find_data(json_object(row_update), "old");
578         new = shash_find_data(json_object(row_update), "new");
579         if (initial) {
580             monitor_print_row(new, "initial", node->name, columns, &t);
581         } else if (!old) {
582             monitor_print_row(new, "insert", node->name, columns, &t);
583         } else if (!new) {
584             monitor_print_row(old, "delete", node->name, columns, &t);
585         } else {
586             monitor_print_row(old, "old", node->name, columns, &t);
587             monitor_print_row(new, "new", "", columns, &t);
588         }
589     }
590     table_print(&t, &table_style);
591     table_destroy(&t);
592 }
593
594 static void
595 monitor_print(struct json *table_updates,
596               const struct monitored_table *mts, size_t n_mts,
597               bool initial)
598 {
599     size_t i;
600
601     if (table_updates->type != JSON_OBJECT) {
602         ovs_error(0, "<table-updates> is not object");
603         return;
604     }
605
606     for (i = 0; i < n_mts; i++) {
607         const struct monitored_table *mt = &mts[i];
608         struct json *table_update = shash_find_data(json_object(table_updates),
609                                                     mt->table->name);
610         if (table_update) {
611             monitor_print_table(table_update, mt,
612                                 n_mts > 1 ? xstrdup(mt->table->name) : NULL,
613                                 initial);
614         }
615     }
616 }
617
618 static void
619 add_column(const char *server, const struct ovsdb_column *column,
620            struct ovsdb_column_set *columns, struct json *columns_json)
621 {
622     if (ovsdb_column_set_contains(columns, column->index)) {
623         ovs_fatal(0, "%s: column \"%s\" mentioned multiple times",
624                   server, column->name);
625     }
626     ovsdb_column_set_add(columns, column);
627     json_array_add(columns_json, json_string_create(column->name));
628 }
629
630 static struct json *
631 parse_monitor_columns(char *arg, const char *server, const char *database,
632                       const struct ovsdb_table_schema *table,
633                       struct ovsdb_column_set *columns)
634 {
635     bool initial, insert, delete, modify;
636     struct json *mr, *columns_json;
637     char *save_ptr = NULL;
638     char *token;
639
640     mr = json_object_create();
641     columns_json = json_array_create_empty();
642     json_object_put(mr, "columns", columns_json);
643
644     initial = insert = delete = modify = true;
645     for (token = strtok_r(arg, ",", &save_ptr); token != NULL;
646          token = strtok_r(NULL, ",", &save_ptr)) {
647         if (!strcmp(token, "!initial")) {
648             initial = false;
649         } else if (!strcmp(token, "!insert")) {
650             insert = false;
651         } else if (!strcmp(token, "!delete")) {
652             delete = false;
653         } else if (!strcmp(token, "!modify")) {
654             modify = false;
655         } else {
656             const struct ovsdb_column *column;
657
658             column = ovsdb_table_schema_get_column(table, token);
659             if (!column) {
660                 ovs_fatal(0, "%s: table \"%s\" in %s does not have a "
661                           "column named \"%s\"",
662                           server, table->name, database, token);
663             }
664             add_column(server, column, columns, columns_json);
665         }
666     }
667
668     if (columns_json->u.array.n == 0) {
669         const struct shash_node **nodes;
670         size_t i, n;
671
672         n = shash_count(&table->columns);
673         nodes = shash_sort(&table->columns);
674         for (i = 0; i < n; i++) {
675             const struct ovsdb_column *column = nodes[i]->data;
676             if (column->index != OVSDB_COL_UUID
677                 && column->index != OVSDB_COL_VERSION) {
678                 add_column(server, column, columns, columns_json);
679             }
680         }
681         free(nodes);
682
683         add_column(server, ovsdb_table_schema_get_column(table, "_version"),
684                    columns, columns_json);
685     }
686
687     if (!initial || !insert || !delete || !modify) {
688         struct json *select = json_object_create();
689         json_object_put(select, "initial", json_boolean_create(initial));
690         json_object_put(select, "insert", json_boolean_create(insert));
691         json_object_put(select, "delete", json_boolean_create(delete));
692         json_object_put(select, "modify", json_boolean_create(modify));
693         json_object_put(mr, "select", select);
694     }
695
696     return mr;
697 }
698
699 static void
700 ovsdb_client_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
701                   const char *argv[] OVS_UNUSED, void *exiting_)
702 {
703     bool *exiting = exiting_;
704     *exiting = true;
705     unixctl_command_reply(conn, NULL);
706 }
707
708 static void
709 ovsdb_client_block(struct unixctl_conn *conn, int argc OVS_UNUSED,
710                    const char *argv[] OVS_UNUSED, void *blocked_)
711 {
712     bool *blocked = blocked_;
713
714     if (!*blocked) {
715         *blocked = true;
716         unixctl_command_reply(conn, NULL);
717     } else {
718         unixctl_command_reply(conn, "already blocking");
719     }
720 }
721
722 static void
723 ovsdb_client_unblock(struct unixctl_conn *conn, int argc OVS_UNUSED,
724                      const char *argv[] OVS_UNUSED, void *blocked_)
725 {
726     bool *blocked = blocked_;
727
728     if (*blocked) {
729         *blocked = false;
730         unixctl_command_reply(conn, NULL);
731     } else {
732         unixctl_command_reply(conn, "already unblocked");
733     }
734 }
735
736 static void
737 add_monitored_table(int argc, char *argv[],
738                     const char *server, const char *database,
739                     struct ovsdb_table_schema *table,
740                     struct json *monitor_requests,
741                     struct monitored_table **mts,
742                     size_t *n_mts, size_t *allocated_mts)
743 {
744     struct json *monitor_request_array;
745     struct monitored_table *mt;
746
747     if (*n_mts >= *allocated_mts) {
748         *mts = x2nrealloc(*mts, allocated_mts, sizeof **mts);
749     }
750     mt = &(*mts)[(*n_mts)++];
751     mt->table = table;
752     ovsdb_column_set_init(&mt->columns);
753
754     monitor_request_array = json_array_create_empty();
755     if (argc > 1) {
756         int i;
757
758         for (i = 1; i < argc; i++) {
759             json_array_add(
760                 monitor_request_array,
761                 parse_monitor_columns(argv[i], server, database, table,
762                                       &mt->columns));
763         }
764     } else {
765         /* Allocate a writable empty string since parse_monitor_columns()
766          * is going to strtok() it and that's risky with literal "". */
767         char empty[] = "";
768         json_array_add(
769             monitor_request_array,
770             parse_monitor_columns(empty, server, database,
771                                   table, &mt->columns));
772     }
773
774     json_object_put(monitor_requests, table->name, monitor_request_array);
775 }
776
777 static void
778 do_monitor(struct jsonrpc *rpc, const char *database,
779            int argc, char *argv[])
780 {
781     const char *server = jsonrpc_get_name(rpc);
782     const char *table_name = argv[0];
783     struct unixctl_server *unixctl;
784     struct ovsdb_schema *schema;
785     struct jsonrpc_msg *request;
786     struct json *monitor, *monitor_requests, *request_id;
787     bool exiting = false;
788     bool blocked = false;
789
790     struct monitored_table *mts;
791     size_t n_mts, allocated_mts;
792
793     daemon_save_fd(STDOUT_FILENO);
794     daemonize_start();
795     if (get_detach()) {
796         int error;
797
798         error = unixctl_server_create(NULL, &unixctl);
799         if (error) {
800             ovs_fatal(error, "failed to create unixctl server");
801         }
802
803         unixctl_command_register("exit", "", 0, 0,
804                                  ovsdb_client_exit, &exiting);
805         unixctl_command_register("ovsdb-client/block", "", 0, 0,
806                                  ovsdb_client_block, &blocked);
807         unixctl_command_register("ovsdb-client/unblock", "", 0, 0,
808                                  ovsdb_client_unblock, &blocked);
809     } else {
810         unixctl = NULL;
811     }
812
813     schema = fetch_schema(rpc, database);
814
815     monitor_requests = json_object_create();
816
817     mts = NULL;
818     n_mts = allocated_mts = 0;
819     if (strcmp(table_name, "ALL")) {
820         struct ovsdb_table_schema *table;
821
822         table = shash_find_data(&schema->tables, table_name);
823         if (!table) {
824             ovs_fatal(0, "%s: %s does not have a table named \"%s\"",
825                       server, database, table_name);
826         }
827
828         add_monitored_table(argc, argv, server, database, table,
829                             monitor_requests, &mts, &n_mts, &allocated_mts);
830     } else {
831         size_t n = shash_count(&schema->tables);
832         const struct shash_node **nodes = shash_sort(&schema->tables);
833         size_t i;
834
835         for (i = 0; i < n; i++) {
836             struct ovsdb_table_schema *table = nodes[i]->data;
837
838             add_monitored_table(argc, argv, server, database, table,
839                                 monitor_requests,
840                                 &mts, &n_mts, &allocated_mts);
841         }
842         free(nodes);
843     }
844
845     monitor = json_array_create_3(json_string_create(database),
846                                   json_null_create(), monitor_requests);
847     request = jsonrpc_create_request("monitor", monitor, NULL);
848     request_id = json_clone(request->id);
849     jsonrpc_send(rpc, request);
850
851     for (;;) {
852         unixctl_server_run(unixctl);
853         while (!blocked) {
854             struct jsonrpc_msg *msg;
855             int error;
856
857             error = jsonrpc_recv(rpc, &msg);
858             if (error == EAGAIN) {
859                 break;
860             } else if (error) {
861                 ovs_fatal(error, "%s: receive failed", server);
862             }
863
864             if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) {
865                 jsonrpc_send(rpc, jsonrpc_create_reply(json_clone(msg->params),
866                                                        msg->id));
867             } else if (msg->type == JSONRPC_REPLY
868                        && json_equal(msg->id, request_id)) {
869                 monitor_print(msg->result, mts, n_mts, true);
870                 fflush(stdout);
871                 daemonize_complete();
872             } else if (msg->type == JSONRPC_NOTIFY
873                        && !strcmp(msg->method, "update")) {
874                 struct json *params = msg->params;
875                 if (params->type == JSON_ARRAY
876                     && params->u.array.n == 2
877                     && params->u.array.elems[0]->type == JSON_NULL) {
878                     monitor_print(params->u.array.elems[1], mts, n_mts, false);
879                     fflush(stdout);
880                 }
881             }
882             jsonrpc_msg_destroy(msg);
883         }
884
885         if (exiting) {
886             break;
887         }
888
889         jsonrpc_run(rpc);
890         jsonrpc_wait(rpc);
891         if (!blocked) {
892             jsonrpc_recv_wait(rpc);
893         }
894         unixctl_server_wait(unixctl);
895         poll_block();
896     }
897 }
898
899 struct dump_table_aux {
900     struct ovsdb_datum **data;
901     const struct ovsdb_column **columns;
902     size_t n_columns;
903 };
904
905 static int
906 compare_data(size_t a_y, size_t b_y, size_t x,
907              const struct dump_table_aux *aux)
908 {
909     return ovsdb_datum_compare_3way(&aux->data[a_y][x],
910                                     &aux->data[b_y][x],
911                                     &aux->columns[x]->type);
912 }
913
914 static int
915 compare_rows(size_t a_y, size_t b_y, void *aux_)
916 {
917     struct dump_table_aux *aux = aux_;
918     size_t x;
919
920     /* Skip UUID columns on the first pass, since their values tend to be
921      * random and make our results less reproducible. */
922     for (x = 0; x < aux->n_columns; x++) {
923         if (aux->columns[x]->type.key.type != OVSDB_TYPE_UUID) {
924             int cmp = compare_data(a_y, b_y, x, aux);
925             if (cmp) {
926                 return cmp;
927             }
928         }
929     }
930
931     /* Use UUID columns as tie-breakers. */
932     for (x = 0; x < aux->n_columns; x++) {
933         if (aux->columns[x]->type.key.type == OVSDB_TYPE_UUID) {
934             int cmp = compare_data(a_y, b_y, x, aux);
935             if (cmp) {
936                 return cmp;
937             }
938         }
939     }
940
941     return 0;
942 }
943
944 static void
945 swap_rows(size_t a_y, size_t b_y, void *aux_)
946 {
947     struct dump_table_aux *aux = aux_;
948     struct ovsdb_datum *tmp = aux->data[a_y];
949     aux->data[a_y] = aux->data[b_y];
950     aux->data[b_y] = tmp;
951 }
952
953 static int
954 compare_columns(const void *a_, const void *b_)
955 {
956     const struct ovsdb_column *const *ap = a_;
957     const struct ovsdb_column *const *bp = b_;
958     const struct ovsdb_column *a = *ap;
959     const struct ovsdb_column *b = *bp;
960
961     return strcmp(a->name, b->name);
962 }
963
964 static void
965 dump_table(const struct ovsdb_table_schema *ts, struct json_array *rows)
966 {
967     const struct ovsdb_column **columns;
968     size_t n_columns;
969
970     struct ovsdb_datum **data;
971
972     struct dump_table_aux aux;
973     struct shash_node *node;
974     struct table t;
975     size_t x, y;
976
977     /* Sort columns by name, for reproducibility. */
978     columns = xmalloc(shash_count(&ts->columns) * sizeof *columns);
979     n_columns = 0;
980     SHASH_FOR_EACH (node, &ts->columns) {
981         struct ovsdb_column *column = node->data;
982         if (strcmp(column->name, "_version")) {
983             columns[n_columns++] = column;
984         }
985     }
986     qsort(columns, n_columns, sizeof *columns, compare_columns);
987
988     /* Extract data from table. */
989     data = xmalloc(rows->n * sizeof *data);
990     for (y = 0; y < rows->n; y++) {
991         struct shash *row;
992
993         if (rows->elems[y]->type != JSON_OBJECT) {
994             ovs_fatal(0,  "row %"PRIuSIZE" in table %s response is not a JSON object: "
995                       "%s", y, ts->name, json_to_string(rows->elems[y], 0));
996         }
997         row = json_object(rows->elems[y]);
998
999         data[y] = xmalloc(n_columns * sizeof **data);
1000         for (x = 0; x < n_columns; x++) {
1001             const struct json *json = shash_find_data(row, columns[x]->name);
1002             if (!json) {
1003                 ovs_fatal(0, "row %"PRIuSIZE" in table %s response lacks %s column",
1004                           y, ts->name, columns[x]->name);
1005             }
1006
1007             check_ovsdb_error(ovsdb_datum_from_json(&data[y][x],
1008                                                     &columns[x]->type,
1009                                                     json, NULL));
1010         }
1011     }
1012
1013     /* Sort rows by column values, for reproducibility. */
1014     aux.data = data;
1015     aux.columns = columns;
1016     aux.n_columns = n_columns;
1017     sort(rows->n, compare_rows, swap_rows, &aux);
1018
1019     /* Add column headings. */
1020     table_init(&t);
1021     table_set_caption(&t, xasprintf("%s table", ts->name));
1022     for (x = 0; x < n_columns; x++) {
1023         table_add_column(&t, "%s", columns[x]->name);
1024     }
1025
1026     /* Print rows. */
1027     for (y = 0; y < rows->n; y++) {
1028         table_add_row(&t);
1029         for (x = 0; x < n_columns; x++) {
1030             struct cell *cell = table_add_cell(&t);
1031             cell->json = ovsdb_datum_to_json(&data[y][x], &columns[x]->type);
1032             cell->type = &columns[x]->type;
1033             ovsdb_datum_destroy(&data[y][x], &columns[x]->type);
1034         }
1035         free(data[y]);
1036     }
1037     table_print(&t, &table_style);
1038     table_destroy(&t);
1039
1040     free(data);
1041     free(columns);
1042 }
1043
1044 static void
1045 do_dump(struct jsonrpc *rpc, const char *database,
1046         int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1047 {
1048     struct jsonrpc_msg *request, *reply;
1049     struct ovsdb_schema *schema;
1050     struct json *transaction;
1051
1052     const struct shash_node **tables;
1053     size_t n_tables;
1054
1055     size_t i;
1056
1057     schema = fetch_schema(rpc, database);
1058     tables = shash_sort(&schema->tables);
1059     n_tables = shash_count(&schema->tables);
1060
1061     /* Construct transaction to retrieve entire database. */
1062     transaction = json_array_create_1(json_string_create(database));
1063     for (i = 0; i < n_tables; i++) {
1064         const struct ovsdb_table_schema *ts = tables[i]->data;
1065         struct json *op, *columns;
1066         struct shash_node *node;
1067
1068         columns = json_array_create_empty();
1069         SHASH_FOR_EACH (node, &ts->columns) {
1070             const struct ovsdb_column *column = node->data;
1071
1072             if (strcmp(column->name, "_version")) {
1073                 json_array_add(columns, json_string_create(column->name));
1074             }
1075         }
1076
1077         op = json_object_create();
1078         json_object_put_string(op, "op", "select");
1079         json_object_put_string(op, "table", tables[i]->name);
1080         json_object_put(op, "where", json_array_create_empty());
1081         json_object_put(op, "columns", columns);
1082         json_array_add(transaction, op);
1083     }
1084
1085     /* Send request, get reply. */
1086     request = jsonrpc_create_request("transact", transaction, NULL);
1087     check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply);
1088
1089     /* Print database contents. */
1090     if (reply->result->type != JSON_ARRAY
1091         || reply->result->u.array.n != n_tables) {
1092         ovs_fatal(0, "reply is not array of %"PRIuSIZE" elements: %s",
1093                   n_tables, json_to_string(reply->result, 0));
1094     }
1095     for (i = 0; i < n_tables; i++) {
1096         const struct ovsdb_table_schema *ts = tables[i]->data;
1097         const struct json *op_result = reply->result->u.array.elems[i];
1098         struct json *rows;
1099
1100         if (op_result->type != JSON_OBJECT
1101             || !(rows = shash_find_data(json_object(op_result), "rows"))
1102             || rows->type != JSON_ARRAY) {
1103             ovs_fatal(0, "%s table reply is not an object with a \"rows\" "
1104                       "member array: %s",
1105                       ts->name, json_to_string(op_result, 0));
1106         }
1107
1108         dump_table(ts, &rows->u.array);
1109     }
1110
1111     jsonrpc_msg_destroy(reply);
1112     free(tables);
1113     ovsdb_schema_destroy(schema);
1114 }
1115
1116 static void
1117 do_help(struct jsonrpc *rpc OVS_UNUSED, const char *database OVS_UNUSED,
1118         int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
1119 {
1120     usage();
1121 }
1122
1123 /* All command handlers (except for "help") are expected to take an optional
1124  * server socket name (e.g. "unix:...") as their first argument.  The socket
1125  * name argument must be included in max_args (but left out of min_args).  The
1126  * command name and socket name are not included in the arguments passed to the
1127  * handler: the argv[0] passed to the handler is the first argument after the
1128  * optional server socket name.  The connection to the server is available as
1129  * global variable 'rpc'. */
1130 static const struct ovsdb_client_command all_commands[] = {
1131     { "list-dbs",           NEED_RPC,      0, 0,       do_list_dbs },
1132     { "get-schema",         NEED_DATABASE, 0, 0,       do_get_schema },
1133     { "get-schema-version", NEED_DATABASE, 0, 0,       do_get_schema_version },
1134     { "list-tables",        NEED_DATABASE, 0, 0,       do_list_tables },
1135     { "list-columns",       NEED_DATABASE, 0, 1,       do_list_columns },
1136     { "transact",           NEED_RPC,      1, 1,       do_transact },
1137     { "monitor",            NEED_DATABASE, 1, INT_MAX, do_monitor },
1138     { "dump",               NEED_DATABASE, 0, 0,       do_dump },
1139
1140     { "help",               NEED_NONE,     0, INT_MAX, do_help },
1141
1142     { NULL,                 0,             0, 0,       NULL },
1143 };
1144
1145 static const struct ovsdb_client_command *get_all_commands(void)
1146 {
1147     return all_commands;
1148 }