ofproto: Batch statistics updates.
[openvswitch] / utilities / ovs-vsctl.c
index 66ba41818cb0285ca40e93ea290f376e3ba281cf..31c485bab7afc9ccf6b540c9f65eff41cf828c72 100644 (file)
 #include "ovsdb-idl.h"
 #include "poll-loop.h"
 #include "process.h"
+#include "stream.h"
 #include "stream-ssl.h"
 #include "svec.h"
 #include "vswitchd/vswitch-idl.h"
+#include "table.h"
 #include "timeval.h"
 #include "util.h"
 #include "vlog.h"
@@ -61,7 +63,7 @@ struct vsctl_command_syntax {
     void (*prerequisites)(struct vsctl_context *ctx);
 
     /* Does the actual work of the command and puts the command's output, if
-     * any, in ctx->output.
+     * any, in ctx->output or ctx->table.
      *
      * Alternatively, if some prerequisite of the command is not met and the
      * caller should wait for something to change and then retry, it may set
@@ -90,6 +92,7 @@ struct vsctl_command {
 
     /* Data modified by commands. */
     struct ds output;
+    struct table *table;
 };
 
 /* --db: The database server to contact. */
@@ -107,6 +110,9 @@ static bool wait_for_reload = true;
 /* --timeout: Time to wait for a connection to 'db'. */
 static int timeout;
 
+/* Format for table output. */
+static struct table_style table_style = TABLE_STYLE_DEFAULT;
+
 /* All supported commands. */
 static const struct vsctl_command_syntax all_commands[];
 
@@ -195,7 +201,8 @@ parse_options(int argc, char *argv[])
         OPT_NO_WAIT,
         OPT_DRY_RUN,
         OPT_PEER_CA_CERT,
-        VLOG_OPTION_ENUMS
+        VLOG_OPTION_ENUMS,
+        TABLE_OPTION_ENUMS
     };
     static struct option long_options[] = {
         {"db", required_argument, 0, OPT_DB},
@@ -207,6 +214,7 @@ parse_options(int argc, char *argv[])
         {"help", no_argument, 0, 'h'},
         {"version", no_argument, 0, 'V'},
         VLOG_LONG_OPTIONS,
+        TABLE_LONG_OPTIONS,
 #ifdef HAVE_OPENSSL
         STREAM_SSL_LONG_OPTIONS
         {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
@@ -219,6 +227,8 @@ parse_options(int argc, char *argv[])
     short_options = xasprintf("+%s", tmp);
     free(tmp);
 
+    table_style.format = TF_LIST;
+
     for (;;) {
         int c;
 
@@ -264,6 +274,7 @@ parse_options(int argc, char *argv[])
             break;
 
         VLOG_OPTION_HANDLERS
+        TABLE_OPTION_HANDLERS(&table_style)
 
 #ifdef HAVE_OPENSSL
         STREAM_SSL_OPTION_HANDLERS
@@ -465,6 +476,10 @@ usage(void)
 %s: ovs-vswitchd management utility\n\
 usage: %s [OPTIONS] COMMAND [ARG...]\n\
 \n\
+Open vSwitch commands:\n\
+  init                        initialize database, if not yet initialized\n\
+  emer-reset                  reset configuration to clean state\n\
+\n\
 Bridge commands:\n\
   add-br BRIDGE               create a new bridge named BRIDGE\n\
   add-br BRIDGE PARENT VLAN   create new fake BRIDGE in PARENT on VLAN\n\
@@ -478,13 +493,12 @@ Bridge commands:\n\
   br-get-external-id BRIDGE KEY  print value of KEY on BRIDGE\n\
   br-get-external-id BRIDGE  list key-value pairs on BRIDGE\n\
 \n\
-Port commands:\n\
+Port commands (a bond is considered to be a single port):\n\
   list-ports BRIDGE           print the names of all the ports on BRIDGE\n\
   add-port BRIDGE PORT        add network device PORT to BRIDGE\n\
   add-bond BRIDGE PORT IFACE...  add bonded port PORT in BRIDGE from IFACES\n\
   del-port [BRIDGE] PORT      delete PORT (which may be bonded) from BRIDGE\n\
   port-to-br PORT             print name of bridge that contains PORT\n\
-A bond is considered to be a single port.\n\
 \n\
 Interface commands (a bond consists of multiple interfaces):\n\
   list-ifaces BRIDGE          print the names of all interfaces on BRIDGE\n\
@@ -527,9 +541,15 @@ Potentially unsafe database commands require --force option.\n\
 Options:\n\
   --db=DATABASE               connect to DATABASE\n\
                               (default: %s)\n\
+  --no-wait                   do not wait for ovs-vswitchd to reconfigure\n\
+  -t, --timeout=SECS          wait at most SECS seconds for ovs-vswitchd\n\
+  --dry-run                   do not commit changes to database\n\
   --oneline                   print exactly one line of output per command\n",
            program_name, program_name, default_db());
     vlog_usage();
+    printf("\
+  --no-syslog             equivalent to --verbose=vsctl:syslog:warn\n");
+    stream_usage("database", true, true, false);
     printf("\n\
 Other options:\n\
   -h, --help                  display this help message\n\
@@ -570,6 +590,7 @@ struct vsctl_context {
 
     /* Modifiable state. */
     struct ds output;
+    struct table *table;
     struct ovsdb_idl *idl;
     struct ovsdb_idl_txn *txn;
     struct ovsdb_symbol_table *symtab;
@@ -988,7 +1009,6 @@ cmd_init(struct vsctl_context *ctx OVS_UNUSED)
 static void
 pre_cmd_emer_reset(struct vsctl_context *ctx)
 {
-    ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_managers);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
 
@@ -1023,7 +1043,6 @@ cmd_emer_reset(struct vsctl_context *ctx)
     const struct ovsrec_sflow *sflow, *next_sflow;
 
     /* Reset the Open_vSwitch table. */
-    ovsrec_open_vswitch_set_managers(ctx->ovs, NULL, 0);
     ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
     ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
 
@@ -1877,7 +1896,6 @@ verify_managers(const struct ovsrec_open_vswitch *ovs)
 {
     size_t i;
 
-    ovsrec_open_vswitch_verify_managers(ovs);
     ovsrec_open_vswitch_verify_manager_options(ovs);
 
     for (i = 0; i < ovs->n_manager_options; ++i) {
@@ -1890,7 +1908,6 @@ verify_managers(const struct ovsrec_open_vswitch *ovs)
 static void
 pre_manager(struct vsctl_context *ctx)
 {
-    ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_managers);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
     ovsdb_idl_add_column(ctx->idl, &ovsrec_manager_col_target);
 }
@@ -1907,12 +1924,6 @@ cmd_get_manager(struct vsctl_context *ctx)
     /* Print the targets in sorted order for reproducibility. */
     svec_init(&targets);
 
-    /* First, add all targets found in deprecated 'managers' column. */
-    for (i = 0; i < ovs->n_managers; i++) {
-        svec_add(&targets, ovs->managers[i]);
-    }
-
-    /* Second, add all targets pointed to by 'manager_options' column. */
     for (i = 0; i < ovs->n_manager_options; i++) {
         svec_add(&targets, ovs->manager_options[i]->target);
     }
@@ -1930,9 +1941,6 @@ delete_managers(const struct vsctl_context *ctx)
     const struct ovsrec_open_vswitch *ovs = ctx->ovs;
     size_t i;
 
-    /* Delete manager targets in deprecated 'managers' column. */
-    ovsrec_open_vswitch_set_managers(ovs, NULL, 0);
-
     /* Delete Manager rows pointed to by 'manager_options' column. */
     for (i = 0; i < ovs->n_manager_options; i++) {
         ovsrec_manager_delete(ovs->manager_options[i]);
@@ -1957,9 +1965,6 @@ insert_managers(struct vsctl_context *ctx, char *targets[], size_t n)
     struct ovsrec_manager **managers;
     size_t i;
 
-    /* Store in deprecated 'manager' column. */
-    ovsrec_open_vswitch_set_managers(ctx->ovs, targets, n);
-
     /* Insert each manager in a new row in Manager table. */
     managers = xmalloc(n * sizeof *managers);
     for (i = 0; i < n; i++) {
@@ -2737,24 +2742,54 @@ pre_cmd_list(struct vsctl_context *ctx)
     pre_list_columns(ctx, table, column_names);
 }
 
+static struct table *
+list_make_table(const struct ovsdb_idl_column **columns, size_t n_columns)
+{
+    struct table *out;
+    size_t i;
+
+    out = xmalloc(sizeof *out);
+    table_init(out);
+
+    for (i = 0; i < n_columns; i++) {
+        const struct ovsdb_idl_column *column = columns[i];
+        const char *column_name = column ? column->name : "_uuid";
+
+        table_add_column(out, "%s", column_name);
+    }
+
+    return out;
+}
+
 static void
 list_record(const struct ovsdb_idl_row *row,
             const struct ovsdb_idl_column **columns, size_t n_columns,
-            struct ds *out)
+            struct table *out)
 {
     size_t i;
 
+    table_add_row(out);
     for (i = 0; i < n_columns; i++) {
         const struct ovsdb_idl_column *column = columns[i];
+        struct cell *cell = table_add_cell(out);
 
         if (!column) {
-            ds_put_format(out, "%-20s: "UUID_FMT"\n", "_uuid",
-                          UUID_ARGS(&row->uuid));
+            struct ovsdb_datum datum;
+            union ovsdb_atom atom;
+
+            atom.uuid = row->uuid;
+
+            datum.keys = &atom;
+            datum.values = NULL;
+            datum.n = 1;
+
+            cell->json = ovsdb_datum_to_json(&datum, &ovsdb_type_uuid);
+            cell->type = &ovsdb_type_uuid;
         } else {
             const struct ovsdb_datum *datum = ovsdb_idl_read(row, column);
-            ds_put_format(out, "%-20s: ", column->name);
-            ovsdb_datum_to_string(datum, &column->type, out);
-            ds_put_char(out, '\n');
+
+            cell->json = ovsdb_datum_to_json(datum, &column->type);
+            cell->type = &column->type;
         }
     }
 }
@@ -2766,17 +2801,15 @@ cmd_list(struct vsctl_context *ctx)
     const struct ovsdb_idl_column **columns;
     const char *table_name = ctx->argv[1];
     const struct vsctl_table_class *table;
-    struct ds *out = &ctx->output;
+    struct table *out;
     size_t n_columns;
     int i;
 
     table = get_table(table_name);
     parse_column_names(column_names, table, &columns, &n_columns);
+    out = ctx->table = list_make_table(columns, n_columns);
     if (ctx->argc > 2) {
         for (i = 2; i < ctx->argc; i++) {
-            if (i > 2) {
-                ds_put_char(out, '\n');
-            }
             list_record(must_get_row(ctx, table, ctx->argv[i]),
                         columns, n_columns, out);
         }
@@ -2787,9 +2820,6 @@ cmd_list(struct vsctl_context *ctx)
         for (row = ovsdb_idl_first_row(ctx->idl, table->class), first = true;
              row != NULL;
              row = ovsdb_idl_next_row(row), first = false) {
-            if (!first) {
-                ds_put_char(out, '\n');
-            }
             list_record(row, columns, n_columns, out);
         }
     }
@@ -2819,12 +2849,12 @@ cmd_find(struct vsctl_context *ctx)
     const char *table_name = ctx->argv[1];
     const struct vsctl_table_class *table;
     const struct ovsdb_idl_row *row;
-    struct ds *out = &ctx->output;
+    struct table *out;
     size_t n_columns;
 
     table = get_table(table_name);
     parse_column_names(column_names, table, &columns, &n_columns);
-
+    out = ctx->table = list_make_table(columns, n_columns);
     for (row = ovsdb_idl_first_row(ctx->idl, table->class); row;
          row = ovsdb_idl_next_row(row)) {
         int i;
@@ -2835,9 +2865,6 @@ cmd_find(struct vsctl_context *ctx)
                 goto next_row;
             }
         }
-        if (out->length) {
-            ds_put_char(out, '\n');
-        }
         list_record(row, columns, n_columns, out);
 
     next_row: ;
@@ -3292,6 +3319,7 @@ vsctl_context_init(struct vsctl_context *ctx, struct vsctl_command *command,
     ctx->options = command->options;
 
     ds_swap(&ctx->output, &command->output);
+    ctx->table = command->table;
     ctx->idl = idl;
     ctx->txn = txn;
     ctx->ovs = ovs;
@@ -3305,6 +3333,7 @@ static void
 vsctl_context_done(struct vsctl_context *ctx, struct vsctl_command *command)
 {
     ds_swap(&ctx->output, &command->output);
+    command->table = ctx->table;
 }
 
 static void
@@ -3322,12 +3351,14 @@ run_prerequisites(struct vsctl_command *commands, size_t n_commands,
             struct vsctl_context ctx;
 
             ds_init(&c->output);
+            c->table = NULL;
 
             vsctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
             (c->syntax->prerequisites)(&ctx);
             vsctl_context_done(&ctx, c);
 
             assert(!c->output.string);
+            assert(!c->table);
         }
     }
 }
@@ -3367,6 +3398,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     symtab = ovsdb_symbol_table_create();
     for (c = commands; c < &commands[n_commands]; c++) {
         ds_init(&c->output);
+        c->table = NULL;
     }
     for (c = commands; c < &commands[n_commands]; c++) {
         struct vsctl_context ctx;
@@ -3433,7 +3465,9 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
     for (c = commands; c < &commands[n_commands]; c++) {
         struct ds *ds = &c->output;
 
-        if (oneline) {
+        if (c->table) {
+            table_print(c->table, &table_style);
+        } else if (oneline) {
             size_t j;
 
             ds_chomp(ds, '\n');
@@ -3457,6 +3491,8 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
             fputs(ds_cstr(ds), stdout);
         }
         ds_destroy(&c->output);
+        table_destroy(c->table);
+        free(c->table);
 
         smap_destroy(&c->options);
     }
@@ -3489,6 +3525,8 @@ try_again:
     ovsdb_symbol_table_destroy(symtab);
     for (c = commands; c < &commands[n_commands]; c++) {
         ds_destroy(&c->output);
+        table_destroy(c->table);
+        free(c->table);
     }
     free(error);
 }