2 * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "db-ctl-base.h"
25 #include "command-line.h"
28 #include "openvswitch/dynamic-string.h"
29 #include "fatal-signal.h"
31 #include "openvswitch/json.h"
32 #include "openvswitch/vlog.h"
33 #include "ovsdb-data.h"
34 #include "ovsdb-idl.h"
35 #include "ovsdb-idl-provider.h"
36 #include "openvswitch/shash.h"
42 VLOG_DEFINE_THIS_MODULE(db_ctl_base
);
44 /* This array defines the 'show' command output format. User can check the
45 * definition in utilities/ovs-vsctl.c as reference.
47 * Particularly, if an element in 'columns[]' represents a reference to
48 * another table, the referred table must also be defined as an entry in
49 * in 'cmd_show_tables[]'.
51 * The definition must end with an all-NULL entry. It is initalized once
52 * when ctl_init() is called.
55 static const struct cmd_show_table
*cmd_show_tables
;
57 /* ctl_exit() is called by ctl_fatal(). User can optionally supply an exit
58 * function ctl_exit_func() via ctl_init. If supplied, this function will
59 * be called by ctl_exit()
61 static void (*ctl_exit_func
)(int status
) = NULL
;
62 OVS_NO_RETURN
static void ctl_exit(int status
);
64 /* Two arrays with 'n_classes' elements, which represent the tables in this
65 * database and how the user can refer to their rows. */
66 static const struct ctl_table_class
*ctl_classes
;
67 static const struct ovsdb_idl_table_class
*idl_classes
;
68 static size_t n_classes
;
70 static struct shash all_commands
= SHASH_INITIALIZER(&all_commands
);
71 static const struct ovsdb_idl_table_class
*get_table(const char *table_name
);
72 static void set_column(const struct ovsdb_idl_table_class
*,
73 const struct ovsdb_idl_row
*, const char *,
74 struct ovsdb_symbol_table
*);
77 static struct option
*
78 find_option(const char *name
, struct option
*options
, size_t n_options
)
82 for (i
= 0; i
< n_options
; i
++) {
83 if (!strcmp(options
[i
].name
, name
)) {
90 static struct option
*
91 add_option(struct option
**optionsp
, size_t *n_optionsp
,
92 size_t *allocated_optionsp
)
94 if (*n_optionsp
>= *allocated_optionsp
) {
95 *optionsp
= x2nrealloc(*optionsp
, allocated_optionsp
,
98 return &(*optionsp
)[(*n_optionsp
)++];
101 /* Converts the command arguments into format that can be parsed by
102 * bash completion script.
104 * Therein, arguments will be attached with following prefixes:
106 * !argument :: The argument is required
107 * ?argument :: The argument is optional
108 * *argument :: The argument may appear any number (0 or more) times
109 * +argument :: The argument may appear one or more times
113 print_command_arguments(const struct ctl_command_syntax
*command
)
116 * The argument string is parsed in reverse. We use a stack 'oew_stack' to
117 * keep track of nested optionals. Whenever a ']' is encountered, we push
118 * a bit to 'oew_stack'. The bit is set to 1 if the ']' is not nested.
119 * Subsequently, we pop an entry everytime '[' is met.
121 * We use 'whole_word_is_optional' value to decide whether or not a ! or +
122 * should be added on encountering a space: if the optional surrounds the
123 * whole word then it shouldn't be, but if it is only a part of the word
124 * (i.e. [key=]value), it should be.
126 uint32_t oew_stack
= 0;
128 const char *arguments
= command
->arguments
;
129 int length
= strlen(arguments
);
134 /* Output buffer, written backward from end. */
135 char *output
= xmalloc(2 * length
);
136 char *outp
= output
+ 2 * length
;
139 bool in_repeated
= false;
140 bool whole_word_is_optional
= false;
142 for (const char *inp
= arguments
+ length
; inp
> arguments
; ) {
146 if (inp
[1] == '\0' || inp
[1] == ' ' || inp
[1] == '.') {
151 /* Checks if the whole word is optional, and sets the
152 * 'whole_word_is_optional' accordingly. */
153 if ((inp
== arguments
|| inp
[-1] == ' ') && oew_stack
& 1) {
154 *--outp
= in_repeated
? '*' : '?';
155 whole_word_is_optional
= true;
158 whole_word_is_optional
= false;
163 if (!whole_word_is_optional
) {
164 *--outp
= in_repeated
? '+' : '!';
168 whole_word_is_optional
= false;
178 if (arguments
[0] != '[' && outp
!= output
+ 2 * length
- 1) {
179 *--outp
= in_repeated
? '+' : '!';
186 die_if_error(char *error
)
189 ctl_fatal("%s", error
);
194 to_lower_and_underscores(unsigned c
)
196 return c
== '-' ? '_' : tolower(c
);
199 /* Returns a score representing how well 's' matches 'name'. Higher return
200 * values indicate a better match. The order of the arguments is important:
201 * 'name' is the name of an entity such as a table or a column, and 's' is user
204 score_partial_match(const char *name
, const char *s
)
208 if (!strcmp(name
, s
)) {
211 for (score
= 0; ; score
++, name
++, s
++) {
212 if (to_lower_and_underscores(*name
) != to_lower_and_underscores(*s
)) {
214 } else if (*name
== '\0') {
218 return *s
== '\0' ? score
: 0;
221 static struct ovsdb_symbol
*
222 create_symbol(struct ovsdb_symbol_table
*symtab
, const char *id
, bool *newp
)
224 struct ovsdb_symbol
*symbol
;
227 ctl_fatal("row id \"%s\" does not begin with \"@\"", id
);
231 *newp
= ovsdb_symbol_table_get(symtab
, id
) == NULL
;
234 symbol
= ovsdb_symbol_table_insert(symtab
, id
);
235 if (symbol
->created
) {
236 ctl_fatal("row id \"%s\" may only be specified on one --id option",
239 symbol
->created
= true;
243 static const struct ovsdb_idl_row
*
244 get_row_by_id(struct ctl_context
*ctx
,
245 const struct ovsdb_idl_table_class
*table
,
246 const struct ctl_row_id
*id
, const char *record_id
)
249 if (!id
->table
|| !id
->name_column
) {
253 const struct ovsdb_idl_row
*referrer
= NULL
;
254 ovs_assert(id
->name_column
->type
.value
.type
== OVSDB_TYPE_VOID
);
256 enum ovsdb_atomic_type key
= id
->name_column
->type
.key
.type
;
257 if (key
== OVSDB_TYPE_INTEGER
) {
258 if (!record_id
[0] || record_id
[strspn(record_id
, "0123456789")]) {
262 ovs_assert(key
== OVSDB_TYPE_STRING
);
265 for (const struct ovsdb_idl_row
*row
= ovsdb_idl_first_row(ctx
->idl
,
268 row
= ovsdb_idl_next_row(row
)) {
269 const struct ovsdb_datum
*name
= ovsdb_idl_get(
270 row
, id
->name_column
, key
, OVSDB_TYPE_VOID
);
272 const union ovsdb_atom
*atom
= &name
->keys
[0];
273 if (key
== OVSDB_TYPE_STRING
274 ? !strcmp(atom
->string
, record_id
)
275 : atom
->integer
== strtoll(record_id
, NULL
, 10)) {
277 ctl_fatal("multiple rows in %s match \"%s\"",
278 table
->name
, record_id
);
288 const struct ovsdb_idl_row
*final
= referrer
;
289 if (id
->uuid_column
) {
290 const struct ovsdb_datum
*uuid
;
292 ovsdb_idl_txn_verify(referrer
, id
->uuid_column
);
293 uuid
= ovsdb_idl_get(referrer
, id
->uuid_column
,
294 OVSDB_TYPE_UUID
, OVSDB_TYPE_VOID
);
296 final
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
,
297 &uuid
->keys
[0].uuid
);
303 static const struct ovsdb_idl_row
*
304 get_row(struct ctl_context
*ctx
,
305 const struct ovsdb_idl_table_class
*table
, const char *record_id
,
308 const struct ovsdb_idl_row
*row
= NULL
;
311 if (uuid_from_string(&uuid
, record_id
)) {
312 row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
, &uuid
);
315 if (!strcmp(record_id
, ".")) {
316 row
= ovsdb_idl_first_row(ctx
->idl
, table
);
317 if (row
&& ovsdb_idl_next_row(row
)) {
323 const struct ctl_table_class
*ctl_class
324 = &ctl_classes
[table
- idl_classes
];
325 for (int i
= 0; i
< ARRAY_SIZE(ctl_class
->row_ids
); i
++) {
326 row
= get_row_by_id(ctx
, table
, &ctl_class
->row_ids
[i
],
333 if (!row
&& uuid_is_partial_string(record_id
) >= 4) {
334 for (const struct ovsdb_idl_row
*r
= ovsdb_idl_first_row(ctx
->idl
,
337 r
= ovsdb_idl_next_row(r
)) {
338 if (uuid_is_partial_match(&r
->uuid
, record_id
)) {
342 ctl_fatal("%s contains 2 or more rows whose UUIDs begin "
343 "with %s: at least "UUID_FMT
" and "UUID_FMT
,
344 table
->name
, record_id
,
345 UUID_ARGS(&row
->uuid
),
346 UUID_ARGS(&r
->uuid
));
351 if (must_exist
&& !row
) {
352 ctl_fatal("no row \"%s\" in table %s", record_id
, table
->name
);
358 get_column(const struct ovsdb_idl_table_class
*table
, const char *column_name
,
359 const struct ovsdb_idl_column
**columnp
)
361 const struct ovsdb_idl_column
*best_match
= NULL
;
362 unsigned int best_score
= 0;
365 for (i
= 0; i
< table
->n_columns
; i
++) {
366 const struct ovsdb_idl_column
*column
= &table
->columns
[i
];
367 unsigned int score
= score_partial_match(column
->name
, column_name
);
368 if (score
> best_score
) {
371 } else if (score
== best_score
) {
376 *columnp
= best_match
;
379 } else if (best_score
) {
380 return xasprintf("%s contains more than one column whose name "
381 "matches \"%s\"", table
->name
, column_name
);
383 return xasprintf("%s does not contain a column whose name matches "
384 "\"%s\"", table
->name
, column_name
);
389 pre_get_column(struct ctl_context
*ctx
,
390 const struct ovsdb_idl_table_class
*table
,
391 const char *column_name
,
392 const struct ovsdb_idl_column
**columnp
)
394 die_if_error(get_column(table
, column_name
, columnp
));
395 ovsdb_idl_add_column(ctx
->idl
, *columnp
);
398 static const struct ovsdb_idl_table_class
*
399 pre_get_table(struct ctl_context
*ctx
, const char *table_name
)
401 const struct ovsdb_idl_table_class
*table
= get_table(table_name
);
402 ovsdb_idl_add_table(ctx
->idl
, table
);
404 const struct ctl_table_class
*ctl
= &ctl_classes
[table
- idl_classes
];
405 for (int i
= 0; i
< ARRAY_SIZE(ctl
->row_ids
); i
++) {
406 const struct ctl_row_id
*id
= &ctl
->row_ids
[i
];
408 ovsdb_idl_add_table(ctx
->idl
, id
->table
);
410 if (id
->name_column
) {
411 ovsdb_idl_add_column(ctx
->idl
, id
->name_column
);
413 if (id
->uuid_column
) {
414 ovsdb_idl_add_column(ctx
->idl
, id
->uuid_column
);
422 missing_operator_error(const char *arg
, const char **allowed_operators
,
428 ds_put_format(&s
, "%s: argument does not end in ", arg
);
429 ds_put_format(&s
, "\"%s\"", allowed_operators
[0]);
430 if (n_allowed
== 2) {
431 ds_put_format(&s
, " or \"%s\"", allowed_operators
[1]);
432 } else if (n_allowed
> 2) {
435 for (i
= 1; i
< n_allowed
- 1; i
++) {
436 ds_put_format(&s
, ", \"%s\"", allowed_operators
[i
]);
438 ds_put_format(&s
, ", or \"%s\"", allowed_operators
[i
]);
440 ds_put_format(&s
, " followed by a value.");
442 return ds_steal_cstr(&s
);
445 /* Breaks 'arg' apart into a number of fields in the following order:
447 * - The name of a column in 'table', stored into '*columnp'. The column
448 * name may be abbreviated.
450 * - Optionally ':' followed by a key string. The key is stored as a
451 * malloc()'d string into '*keyp', or NULL if no key is present in
454 * - If 'valuep' is nonnull, an operator followed by a value string. The
455 * allowed operators are the 'n_allowed' string in 'allowed_operators',
456 * or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
457 * index of the operator within 'allowed_operators' is stored into
458 * '*operatorp'. The value is stored as a malloc()'d string into
459 * '*valuep', or NULL if no value is present in 'arg'.
461 * On success, returns NULL. On failure, returned a malloc()'d string error
462 * message and stores NULL into all of the nonnull output arguments. */
463 static char * OVS_WARN_UNUSED_RESULT
464 parse_column_key_value(const char *arg
,
465 const struct ovsdb_idl_table_class
*table
,
466 const struct ovsdb_idl_column
**columnp
, char **keyp
,
468 const char **allowed_operators
, size_t n_allowed
,
475 ovs_assert(!(operatorp
&& !valuep
));
481 /* Parse column name. */
482 error
= ovsdb_token_parse(&p
, &column_name
);
486 if (column_name
[0] == '\0') {
488 error
= xasprintf("%s: missing column name", arg
);
491 error
= get_column(table
, column_name
, columnp
);
497 /* Parse key string. */
500 error
= ovsdb_token_parse(&p
, keyp
);
506 /* Parse value string. */
512 if (!allowed_operators
) {
513 static const char *equals
= "=";
514 allowed_operators
= &equals
;
520 for (i
= 0; i
< n_allowed
; i
++) {
521 const char *op
= allowed_operators
[i
];
522 size_t op_len
= strlen(op
);
524 if (op_len
> best_len
&& !strncmp(op
, p
, op_len
) && p
[op_len
]) {
530 error
= missing_operator_error(arg
, allowed_operators
, n_allowed
);
537 *valuep
= xstrdup(p
+ best_len
);
540 error
= xasprintf("%s: trailing garbage \"%s\" in argument",
561 static const struct ovsdb_idl_column
*
562 pre_parse_column_key_value(struct ctl_context
*ctx
,
564 const struct ovsdb_idl_table_class
*table
)
566 const struct ovsdb_idl_column
*column
;
571 die_if_error(ovsdb_token_parse(&p
, &column_name
));
572 if (column_name
[0] == '\0') {
573 ctl_fatal("%s: missing column name", arg
);
576 pre_get_column(ctx
, table
, column_name
, &column
);
583 check_mutable(const struct ovsdb_idl_row
*row
,
584 const struct ovsdb_idl_column
*column
)
586 if (!ovsdb_idl_is_mutable(row
, column
)) {
587 ctl_fatal("cannot modify read-only column %s in table %s",
588 column
->name
, row
->table
->class->name
);
593 RELOP(RELOP_EQ, "=") \
594 RELOP(RELOP_NE, "!=") \
595 RELOP(RELOP_LT, "<") \
596 RELOP(RELOP_GT, ">") \
597 RELOP(RELOP_LE, "<=") \
598 RELOP(RELOP_GE, ">=") \
599 RELOP(RELOP_SET_EQ, "{=}") \
600 RELOP(RELOP_SET_NE, "{!=}") \
601 RELOP(RELOP_SET_LT, "{<}") \
602 RELOP(RELOP_SET_GT, "{>}") \
603 RELOP(RELOP_SET_LE, "{<=}") \
604 RELOP(RELOP_SET_GE, "{>=}")
607 #define RELOP(ENUM, STRING) ENUM,
613 is_set_operator(enum relop op
)
615 return (op
== RELOP_SET_EQ
|| op
== RELOP_SET_NE
||
616 op
== RELOP_SET_LT
|| op
== RELOP_SET_GT
||
617 op
== RELOP_SET_LE
|| op
== RELOP_SET_GE
);
621 evaluate_relop(const struct ovsdb_datum
*a
, const struct ovsdb_datum
*b
,
622 const struct ovsdb_type
*type
, enum relop op
)
627 return ovsdb_datum_compare_3way(a
, b
, type
) == 0;
630 return ovsdb_datum_compare_3way(a
, b
, type
) != 0;
632 return ovsdb_datum_compare_3way(a
, b
, type
) < 0;
634 return ovsdb_datum_compare_3way(a
, b
, type
) > 0;
636 return ovsdb_datum_compare_3way(a
, b
, type
) <= 0;
638 return ovsdb_datum_compare_3way(a
, b
, type
) >= 0;
641 return b
->n
> a
->n
&& ovsdb_datum_includes_all(a
, b
, type
);
643 return a
->n
> b
->n
&& ovsdb_datum_includes_all(b
, a
, type
);
645 return ovsdb_datum_includes_all(a
, b
, type
);
647 return ovsdb_datum_includes_all(b
, a
, type
);
655 is_condition_satisfied(const struct ovsdb_idl_table_class
*table
,
656 const struct ovsdb_idl_row
*row
, const char *arg
,
657 struct ovsdb_symbol_table
*symtab
)
659 static const char *operators
[] = {
660 #define RELOP(ENUM, STRING) STRING,
665 const struct ovsdb_idl_column
*column
;
666 const struct ovsdb_datum
*have_datum
;
667 char *key_string
, *value_string
;
668 struct ovsdb_type type
;
673 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
674 &operator, operators
, ARRAY_SIZE(operators
),
678 ctl_fatal("%s: missing value", arg
);
682 type
.n_max
= UINT_MAX
;
684 have_datum
= ovsdb_idl_read(row
, column
);
686 union ovsdb_atom want_key
;
687 struct ovsdb_datum b
;
690 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
691 ctl_fatal("cannot specify key to check for non-map column %s",
695 die_if_error(ovsdb_atom_from_string(&want_key
, NULL
, &column
->type
.key
,
696 key_string
, symtab
));
698 type
.key
= type
.value
;
699 type
.value
.type
= OVSDB_TYPE_VOID
;
700 die_if_error(ovsdb_datum_from_string(&b
, &type
, value_string
, symtab
));
702 idx
= ovsdb_datum_find_key(have_datum
,
703 &want_key
, column
->type
.key
.type
);
704 if (idx
== UINT_MAX
&& !is_set_operator(operator)) {
707 struct ovsdb_datum a
;
709 if (idx
!= UINT_MAX
) {
711 a
.keys
= &have_datum
->values
[idx
];
719 retval
= evaluate_relop(&a
, &b
, &type
, operator);
722 ovsdb_atom_destroy(&want_key
, column
->type
.key
.type
);
723 ovsdb_datum_destroy(&b
, &type
);
725 struct ovsdb_datum want_datum
;
727 die_if_error(ovsdb_datum_from_string(&want_datum
, &column
->type
,
728 value_string
, symtab
));
729 retval
= evaluate_relop(have_datum
, &want_datum
, &type
, operator);
730 ovsdb_datum_destroy(&want_datum
, &column
->type
);
740 invalidate_cache(struct ctl_context
*ctx
)
742 if (ctx
->invalidate_cache
) {
743 (ctx
->invalidate_cache
)(ctx
);
748 pre_cmd_get(struct ctl_context
*ctx
)
750 const char *id
= shash_find_data(&ctx
->options
, "--id");
751 const char *table_name
= ctx
->argv
[1];
752 const struct ovsdb_idl_table_class
*table
;
755 /* Using "get" without --id or a column name could possibly make sense.
756 * Maybe, for example, a *ctl command run wants to assert that a row
757 * exists. But it is unlikely that an interactive user would want to do
758 * that, so issue a warning if we're running on a terminal. */
759 if (!id
&& ctx
->argc
<= 3 && isatty(STDOUT_FILENO
)) {
760 VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
761 "possibly erroneous");
764 table
= pre_get_table(ctx
, table_name
);
765 for (i
= 3; i
< ctx
->argc
; i
++) {
766 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
767 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
771 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
776 cmd_get(struct ctl_context
*ctx
)
778 const char *id
= shash_find_data(&ctx
->options
, "--id");
779 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
780 const char *table_name
= ctx
->argv
[1];
781 const char *record_id
= ctx
->argv
[2];
782 const struct ovsdb_idl_table_class
*table
;
783 const struct ovsdb_idl_row
*row
;
784 struct ds
*out
= &ctx
->output
;
787 if (id
&& !must_exist
) {
788 ctl_fatal("--if-exists and --id may not be specified together");
791 table
= get_table(table_name
);
792 row
= get_row(ctx
, table
, record_id
, must_exist
);
798 struct ovsdb_symbol
*symbol
;
801 symbol
= create_symbol(ctx
->symtab
, id
, &new);
803 ctl_fatal("row id \"%s\" specified on \"get\" command was used "
804 "before it was defined", id
);
806 symbol
->uuid
= row
->uuid
;
808 /* This symbol refers to a row that already exists, so disable warnings
809 * about it being unreferenced. */
810 symbol
->strong_ref
= true;
812 for (i
= 3; i
< ctx
->argc
; i
++) {
813 const struct ovsdb_idl_column
*column
;
814 const struct ovsdb_datum
*datum
;
817 /* Special case for obtaining the UUID of a row. We can't just do this
818 * through parse_column_key_value() below since it returns a "struct
819 * ovsdb_idl_column" and the UUID column doesn't have one. */
820 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
821 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
822 ds_put_format(out
, UUID_FMT
"\n", UUID_ARGS(&row
->uuid
));
826 die_if_error(parse_column_key_value(ctx
->argv
[i
], table
,
827 &column
, &key_string
,
828 NULL
, NULL
, 0, NULL
));
830 ovsdb_idl_txn_verify(row
, column
);
831 datum
= ovsdb_idl_read(row
, column
);
833 union ovsdb_atom key
;
836 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
837 ctl_fatal("cannot specify key to get for non-map column %s",
841 die_if_error(ovsdb_atom_from_string(&key
, NULL
,
843 key_string
, ctx
->symtab
));
845 idx
= ovsdb_datum_find_key(datum
, &key
,
846 column
->type
.key
.type
);
847 if (idx
== UINT_MAX
) {
849 ctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
850 key_string
, table
->name
, record_id
,
854 ovsdb_atom_to_string(&datum
->values
[idx
],
855 column
->type
.value
.type
, out
);
857 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
859 ovsdb_datum_to_string(datum
, &column
->type
, out
);
861 ds_put_char(out
, '\n');
868 parse_column_names(const char *column_names
,
869 const struct ovsdb_idl_table_class
*table
,
870 const struct ovsdb_idl_column
***columnsp
,
873 const struct ovsdb_idl_column
**columns
;
879 n_columns
= table
->n_columns
+ 1;
880 columns
= xmalloc(n_columns
* sizeof *columns
);
882 for (i
= 0; i
< table
->n_columns
; i
++) {
883 columns
[i
+ 1] = &table
->columns
[i
];
886 char *s
= xstrdup(column_names
);
887 size_t allocated_columns
;
888 char *save_ptr
= NULL
;
892 allocated_columns
= n_columns
= 0;
893 for (column_name
= strtok_r(s
, ", ", &save_ptr
); column_name
;
894 column_name
= strtok_r(NULL
, ", ", &save_ptr
)) {
895 const struct ovsdb_idl_column
*column
;
897 if (!strcasecmp(column_name
, "_uuid")) {
900 die_if_error(get_column(table
, column_name
, &column
));
902 if (n_columns
>= allocated_columns
) {
903 columns
= x2nrealloc(columns
, &allocated_columns
,
906 columns
[n_columns
++] = column
;
911 ctl_fatal("must specify at least one column name");
915 *n_columnsp
= n_columns
;
919 pre_list_columns(struct ctl_context
*ctx
,
920 const struct ovsdb_idl_table_class
*table
,
921 const char *column_names
)
923 const struct ovsdb_idl_column
**columns
;
927 parse_column_names(column_names
, table
, &columns
, &n_columns
);
928 for (i
= 0; i
< n_columns
; i
++) {
930 ovsdb_idl_add_column(ctx
->idl
, columns
[i
]);
937 pre_cmd_list(struct ctl_context
*ctx
)
939 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
940 const char *table_name
= ctx
->argv
[1];
941 const struct ovsdb_idl_table_class
*table
;
943 table
= pre_get_table(ctx
, table_name
);
944 pre_list_columns(ctx
, table
, column_names
);
947 static struct table
*
948 list_make_table(const struct ovsdb_idl_column
**columns
, size_t n_columns
)
953 out
= xmalloc(sizeof *out
);
956 for (i
= 0; i
< n_columns
; i
++) {
957 const struct ovsdb_idl_column
*column
= columns
[i
];
958 const char *column_name
= column
? column
->name
: "_uuid";
960 table_add_column(out
, "%s", column_name
);
967 list_record(const struct ovsdb_idl_row
*row
,
968 const struct ovsdb_idl_column
**columns
, size_t n_columns
,
978 for (i
= 0; i
< n_columns
; i
++) {
979 const struct ovsdb_idl_column
*column
= columns
[i
];
980 struct cell
*cell
= table_add_cell(out
);
983 struct ovsdb_datum datum
;
984 union ovsdb_atom atom
;
986 atom
.uuid
= row
->uuid
;
992 cell
->json
= ovsdb_datum_to_json(&datum
, &ovsdb_type_uuid
);
993 cell
->type
= &ovsdb_type_uuid
;
995 const struct ovsdb_datum
*datum
= ovsdb_idl_read(row
, column
);
997 cell
->json
= ovsdb_datum_to_json(datum
, &column
->type
);
998 cell
->type
= &column
->type
;
1004 cmd_list(struct ctl_context
*ctx
)
1006 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
1007 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1008 const struct ovsdb_idl_column
**columns
;
1009 const char *table_name
= ctx
->argv
[1];
1010 const struct ovsdb_idl_table_class
*table
;
1015 table
= get_table(table_name
);
1016 parse_column_names(column_names
, table
, &columns
, &n_columns
);
1017 out
= ctx
->table
= list_make_table(columns
, n_columns
);
1018 if (ctx
->argc
> 2) {
1019 for (i
= 2; i
< ctx
->argc
; i
++) {
1020 list_record(get_row(ctx
, table
, ctx
->argv
[i
], must_exist
),
1021 columns
, n_columns
, out
);
1024 const struct ovsdb_idl_row
*row
;
1026 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
); row
!= NULL
;
1027 row
= ovsdb_idl_next_row(row
)) {
1028 list_record(row
, columns
, n_columns
, out
);
1034 /* Finds and returns the "struct ovsdb_idl_table_class *" with 'table_name' by
1035 * searching the tables in these schema. */
1036 static const struct ovsdb_idl_table_class
*
1037 get_table(const char *table_name
)
1039 const struct ovsdb_idl_table_class
*best_match
= NULL
;
1040 unsigned int best_score
= 0;
1042 for (const struct ovsdb_idl_table_class
*table
= idl_classes
;
1043 table
< &idl_classes
[n_classes
]; table
++) {
1044 unsigned int score
= score_partial_match(table
->name
, table_name
);
1045 if (score
> best_score
) {
1048 } else if (score
== best_score
) {
1054 } else if (best_score
) {
1055 ctl_fatal("multiple table names match \"%s\"", table_name
);
1057 ctl_fatal("unknown table \"%s\"", table_name
);
1063 pre_cmd_find(struct ctl_context
*ctx
)
1065 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
1066 const char *table_name
= ctx
->argv
[1];
1067 const struct ovsdb_idl_table_class
*table
;
1070 table
= pre_get_table(ctx
, table_name
);
1071 pre_list_columns(ctx
, table
, column_names
);
1072 for (i
= 2; i
< ctx
->argc
; i
++) {
1073 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1078 cmd_find(struct ctl_context
*ctx
)
1080 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
1081 const struct ovsdb_idl_column
**columns
;
1082 const char *table_name
= ctx
->argv
[1];
1083 const struct ovsdb_idl_table_class
*table
;
1084 const struct ovsdb_idl_row
*row
;
1088 table
= get_table(table_name
);
1089 parse_column_names(column_names
, table
, &columns
, &n_columns
);
1090 out
= ctx
->table
= list_make_table(columns
, n_columns
);
1091 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
); row
;
1092 row
= ovsdb_idl_next_row(row
)) {
1095 for (i
= 2; i
< ctx
->argc
; i
++) {
1096 if (!is_condition_satisfied(table
, row
, ctx
->argv
[i
],
1101 list_record(row
, columns
, n_columns
, out
);
1108 /* Sets the column of 'row' in 'table'. */
1110 set_column(const struct ovsdb_idl_table_class
*table
,
1111 const struct ovsdb_idl_row
*row
, const char *arg
,
1112 struct ovsdb_symbol_table
*symtab
)
1114 const struct ovsdb_idl_column
*column
;
1115 char *key_string
, *value_string
;
1118 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
1119 NULL
, NULL
, 0, &value_string
);
1120 die_if_error(error
);
1121 if (!value_string
) {
1122 ctl_fatal("%s: missing value", arg
);
1124 check_mutable(row
, column
);
1127 union ovsdb_atom key
, value
;
1128 struct ovsdb_datum datum
;
1130 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
1131 ctl_fatal("cannot specify key to set for non-map column %s",
1135 die_if_error(ovsdb_atom_from_string(&key
, NULL
, &column
->type
.key
,
1136 key_string
, symtab
));
1137 die_if_error(ovsdb_atom_from_string(&value
, NULL
, &column
->type
.value
,
1138 value_string
, symtab
));
1140 ovsdb_datum_init_empty(&datum
);
1141 ovsdb_datum_add_unsafe(&datum
, &key
, &value
, &column
->type
, NULL
);
1143 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
1144 ovsdb_atom_destroy(&value
, column
->type
.value
.type
);
1146 ovsdb_datum_union(&datum
, ovsdb_idl_read(row
, column
),
1147 &column
->type
, false);
1148 ovsdb_idl_txn_verify(row
, column
);
1149 ovsdb_idl_txn_write(row
, column
, &datum
);
1151 struct ovsdb_datum datum
;
1153 die_if_error(ovsdb_datum_from_string(&datum
, &column
->type
,
1154 value_string
, symtab
));
1155 ovsdb_idl_txn_write(row
, column
, &datum
);
1163 pre_cmd_set(struct ctl_context
*ctx
)
1165 const char *table_name
= ctx
->argv
[1];
1166 const struct ovsdb_idl_table_class
*table
;
1169 table
= pre_get_table(ctx
, table_name
);
1170 for (i
= 3; i
< ctx
->argc
; i
++) {
1171 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1176 cmd_set(struct ctl_context
*ctx
)
1178 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1179 const char *table_name
= ctx
->argv
[1];
1180 const char *record_id
= ctx
->argv
[2];
1181 const struct ovsdb_idl_table_class
*table
;
1182 const struct ovsdb_idl_row
*row
;
1185 table
= get_table(table_name
);
1186 row
= get_row(ctx
, table
, record_id
, must_exist
);
1191 for (i
= 3; i
< ctx
->argc
; i
++) {
1192 set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
1195 invalidate_cache(ctx
);
1199 pre_cmd_add(struct ctl_context
*ctx
)
1201 const char *table_name
= ctx
->argv
[1];
1202 const char *column_name
= ctx
->argv
[3];
1203 const struct ovsdb_idl_table_class
*table
;
1204 const struct ovsdb_idl_column
*column
;
1206 table
= pre_get_table(ctx
, table_name
);
1207 pre_get_column(ctx
, table
, column_name
, &column
);
1211 cmd_add(struct ctl_context
*ctx
)
1213 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1214 const char *table_name
= ctx
->argv
[1];
1215 const char *record_id
= ctx
->argv
[2];
1216 const char *column_name
= ctx
->argv
[3];
1217 const struct ovsdb_idl_table_class
*table
;
1218 const struct ovsdb_idl_column
*column
;
1219 const struct ovsdb_idl_row
*row
;
1220 const struct ovsdb_type
*type
;
1221 struct ovsdb_datum old
;
1224 table
= get_table(table_name
);
1225 die_if_error(get_column(table
, column_name
, &column
));
1226 row
= get_row(ctx
, table
, record_id
, must_exist
);
1230 check_mutable(row
, column
);
1232 type
= &column
->type
;
1233 ovsdb_datum_clone(&old
, ovsdb_idl_read(row
, column
), &column
->type
);
1234 for (i
= 4; i
< ctx
->argc
; i
++) {
1235 struct ovsdb_type add_type
;
1236 struct ovsdb_datum add
;
1240 add_type
.n_max
= UINT_MAX
;
1241 die_if_error(ovsdb_datum_from_string(&add
, &add_type
, ctx
->argv
[i
],
1243 ovsdb_datum_union(&old
, &add
, type
, false);
1244 ovsdb_datum_destroy(&add
, type
);
1246 if (old
.n
> type
->n_max
) {
1247 ctl_fatal("\"add\" operation would put %u %s in column %s of "
1248 "table %s but the maximum number is %u",
1250 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
1251 column
->name
, table
->name
, type
->n_max
);
1253 ovsdb_idl_txn_verify(row
, column
);
1254 ovsdb_idl_txn_write(row
, column
, &old
);
1256 invalidate_cache(ctx
);
1260 pre_cmd_remove(struct ctl_context
*ctx
)
1262 const char *table_name
= ctx
->argv
[1];
1263 const char *column_name
= ctx
->argv
[3];
1264 const struct ovsdb_idl_table_class
*table
;
1265 const struct ovsdb_idl_column
*column
;
1267 table
= pre_get_table(ctx
, table_name
);
1268 pre_get_column(ctx
, table
, column_name
, &column
);
1272 cmd_remove(struct ctl_context
*ctx
)
1274 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1275 const char *table_name
= ctx
->argv
[1];
1276 const char *record_id
= ctx
->argv
[2];
1277 const char *column_name
= ctx
->argv
[3];
1278 const struct ovsdb_idl_table_class
*table
;
1279 const struct ovsdb_idl_column
*column
;
1280 const struct ovsdb_idl_row
*row
;
1281 const struct ovsdb_type
*type
;
1282 struct ovsdb_datum old
;
1285 table
= get_table(table_name
);
1286 die_if_error(get_column(table
, column_name
, &column
));
1287 row
= get_row(ctx
, table
, record_id
, must_exist
);
1291 check_mutable(row
, column
);
1293 type
= &column
->type
;
1294 ovsdb_datum_clone(&old
, ovsdb_idl_read(row
, column
), &column
->type
);
1295 for (i
= 4; i
< ctx
->argc
; i
++) {
1296 struct ovsdb_type rm_type
;
1297 struct ovsdb_datum rm
;
1302 rm_type
.n_max
= UINT_MAX
;
1303 error
= ovsdb_datum_from_string(&rm
, &rm_type
,
1304 ctx
->argv
[i
], ctx
->symtab
);
1307 if (ovsdb_type_is_map(&rm_type
)) {
1308 rm_type
.value
.type
= OVSDB_TYPE_VOID
;
1310 die_if_error(ovsdb_datum_from_string(
1311 &rm
, &rm_type
, ctx
->argv
[i
], ctx
->symtab
));
1313 ctl_fatal("%s", error
);
1316 ovsdb_datum_subtract(&old
, type
, &rm
, &rm_type
);
1317 ovsdb_datum_destroy(&rm
, &rm_type
);
1319 if (old
.n
< type
->n_min
) {
1320 ctl_fatal("\"remove\" operation would put %u %s in column %s of "
1321 "table %s but the minimum number is %u",
1323 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
1324 column
->name
, table
->name
, type
->n_min
);
1326 ovsdb_idl_txn_verify(row
, column
);
1327 ovsdb_idl_txn_write(row
, column
, &old
);
1329 invalidate_cache(ctx
);
1333 pre_cmd_clear(struct ctl_context
*ctx
)
1335 const char *table_name
= ctx
->argv
[1];
1336 const struct ovsdb_idl_table_class
*table
;
1339 table
= pre_get_table(ctx
, table_name
);
1340 for (i
= 3; i
< ctx
->argc
; i
++) {
1341 const struct ovsdb_idl_column
*column
;
1343 pre_get_column(ctx
, table
, ctx
->argv
[i
], &column
);
1348 cmd_clear(struct ctl_context
*ctx
)
1350 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1351 const char *table_name
= ctx
->argv
[1];
1352 const char *record_id
= ctx
->argv
[2];
1353 const struct ovsdb_idl_table_class
*table
;
1354 const struct ovsdb_idl_row
*row
;
1357 table
= get_table(table_name
);
1358 row
= get_row(ctx
, table
, record_id
, must_exist
);
1363 for (i
= 3; i
< ctx
->argc
; i
++) {
1364 const struct ovsdb_idl_column
*column
;
1365 const struct ovsdb_type
*type
;
1366 struct ovsdb_datum datum
;
1368 die_if_error(get_column(table
, ctx
->argv
[i
], &column
));
1369 check_mutable(row
, column
);
1371 type
= &column
->type
;
1372 if (type
->n_min
> 0) {
1373 ctl_fatal("\"clear\" operation cannot be applied to column %s "
1374 "of table %s, which is not allowed to be empty",
1375 column
->name
, table
->name
);
1378 ovsdb_datum_init_empty(&datum
);
1379 ovsdb_idl_txn_write(row
, column
, &datum
);
1382 invalidate_cache(ctx
);
1386 pre_create(struct ctl_context
*ctx
)
1388 const char *id
= shash_find_data(&ctx
->options
, "--id");
1389 const char *table_name
= ctx
->argv
[1];
1390 const struct ovsdb_idl_table_class
*table
;
1392 table
= get_table(table_name
);
1393 if (!id
&& !table
->is_root
) {
1394 VLOG_WARN("applying \"create\" command to table %s without --id "
1395 "option will have no effect", table
->name
);
1400 cmd_create(struct ctl_context
*ctx
)
1402 const char *id
= shash_find_data(&ctx
->options
, "--id");
1403 const char *table_name
= ctx
->argv
[1];
1404 const struct ovsdb_idl_table_class
*table
= get_table(table_name
);
1405 const struct ovsdb_idl_row
*row
;
1406 const struct uuid
*uuid
;
1410 struct ovsdb_symbol
*symbol
= create_symbol(ctx
->symtab
, id
, NULL
);
1411 if (table
->is_root
) {
1412 /* This table is in the root set, meaning that rows created in it
1413 * won't disappear even if they are unreferenced, so disable
1414 * warnings about that by pretending that there is a reference. */
1415 symbol
->strong_ref
= true;
1417 uuid
= &symbol
->uuid
;
1422 row
= ovsdb_idl_txn_insert(ctx
->txn
, table
, uuid
);
1423 for (i
= 2; i
< ctx
->argc
; i
++) {
1424 set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
1426 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
1429 /* This function may be used as the 'postprocess' function for commands that
1430 * insert new rows into the database. It expects that the command's 'run'
1431 * function prints the UUID reported by ovsdb_idl_txn_insert() as the command's
1432 * sole output. It replaces that output by the row's permanent UUID assigned
1433 * by the database server and appends a new-line.
1435 * Currently we use this only for "create", because the higher-level commands
1436 * are supposed to be independent of the actual structure of the vswitch
1439 post_create(struct ctl_context
*ctx
)
1441 const struct uuid
*real
;
1444 if (!uuid_from_string(&dummy
, ds_cstr(&ctx
->output
))) {
1447 real
= ovsdb_idl_txn_get_insert_uuid(ctx
->txn
, &dummy
);
1449 ds_clear(&ctx
->output
);
1450 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(real
));
1452 ds_put_char(&ctx
->output
, '\n');
1456 pre_cmd_destroy(struct ctl_context
*ctx
)
1458 const char *table_name
= ctx
->argv
[1];
1460 pre_get_table(ctx
, table_name
);
1464 cmd_destroy(struct ctl_context
*ctx
)
1466 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1467 bool delete_all
= shash_find(&ctx
->options
, "--all");
1468 const char *table_name
= ctx
->argv
[1];
1469 const struct ovsdb_idl_table_class
*table
;
1472 table
= get_table(table_name
);
1474 if (delete_all
&& ctx
->argc
> 2) {
1475 ctl_fatal("--all and records argument should not be specified together");
1478 if (delete_all
&& !must_exist
) {
1479 ctl_fatal("--all and --if-exists should not be specified together");
1483 const struct ovsdb_idl_row
*row
;
1484 const struct ovsdb_idl_row
*next_row
;
1486 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
);
1488 next_row
= ovsdb_idl_next_row(row
);
1489 ovsdb_idl_txn_delete(row
);
1493 for (i
= 2; i
< ctx
->argc
; i
++) {
1494 const struct ovsdb_idl_row
*row
;
1496 row
= get_row(ctx
, table
, ctx
->argv
[i
], must_exist
);
1498 ovsdb_idl_txn_delete(row
);
1502 invalidate_cache(ctx
);
1506 pre_cmd_wait_until(struct ctl_context
*ctx
)
1508 const char *table_name
= ctx
->argv
[1];
1509 const struct ovsdb_idl_table_class
*table
;
1512 table
= pre_get_table(ctx
, table_name
);
1514 for (i
= 3; i
< ctx
->argc
; i
++) {
1515 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
1520 cmd_wait_until(struct ctl_context
*ctx
)
1522 const char *table_name
= ctx
->argv
[1];
1523 const char *record_id
= ctx
->argv
[2];
1524 const struct ovsdb_idl_table_class
*table
;
1525 const struct ovsdb_idl_row
*row
;
1528 table
= get_table(table_name
);
1530 row
= get_row(ctx
, table
, record_id
, false);
1532 ctx
->try_again
= true;
1536 for (i
= 3; i
< ctx
->argc
; i
++) {
1537 if (!is_condition_satisfied(table
, row
, ctx
->argv
[i
], ctx
->symtab
)) {
1538 ctx
->try_again
= true;
1544 /* Parses one command. */
1546 parse_command(int argc
, char *argv
[], struct shash
*local_options
,
1547 struct ctl_command
*command
)
1549 const struct ctl_command_syntax
*p
;
1550 struct shash_node
*node
;
1554 shash_init(&command
->options
);
1555 shash_swap(local_options
, &command
->options
);
1556 for (i
= 0; i
< argc
; i
++) {
1557 const char *option
= argv
[i
];
1561 if (option
[0] != '-') {
1565 equals
= strchr(option
, '=');
1567 key
= xmemdup0(option
, equals
- option
);
1568 value
= xstrdup(equals
+ 1);
1570 key
= xstrdup(option
);
1574 if (shash_find(&command
->options
, key
)) {
1575 ctl_fatal("'%s' option specified multiple times", argv
[i
]);
1577 shash_add_nocopy(&command
->options
, key
, value
);
1580 ctl_fatal("missing command name (use --help for help)");
1583 p
= shash_find_data(&all_commands
, argv
[i
]);
1585 ctl_fatal("unknown command '%s'; use --help for help", argv
[i
]);
1588 SHASH_FOR_EACH (node
, &command
->options
) {
1589 const char *s
= strstr(p
->options
, node
->name
);
1590 int end
= s
? s
[strlen(node
->name
)] : EOF
;
1592 if (end
!= '=' && end
!= ',' && end
!= ' ' && end
!= '\0') {
1593 ctl_fatal("'%s' command has no '%s' option",
1594 argv
[i
], node
->name
);
1596 if ((end
== '=') != (node
->data
!= NULL
)) {
1598 ctl_fatal("missing argument to '%s' option on '%s' "
1599 "command", node
->name
, argv
[i
]);
1601 ctl_fatal("'%s' option on '%s' does not accept an "
1602 "argument", node
->name
, argv
[i
]);
1607 n_arg
= argc
- i
- 1;
1608 if (n_arg
< p
->min_args
) {
1609 ctl_fatal("'%s' command requires at least %d arguments",
1610 p
->name
, p
->min_args
);
1611 } else if (n_arg
> p
->max_args
) {
1614 for (j
= i
+ 1; j
< argc
; j
++) {
1615 if (argv
[j
][0] == '-') {
1616 ctl_fatal("'%s' command takes at most %d arguments "
1617 "(note that options must precede command "
1618 "names and follow a \"--\" argument)",
1619 p
->name
, p
->max_args
);
1623 ctl_fatal("'%s' command takes at most %d arguments",
1624 p
->name
, p
->max_args
);
1627 command
->syntax
= p
;
1628 command
->argc
= n_arg
+ 1;
1629 command
->argv
= &argv
[i
];
1633 pre_cmd_show(struct ctl_context
*ctx
)
1635 const struct cmd_show_table
*show
;
1637 for (show
= cmd_show_tables
; show
->table
; show
++) {
1640 ovsdb_idl_add_table(ctx
->idl
, show
->table
);
1641 if (show
->name_column
) {
1642 ovsdb_idl_add_column(ctx
->idl
, show
->name_column
);
1644 for (i
= 0; i
< ARRAY_SIZE(show
->columns
); i
++) {
1645 const struct ovsdb_idl_column
*column
= show
->columns
[i
];
1647 ovsdb_idl_add_column(ctx
->idl
, column
);
1650 if (show
->wref_table
.table
) {
1651 ovsdb_idl_add_table(ctx
->idl
, show
->wref_table
.table
);
1653 if (show
->wref_table
.name_column
) {
1654 ovsdb_idl_add_column(ctx
->idl
, show
->wref_table
.name_column
);
1656 if (show
->wref_table
.wref_column
) {
1657 ovsdb_idl_add_column(ctx
->idl
, show
->wref_table
.wref_column
);
1662 static const struct cmd_show_table
*
1663 cmd_show_find_table_by_row(const struct ovsdb_idl_row
*row
)
1665 const struct cmd_show_table
*show
;
1667 for (show
= cmd_show_tables
; show
->table
; show
++) {
1668 if (show
->table
== row
->table
->class) {
1675 static const struct cmd_show_table
*
1676 cmd_show_find_table_by_name(const char *name
)
1678 const struct cmd_show_table
*show
;
1680 for (show
= cmd_show_tables
; show
->table
; show
++) {
1681 if (!strcmp(show
->table
->name
, name
)) {
1688 /* Prints table entries that weak reference the 'cur_row'. */
1690 cmd_show_weak_ref(struct ctl_context
*ctx
, const struct cmd_show_table
*show
,
1691 const struct ovsdb_idl_row
*cur_row
, int level
)
1693 const struct ovsdb_idl_row
*row_wref
;
1694 const struct ovsdb_idl_table_class
*table
= show
->wref_table
.table
;
1695 const struct ovsdb_idl_column
*name_column
1696 = show
->wref_table
.name_column
;
1697 const struct ovsdb_idl_column
*wref_column
1698 = show
->wref_table
.wref_column
;
1700 if (!table
|| !name_column
|| !wref_column
) {
1704 for (row_wref
= ovsdb_idl_first_row(ctx
->idl
, table
); row_wref
;
1705 row_wref
= ovsdb_idl_next_row(row_wref
)) {
1706 const struct ovsdb_datum
*wref_datum
1707 = ovsdb_idl_read(row_wref
, wref_column
);
1708 /* If weak reference refers to the 'cur_row', prints it. */
1710 && uuid_equals(&cur_row
->uuid
, &wref_datum
->keys
[0].uuid
)) {
1711 const struct ovsdb_datum
*name_datum
1712 = ovsdb_idl_read(row_wref
, name_column
);
1713 ds_put_char_multiple(&ctx
->output
, ' ', (level
+ 1) * 4);
1714 ds_put_format(&ctx
->output
, "%s ", table
->name
);
1715 ovsdb_datum_to_string(name_datum
, &name_column
->type
, &ctx
->output
);
1716 ds_put_char(&ctx
->output
, '\n');
1721 /* 'shown' records the tables that has been displayed by the current
1722 * command to avoid duplicated prints.
1725 cmd_show_row(struct ctl_context
*ctx
, const struct ovsdb_idl_row
*row
,
1726 int level
, struct sset
*shown
)
1728 const struct cmd_show_table
*show
= cmd_show_find_table_by_row(row
);
1731 ds_put_char_multiple(&ctx
->output
, ' ', level
* 4);
1732 if (show
&& show
->name_column
) {
1733 const struct ovsdb_datum
*datum
;
1735 ds_put_format(&ctx
->output
, "%s ", show
->table
->name
);
1736 datum
= ovsdb_idl_read(row
, show
->name_column
);
1737 ovsdb_datum_to_string(datum
, &show
->name_column
->type
, &ctx
->output
);
1739 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
1741 ds_put_char(&ctx
->output
, '\n');
1743 if (!show
|| sset_find(shown
, show
->table
->name
)) {
1747 sset_add(shown
, show
->table
->name
);
1748 for (i
= 0; i
< ARRAY_SIZE(show
->columns
); i
++) {
1749 const struct ovsdb_idl_column
*column
= show
->columns
[i
];
1750 const struct ovsdb_datum
*datum
;
1756 datum
= ovsdb_idl_read(row
, column
);
1757 if (column
->type
.key
.type
== OVSDB_TYPE_UUID
&&
1758 column
->type
.key
.u
.uuid
.refTableName
) {
1759 const struct cmd_show_table
*ref_show
;
1762 ref_show
= cmd_show_find_table_by_name(
1763 column
->type
.key
.u
.uuid
.refTableName
);
1765 for (j
= 0; j
< datum
->n
; j
++) {
1766 const struct ovsdb_idl_row
*ref_row
;
1768 ref_row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
,
1770 &datum
->keys
[j
].uuid
);
1772 cmd_show_row(ctx
, ref_row
, level
+ 1, shown
);
1777 } else if (ovsdb_type_is_map(&column
->type
) &&
1778 column
->type
.value
.type
== OVSDB_TYPE_UUID
&&
1779 column
->type
.value
.u
.uuid
.refTableName
) {
1780 const struct cmd_show_table
*ref_show
;
1783 /* Prints the key to ref'ed table name map if the ref'ed table
1784 * is also defined in 'cmd_show_tables'. */
1785 ref_show
= cmd_show_find_table_by_name(
1786 column
->type
.value
.u
.uuid
.refTableName
);
1787 if (ref_show
&& ref_show
->name_column
) {
1788 ds_put_char_multiple(&ctx
->output
, ' ', (level
+ 1) * 4);
1789 ds_put_format(&ctx
->output
, "%s:\n", column
->name
);
1790 for (j
= 0; j
< datum
->n
; j
++) {
1791 const struct ovsdb_idl_row
*ref_row
;
1793 ref_row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
,
1795 &datum
->values
[j
].uuid
);
1797 ds_put_char_multiple(&ctx
->output
, ' ', (level
+ 2) * 4);
1798 ovsdb_atom_to_string(&datum
->keys
[j
], column
->type
.key
.type
,
1800 ds_put_char(&ctx
->output
, '=');
1802 const struct ovsdb_datum
*ref_datum
;
1804 ref_datum
= ovsdb_idl_read(ref_row
,
1805 ref_show
->name_column
);
1806 ovsdb_datum_to_string(ref_datum
,
1807 &ref_show
->name_column
->type
,
1810 ds_put_cstr(&ctx
->output
, "\"<null>\"");
1812 ds_put_char(&ctx
->output
, '\n');
1818 if (!ovsdb_datum_is_default(datum
, &column
->type
)) {
1819 ds_put_char_multiple(&ctx
->output
, ' ', (level
+ 1) * 4);
1820 ds_put_format(&ctx
->output
, "%s: ", column
->name
);
1821 ovsdb_datum_to_string(datum
, &column
->type
, &ctx
->output
);
1822 ds_put_char(&ctx
->output
, '\n');
1825 cmd_show_weak_ref(ctx
, show
, row
, level
);
1826 sset_find_and_delete_assert(shown
, show
->table
->name
);
1830 cmd_show(struct ctl_context
*ctx
)
1832 const struct ovsdb_idl_row
*row
;
1833 struct sset shown
= SSET_INITIALIZER(&shown
);
1835 for (row
= ovsdb_idl_first_row(ctx
->idl
, cmd_show_tables
[0].table
);
1836 row
; row
= ovsdb_idl_next_row(row
)) {
1837 cmd_show_row(ctx
, row
, 0, &shown
);
1840 ovs_assert(sset_is_empty(&shown
));
1841 sset_destroy(&shown
);
1845 /* Given pointer to dynamic array 'options_p', array's current size
1846 * 'allocated_options_p' and number of added options 'n_options_p',
1847 * adds all command options to the array. Enlarges the array if
1850 ctl_add_cmd_options(struct option
**options_p
, size_t *n_options_p
,
1851 size_t *allocated_options_p
, int opt_val
)
1854 const struct shash_node
*node
;
1855 size_t n_existing_options
= *n_options_p
;
1857 SHASH_FOR_EACH (node
, &all_commands
) {
1858 const struct ctl_command_syntax
*p
= node
->data
;
1860 if (p
->options
[0]) {
1861 char *save_ptr
= NULL
;
1865 s
= xstrdup(p
->options
);
1866 for (name
= strtok_r(s
, ",", &save_ptr
); name
!= NULL
;
1867 name
= strtok_r(NULL
, ",", &save_ptr
)) {
1871 ovs_assert(name
[0] == '-' && name
[1] == '-' && name
[2]);
1874 equals
= strchr(name
, '=');
1876 has_arg
= required_argument
;
1879 has_arg
= no_argument
;
1882 o
= find_option(name
, *options_p
, *n_options_p
);
1884 ovs_assert(o
- *options_p
>= n_existing_options
);
1885 ovs_assert(o
->has_arg
== has_arg
);
1887 o
= add_option(options_p
, n_options_p
, allocated_options_p
);
1888 o
->name
= xstrdup(name
);
1889 o
->has_arg
= has_arg
;
1898 o
= add_option(options_p
, n_options_p
, allocated_options_p
);
1899 memset(o
, 0, sizeof *o
);
1902 /* Parses command-line input for commands. */
1903 struct ctl_command
*
1904 ctl_parse_commands(int argc
, char *argv
[], struct shash
*local_options
,
1905 size_t *n_commandsp
)
1907 struct ctl_command
*commands
;
1908 size_t n_commands
, allocated_commands
;
1912 n_commands
= allocated_commands
= 0;
1914 for (start
= i
= 0; i
<= argc
; i
++) {
1915 if (i
== argc
|| !strcmp(argv
[i
], "--")) {
1917 if (n_commands
>= allocated_commands
) {
1918 struct ctl_command
*c
;
1920 commands
= x2nrealloc(commands
, &allocated_commands
,
1922 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
1923 shash_moved(&c
->options
);
1926 parse_command(i
- start
, &argv
[start
], local_options
,
1927 &commands
[n_commands
++]);
1928 } else if (!shash_is_empty(local_options
)) {
1929 ctl_fatal("missing command name (use --help for help)");
1935 ctl_fatal("missing command name (use --help for help)");
1937 *n_commandsp
= n_commands
;
1941 /* Prints all registered commands. */
1943 ctl_print_commands(void)
1945 const struct shash_node
*node
;
1947 SHASH_FOR_EACH (node
, &all_commands
) {
1948 const struct ctl_command_syntax
*p
= node
->data
;
1949 char *options
= xstrdup(p
->options
);
1950 char *options_begin
= options
;
1953 for (item
= strsep(&options
, ","); item
!= NULL
;
1954 item
= strsep(&options
, ",")) {
1955 if (item
[0] != '\0') {
1956 printf("[%s] ", item
);
1959 printf(",%s,", p
->name
);
1960 print_command_arguments(p
);
1963 free(options_begin
);
1969 /* Given array of options 'options', prints them. */
1971 ctl_print_options(const struct option
*options
)
1973 for (; options
->name
; options
++) {
1974 const struct option
*o
= options
;
1976 printf("--%s%s\n", o
->name
, o
->has_arg
? "=ARG" : "");
1977 if (o
->flag
== NULL
&& o
->val
> 0 && o
->val
<= UCHAR_MAX
) {
1978 printf("-%c%s\n", o
->val
, o
->has_arg
? " ARG" : "");
1985 /* Returns the default local database path. */
1987 ctl_default_db(void)
1991 def
= xasprintf("unix:%s/db.sock", ovs_rundir());
1996 /* Returns true if it looks like this set of arguments might modify the
1997 * database, otherwise false. (Not very smart, so it's prone to false
2000 ctl_might_write_to_db(char **argv
)
2002 for (; *argv
; argv
++) {
2003 const struct ctl_command_syntax
*p
= shash_find_data(&all_commands
,
2005 if (p
&& p
->mode
== RW
) {
2013 ctl_fatal(const char *format
, ...)
2018 va_start(args
, format
);
2019 message
= xvasprintf(format
, args
);
2022 vlog_set_levels(&this_module
, VLF_CONSOLE
, VLL_OFF
);
2023 VLOG_ERR("%s", message
);
2024 ovs_error(0, "%s", message
);
2025 ctl_exit(EXIT_FAILURE
);
2028 /* Frees the current transaction and the underlying IDL and then calls
2031 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2032 * for a clean memory leak report from valgrind in the normal case. That makes
2033 * it easier to notice real memory leaks. */
2035 ctl_exit(int status
)
2037 if (ctl_exit_func
) {
2038 ctl_exit_func(status
);
2043 /* Comman database commands to be registered. */
2044 static const struct ctl_command_syntax db_ctl_commands
[] = {
2045 {"comment", 0, INT_MAX
, "[ARG]...", NULL
, NULL
, NULL
, "", RO
},
2046 {"get", 2, INT_MAX
, "TABLE RECORD [COLUMN[:KEY]]...",pre_cmd_get
, cmd_get
,
2047 NULL
, "--if-exists,--id=", RO
},
2048 {"list", 1, INT_MAX
, "TABLE [RECORD]...", pre_cmd_list
, cmd_list
, NULL
,
2049 "--if-exists,--columns=", RO
},
2050 {"find", 1, INT_MAX
, "TABLE [COLUMN[:KEY]=VALUE]...", pre_cmd_find
,
2051 cmd_find
, NULL
, "--columns=", RO
},
2052 {"set", 3, INT_MAX
, "TABLE RECORD COLUMN[:KEY]=VALUE...", pre_cmd_set
,
2053 cmd_set
, NULL
, "--if-exists", RW
},
2054 {"add", 4, INT_MAX
, "TABLE RECORD COLUMN [KEY=]VALUE...", pre_cmd_add
,
2055 cmd_add
, NULL
, "--if-exists", RW
},
2056 {"remove", 4, INT_MAX
, "TABLE RECORD COLUMN KEY|VALUE|KEY=VALUE...",
2057 pre_cmd_remove
, cmd_remove
, NULL
, "--if-exists", RW
},
2058 {"clear", 3, INT_MAX
, "TABLE RECORD COLUMN...", pre_cmd_clear
, cmd_clear
,
2059 NULL
, "--if-exists", RW
},
2060 {"create", 2, INT_MAX
, "TABLE COLUMN[:KEY]=VALUE...", pre_create
,
2061 cmd_create
, post_create
, "--id=", RW
},
2062 {"destroy", 1, INT_MAX
, "TABLE [RECORD]...", pre_cmd_destroy
, cmd_destroy
,
2063 NULL
, "--if-exists,--all", RW
},
2064 {"wait-until", 2, INT_MAX
, "TABLE RECORD [COLUMN[:KEY]=VALUE]...",
2065 pre_cmd_wait_until
, cmd_wait_until
, NULL
, "", RO
},
2066 {NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, RO
},
2070 ctl_register_command(const struct ctl_command_syntax
*command
)
2072 shash_add_assert(&all_commands
, command
->name
, command
);
2075 /* Registers commands represented by 'struct ctl_command_syntax's to
2076 * 'all_commands'. The last element of 'commands' must be an all-NULL
2079 ctl_register_commands(const struct ctl_command_syntax
*commands
)
2081 const struct ctl_command_syntax
*p
;
2083 for (p
= commands
; p
->name
; p
++) {
2084 ctl_register_command(p
);
2088 /* Registers the 'db_ctl_commands' to 'all_commands'. */
2090 ctl_init__(const struct ovsdb_idl_table_class
*idl_classes_
,
2091 const struct ctl_table_class
*ctl_classes_
,
2093 const struct cmd_show_table cmd_show_tables_
[],
2094 void (*ctl_exit_func_
)(int status
))
2096 idl_classes
= idl_classes_
;
2097 ctl_classes
= ctl_classes_
;
2098 n_classes
= n_classes_
;
2099 ctl_exit_func
= ctl_exit_func_
;
2100 ctl_register_commands(db_ctl_commands
);
2102 cmd_show_tables
= cmd_show_tables_
;
2103 if (cmd_show_tables
) {
2104 static const struct ctl_command_syntax show
=
2105 {"show", 0, 0, "", pre_cmd_show
, cmd_show
, NULL
, "", RO
};
2106 ctl_register_command(&show
);
2110 /* Returns the text for the database commands usage. */
2112 ctl_get_db_cmd_usage(void)
2114 return "Database commands:\n\
2115 list TBL [REC] list RECord (or all records) in TBL\n\
2116 find TBL CONDITION... list records satisfying CONDITION in TBL\n\
2117 get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\
2118 set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
2119 add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
2120 remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn\n\
2121 clear TBL REC COL clear values from COLumn in RECord in TBL\n\
2122 create TBL COL[:KEY]=VALUE create and initialize new record\n\
2123 destroy TBL REC delete RECord from TBL\n\
2124 wait-until TBL REC [COL[:KEY]=VALUE] wait until condition is true\n\
2125 Potentially unsafe database commands require --force option.\n";
2128 /* Initializes 'ctx' from 'command'. */
2130 ctl_context_init_command(struct ctl_context
*ctx
,
2131 struct ctl_command
*command
)
2133 ctx
->argc
= command
->argc
;
2134 ctx
->argv
= command
->argv
;
2135 ctx
->options
= command
->options
;
2137 ds_swap(&ctx
->output
, &command
->output
);
2138 ctx
->table
= command
->table
;
2139 ctx
->try_again
= false;
2142 /* Initializes the entire 'ctx'. */
2144 ctl_context_init(struct ctl_context
*ctx
, struct ctl_command
*command
,
2145 struct ovsdb_idl
*idl
, struct ovsdb_idl_txn
*txn
,
2146 struct ovsdb_symbol_table
*symtab
,
2147 void (*invalidate_cache
)(struct ctl_context
*))
2150 ctl_context_init_command(ctx
, command
);
2154 ctx
->symtab
= symtab
;
2155 ctx
->invalidate_cache
= invalidate_cache
;
2158 /* Completes processing of 'command' within 'ctx'. */
2160 ctl_context_done_command(struct ctl_context
*ctx
,
2161 struct ctl_command
*command
)
2163 ds_swap(&ctx
->output
, &command
->output
);
2164 command
->table
= ctx
->table
;
2167 /* Finishes up with 'ctx'.
2169 * If command is nonnull, first calls ctl_context_done_command() to complete
2170 * processing that command within 'ctx'. */
2172 ctl_context_done(struct ctl_context
*ctx
,
2173 struct ctl_command
*command
)
2176 ctl_context_done_command(ctx
, command
);
2178 invalidate_cache(ctx
);
2181 void ctl_set_column(const char *table_name
,
2182 const struct ovsdb_idl_row
*row
, const char *arg
,
2183 struct ovsdb_symbol_table
*symtab
)
2185 set_column(get_table(table_name
), row
, arg
, symtab
);