X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fovs-vsctl.c;h=61ff5bbd16d1598655586ec87c6d9055f438df13;hb=92dbd5c9e3134eabc6e57b397dd18493bc96c9b8;hp=911d8fe822db11fb0bdc7c97a3dace09652ab5e1;hpb=24b8b259bb06af4e6ded4401a6eb41672ca0a58f;p=openvswitch diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 911d8fe8..61ff5bbd 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. @@ -39,6 +39,7 @@ #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 +62,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 +91,7 @@ struct vsctl_command { /* Data modified by commands. */ struct ds output; + struct table *table; }; /* --db: The database server to contact. */ @@ -107,6 +109,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 +143,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 +200,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 +213,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 +226,8 @@ parse_options(int argc, char *argv[]) short_options = xasprintf("+%s", tmp); free(tmp); + table_style.format = TF_LIST; + for (;;) { int c; @@ -259,6 +273,7 @@ parse_options(int argc, char *argv[]) break; VLOG_OPTION_HANDLERS + TABLE_OPTION_HANDLERS(&table_style) #ifdef HAVE_OPENSSL STREAM_SSL_OPTION_HANDLERS @@ -508,6 +523,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\ @@ -564,6 +580,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; @@ -2650,54 +2667,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 +2826,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 +3189,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 +3293,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 +3325,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 +3339,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 +3357,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 +3404,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 +3471,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 +3497,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 +3531,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 +3591,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},