X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fovs-vsctl.c;h=31c485bab7afc9ccf6b540c9f65eff41cf828c72;hb=3394b5b69070b0aef4fc3231ca28bdf09bc0a0d2;hp=911d8fe822db11fb0bdc7c97a3dace09652ab5e1;hpb=24b8b259bb06af4e6ded4401a6eb41672ca0a58f;p=openvswitch diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 911d8fe8..31c485ba 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,9 +36,11 @@ #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[]; @@ -138,6 +144,11 @@ static void set_column(const struct vsctl_table_class *, const struct ovsdb_idl_row *, const char *arg, struct ovsdb_symbol_table *); +static bool is_condition_satisfied(const struct vsctl_table_class *, + const struct ovsdb_idl_row *, + const char *arg, + struct ovsdb_symbol_table *); + int main(int argc, char *argv[]) { @@ -190,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}, @@ -202,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}, @@ -214,6 +227,8 @@ parse_options(int argc, char *argv[]) short_options = xasprintf("+%s", tmp); free(tmp); + table_style.format = TF_LIST; + for (;;) { int c; @@ -259,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 @@ -460,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\ @@ -473,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\ @@ -508,6 +527,7 @@ Switch commands:\n\ \n\ Database commands:\n\ list TBL [REC] list RECord (or all records) in TBL\n\ + find TBL CONDITION... list records satisfying CONDITION in TBL\n\ get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\ set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\ add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\ @@ -521,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\ @@ -564,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; @@ -982,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); @@ -1017,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); @@ -1871,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) { @@ -1884,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); } @@ -1901,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); } @@ -1924,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]); @@ -1951,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++) { @@ -2650,54 +2661,157 @@ cmd_get(struct vsctl_context *ctx) } } +static void +parse_column_names(const char *column_names, + const struct vsctl_table_class *table, + const struct ovsdb_idl_column ***columnsp, + size_t *n_columnsp) +{ + const struct ovsdb_idl_column **columns; + size_t n_columns; + + if (!column_names) { + size_t i; + + n_columns = table->class->n_columns + 1; + columns = xmalloc(n_columns * sizeof *columns); + columns[0] = NULL; + for (i = 0; i < table->class->n_columns; i++) { + columns[i + 1] = &table->class->columns[i]; + } + } else { + char *s = xstrdup(column_names); + size_t allocated_columns; + char *save_ptr = NULL; + char *column_name; + + columns = NULL; + allocated_columns = n_columns = 0; + for (column_name = strtok_r(s, ", ", &save_ptr); column_name; + column_name = strtok_r(NULL, ", ", &save_ptr)) { + const struct ovsdb_idl_column *column; + + if (!strcasecmp(column_name, "_uuid")) { + column = NULL; + } else { + die_if_error(get_column(table, column_name, &column)); + } + if (n_columns >= allocated_columns) { + columns = x2nrealloc(columns, &allocated_columns, + sizeof *columns); + } + columns[n_columns++] = column; + } + free(s); + + if (!n_columns) { + vsctl_fatal("must specify at least one column name"); + } + } + *columnsp = columns; + *n_columnsp = n_columns; +} + + +static void +pre_list_columns(struct vsctl_context *ctx, + const struct vsctl_table_class *table, + const char *column_names) +{ + const struct ovsdb_idl_column **columns; + size_t n_columns; + size_t i; + + parse_column_names(column_names, table, &columns, &n_columns); + for (i = 0; i < n_columns; i++) { + if (columns[i]) { + ovsdb_idl_add_column(ctx->idl, columns[i]); + } + } + free(columns); +} + static void pre_cmd_list(struct vsctl_context *ctx) { + const char *column_names = shash_find_data(&ctx->options, "--columns"); const char *table_name = ctx->argv[1]; const struct vsctl_table_class *table; - size_t i; table = pre_get_table(ctx, table_name); - for (i = 0; i < table->class->n_columns; i++) { - ovsdb_idl_add_column(ctx->idl, &table->class->columns[i]); + 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 vsctl_table_class *table, - const struct ovsdb_idl_row *row, struct ds *out) +list_record(const struct ovsdb_idl_row *row, + const struct ovsdb_idl_column **columns, size_t n_columns, + struct table *out) { size_t i; - ds_put_format(out, "%-20s: "UUID_FMT"\n", "_uuid", - UUID_ARGS(&row->uuid)); - for (i = 0; i < table->class->n_columns; i++) { - const struct ovsdb_idl_column *column = &table->class->columns[i]; - const struct ovsdb_datum *datum; + 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); - datum = ovsdb_idl_read(row, column); + if (!column) { + struct ovsdb_datum datum; + union ovsdb_atom atom; - ds_put_format(out, "%-20s: ", column->name); - ovsdb_datum_to_string(datum, &column->type, out); - ds_put_char(out, '\n'); + 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); + + cell->json = ovsdb_datum_to_json(datum, &column->type); + cell->type = &column->type; + } } } static void cmd_list(struct vsctl_context *ctx) { + const char *column_names = shash_find_data(&ctx->options, "--columns"); + 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(table, must_get_row(ctx, table, ctx->argv[i]), out); + list_record(must_get_row(ctx, table, ctx->argv[i]), + columns, n_columns, out); } } else { const struct ovsdb_idl_row *row; @@ -2706,11 +2820,54 @@ 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); + } + } + free(columns); +} + +static void +pre_cmd_find(struct vsctl_context *ctx) +{ + const char *column_names = shash_find_data(&ctx->options, "--columns"); + const char *table_name = ctx->argv[1]; + const struct vsctl_table_class *table; + int i; + + table = pre_get_table(ctx, table_name); + pre_list_columns(ctx, table, column_names); + for (i = 2; i < ctx->argc; i++) { + pre_parse_column_key_value(ctx, ctx->argv[i], table); + } +} + +static void +cmd_find(struct vsctl_context *ctx) +{ + const char *column_names = shash_find_data(&ctx->options, "--columns"); + const struct ovsdb_idl_column **columns; + const char *table_name = ctx->argv[1]; + const struct vsctl_table_class *table; + const struct ovsdb_idl_row *row; + 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; + + for (i = 2; i < ctx->argc; i++) { + if (!is_condition_satisfied(table, row, ctx->argv[i], + ctx->symtab)) { + goto next_row; } - list_record(table, row, out); } + list_record(row, columns, n_columns, out); + + next_row: ; } } @@ -3026,9 +3183,9 @@ cmd_destroy(struct vsctl_context *ctx) } static bool -is_condition_satified(const struct vsctl_table_class *table, - const struct ovsdb_idl_row *row, const char *arg, - struct ovsdb_symbol_table *symtab) +is_condition_satisfied(const struct vsctl_table_class *table, + const struct ovsdb_idl_row *row, const char *arg, + struct ovsdb_symbol_table *symtab) { static const char *operators[] = { "=", "!=", "<", ">", "<=", ">=" @@ -3130,7 +3287,7 @@ cmd_wait_until(struct vsctl_context *ctx) } for (i = 3; i < ctx->argc; i++) { - if (!is_condition_satified(table, row, ctx->argv[i], ctx->symtab)) { + if (!is_condition_satisfied(table, row, ctx->argv[i], ctx->symtab)) { ctx->try_again = true; return; } @@ -3162,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; @@ -3175,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 @@ -3192,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); } } } @@ -3237,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; @@ -3303,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'); @@ -3327,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); } @@ -3359,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); } @@ -3417,7 +3585,8 @@ static const struct vsctl_command_syntax all_commands[] = { /* Parameter commands. */ {"get", 2, INT_MAX, pre_cmd_get, cmd_get, NULL, "--if-exists,--id=", RO}, - {"list", 1, INT_MAX, pre_cmd_list, cmd_list, NULL, "", RO}, + {"list", 1, INT_MAX, pre_cmd_list, cmd_list, NULL, "--columns=", RO}, + {"find", 1, INT_MAX, pre_cmd_find, cmd_find, NULL, "--columns=", RO}, {"set", 3, INT_MAX, pre_cmd_set, cmd_set, NULL, "", RW}, {"add", 4, INT_MAX, pre_cmd_add, cmd_add, NULL, "", RW}, {"remove", 4, INT_MAX, pre_cmd_remove, cmd_remove, NULL, "", RW},