]> git.proxmox.com Git - mirror_ovs.git/blob - lib/db-ctl-base.c
db-ctl-base: Don't die in pre_get_column() on error.
[mirror_ovs.git] / lib / db-ctl-base.c
1 /*
2 * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18
19 #include <ctype.h>
20 #include <getopt.h>
21 #include <unistd.h>
22
23 #include "db-ctl-base.h"
24
25 #include "command-line.h"
26 #include "compiler.h"
27 #include "dirs.h"
28 #include "openvswitch/dynamic-string.h"
29 #include "fatal-signal.h"
30 #include "hash.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"
37 #include "sset.h"
38 #include "svec.h"
39 #include "string.h"
40 #include "table.h"
41 #include "util.h"
42
43 VLOG_DEFINE_THIS_MODULE(db_ctl_base);
44
45 /* This array defines the 'show' command output format. User can check the
46 * definition in utilities/ovs-vsctl.c as reference.
47 *
48 * Particularly, if an element in 'columns[]' represents a reference to
49 * another table, the referred table must also be defined as an entry in
50 * in 'cmd_show_tables[]'.
51 *
52 * The definition must end with an all-NULL entry. It is initalized once
53 * when ctl_init() is called.
54 *
55 * */
56 static const struct cmd_show_table *cmd_show_tables;
57
58 /* ctl_exit() is called by ctl_fatal(). User can optionally supply an exit
59 * function ctl_exit_func() via ctl_init. If supplied, this function will
60 * be called by ctl_exit()
61 */
62 static void (*ctl_exit_func)(int status) = NULL;
63 OVS_NO_RETURN static void ctl_exit(int status);
64
65 /* IDL class. */
66 static const struct ovsdb_idl_class *idl_class;
67
68 /* Two arrays with 'n_classes' elements, which represent the tables in this
69 * database and how the user can refer to their rows. */
70 static const struct ctl_table_class *ctl_classes;
71 static const struct ovsdb_idl_table_class *idl_classes;
72 static size_t n_classes;
73
74 static struct shash all_commands = SHASH_INITIALIZER(&all_commands);
75 static char *get_table(const char *, const struct ovsdb_idl_table_class **);
76 static char *set_column(const struct ovsdb_idl_table_class *,
77 const struct ovsdb_idl_row *, const char *,
78 struct ovsdb_symbol_table *);
79
80 \f
81 static struct option *
82 find_option(const char *name, struct option *options, size_t n_options)
83 {
84 size_t i;
85
86 for (i = 0; i < n_options; i++) {
87 if (!strcmp(options[i].name, name)) {
88 return &options[i];
89 }
90 }
91 return NULL;
92 }
93
94 static struct option *
95 add_option(struct option **optionsp, size_t *n_optionsp,
96 size_t *allocated_optionsp)
97 {
98 if (*n_optionsp >= *allocated_optionsp) {
99 *optionsp = x2nrealloc(*optionsp, allocated_optionsp,
100 sizeof **optionsp);
101 }
102 return &(*optionsp)[(*n_optionsp)++];
103 }
104
105 /* Converts the command arguments into format that can be parsed by
106 * bash completion script.
107 *
108 * Therein, arguments will be attached with following prefixes:
109 *
110 * !argument :: The argument is required
111 * ?argument :: The argument is optional
112 * *argument :: The argument may appear any number (0 or more) times
113 * +argument :: The argument may appear one or more times
114 *
115 */
116 static void
117 print_command_arguments(const struct ctl_command_syntax *command)
118 {
119 /*
120 * The argument string is parsed in reverse. We use a stack 'oew_stack' to
121 * keep track of nested optionals. Whenever a ']' is encountered, we push
122 * a bit to 'oew_stack'. The bit is set to 1 if the ']' is not nested.
123 * Subsequently, we pop an entry everytime '[' is met.
124 *
125 * We use 'whole_word_is_optional' value to decide whether or not a ! or +
126 * should be added on encountering a space: if the optional surrounds the
127 * whole word then it shouldn't be, but if it is only a part of the word
128 * (i.e. [key=]value), it should be.
129 */
130 uint32_t oew_stack = 0;
131
132 const char *arguments = command->arguments;
133 int length = strlen(arguments);
134 if (!length) {
135 return;
136 }
137
138 /* Output buffer, written backward from end. */
139 char *output = xmalloc(2 * length);
140 char *outp = output + 2 * length;
141 *--outp = '\0';
142
143 bool in_repeated = false;
144 bool whole_word_is_optional = false;
145
146 for (const char *inp = arguments + length; inp > arguments; ) {
147 switch (*--inp) {
148 case ']':
149 oew_stack <<= 1;
150 if (inp[1] == '\0' || inp[1] == ' ' || inp[1] == '.') {
151 oew_stack |= 1;
152 }
153 break;
154 case '[':
155 /* Checks if the whole word is optional, and sets the
156 * 'whole_word_is_optional' accordingly. */
157 if ((inp == arguments || inp[-1] == ' ') && oew_stack & 1) {
158 *--outp = in_repeated ? '*' : '?';
159 whole_word_is_optional = true;
160 } else {
161 *--outp = '?';
162 whole_word_is_optional = false;
163 }
164 oew_stack >>= 1;
165 break;
166 case ' ':
167 if (!whole_word_is_optional) {
168 *--outp = in_repeated ? '+' : '!';
169 }
170 *--outp = ' ';
171 in_repeated = false;
172 whole_word_is_optional = false;
173 break;
174 case '.':
175 in_repeated = true;
176 break;
177 default:
178 *--outp = *inp;
179 break;
180 }
181 }
182 if (arguments[0] != '[' && outp != output + 2 * length - 1) {
183 *--outp = in_repeated ? '+' : '!';
184 }
185 printf("%s", outp);
186 free(output);
187 }
188
189 static void
190 die_if_error(char *error)
191 {
192 if (error) {
193 ctl_fatal("%s", error);
194 }
195 }
196
197 static int
198 to_lower_and_underscores(unsigned c)
199 {
200 return c == '-' ? '_' : tolower(c);
201 }
202
203 /* Returns a score representing how well 's' matches 'name'. Higher return
204 * values indicate a better match. The order of the arguments is important:
205 * 'name' is the name of an entity such as a table or a column, and 's' is user
206 * input. */
207 static unsigned int
208 score_partial_match(const char *name, const char *s)
209 {
210 int score;
211
212 if (!strcmp(name, s)) {
213 return UINT_MAX;
214 }
215 for (score = 0; ; score++, name++, s++) {
216 if (to_lower_and_underscores(*name) != to_lower_and_underscores(*s)) {
217 break;
218 } else if (*name == '\0') {
219 return UINT_MAX - 1;
220 }
221 }
222 return *s == '\0' ? score : 0;
223 }
224
225 /* Returns NULL and sets 'symbolp' and 'newp' if symbol was created
226 * successfully. Otherwise returns a malloc()'ed error message on failure. */
227 static char * OVS_WARN_UNUSED_RESULT
228 create_symbol(struct ovsdb_symbol_table *symtab, const char *id,
229 struct ovsdb_symbol **symbolp, bool *newp)
230 {
231 struct ovsdb_symbol *symbol;
232
233 ovs_assert(symbolp);
234
235 if (id[0] != '@') {
236 return xasprintf("row id \"%s\" does not begin with \"@\"", id);
237 }
238
239 if (newp) {
240 *newp = ovsdb_symbol_table_get(symtab, id) == NULL;
241 }
242
243 symbol = ovsdb_symbol_table_insert(symtab, id);
244 if (symbol->created) {
245 return xasprintf("row id \"%s\" may only be specified on one --id "
246 "option", id);
247 }
248 symbol->created = true;
249 *symbolp = symbol;
250 return NULL;
251 }
252
253 static bool
254 record_id_equals(const union ovsdb_atom *name, enum ovsdb_atomic_type type,
255 const char *record_id)
256 {
257 if (type == OVSDB_TYPE_STRING) {
258 if (!strcmp(name->string, record_id)) {
259 return true;
260 }
261
262 struct uuid uuid;
263 size_t len = strlen(record_id);
264 if (len >= 4
265 && uuid_from_string(&uuid, name->string)
266 && !strncmp(name->string, record_id, len)) {
267 return true;
268 }
269
270 return false;
271 } else {
272 ovs_assert(type == OVSDB_TYPE_INTEGER);
273 return name->integer == strtoll(record_id, NULL, 10);
274 }
275 }
276
277 static const struct ovsdb_idl_row *
278 get_row_by_id(struct ctl_context *ctx,
279 const struct ovsdb_idl_table_class *table,
280 const struct ctl_row_id *id, const char *record_id,
281 bool *multiple_matches)
282 {
283 ovs_assert(multiple_matches);
284 *multiple_matches = false;
285
286 if (!id->name_column) {
287 return NULL;
288 }
289
290 const struct ovsdb_idl_row *referrer = NULL;
291
292 /* Figure out the 'key' and 'value' types for the column that we're going
293 * to look at. One of these ('name_type') is the type of the name we're
294 * going to compare against 'record_id'. */
295 enum ovsdb_atomic_type key, value, name_type;
296 if (!id->key) {
297 name_type = key = id->name_column->type.key.type;
298 value = OVSDB_TYPE_VOID;
299 } else {
300 key = OVSDB_TYPE_STRING;
301 name_type = value = id->name_column->type.value.type;
302 }
303
304 /* We only support integer and string names (so far). */
305 if (name_type == OVSDB_TYPE_INTEGER) {
306 if (!record_id[0] || record_id[strspn(record_id, "0123456789")]) {
307 return NULL;
308 }
309 } else {
310 ovs_assert(name_type == OVSDB_TYPE_STRING);
311 }
312
313 const struct ovsdb_idl_class *class = ovsdb_idl_get_class(ctx->idl);
314 const struct ovsdb_idl_table_class *id_table
315 = ovsdb_idl_table_class_from_column(class, id->name_column);
316 for (const struct ovsdb_idl_row *row = ovsdb_idl_first_row(ctx->idl,
317 id_table);
318 row != NULL;
319 row = ovsdb_idl_next_row(row)) {
320 /* Pick out the name column's data. */
321 const struct ovsdb_datum *datum = ovsdb_idl_get(
322 row, id->name_column, key, value);
323
324 /* Extract the name from the column. */
325 const union ovsdb_atom *name;
326 if (!id->key) {
327 name = datum->n == 1 ? &datum->keys[0] : NULL;
328 } else {
329 const union ovsdb_atom key_atom
330 = { .string = CONST_CAST(char *, id->key) };
331 unsigned int i = ovsdb_datum_find_key(datum, &key_atom,
332 OVSDB_TYPE_STRING);
333 name = i == UINT_MAX ? NULL : &datum->values[i];
334 }
335 if (!name) {
336 continue;
337 }
338
339 /* If the name equals 'record_id', take it. */
340 if (record_id_equals(name, name_type, record_id)) {
341 if (referrer) {
342 *multiple_matches = true;
343 return NULL;
344 }
345 referrer = row;
346 }
347 }
348 if (!referrer) {
349 return NULL;
350 }
351
352 const struct ovsdb_idl_row *final = referrer;
353 if (id->uuid_column) {
354 const struct ovsdb_datum *uuid;
355
356 ovsdb_idl_txn_verify(referrer, id->uuid_column);
357 uuid = ovsdb_idl_get(referrer, id->uuid_column,
358 OVSDB_TYPE_UUID, OVSDB_TYPE_VOID);
359 if (uuid->n == 1) {
360 final = ovsdb_idl_get_row_for_uuid(ctx->idl, table,
361 &uuid->keys[0].uuid);
362 } else {
363 final = NULL;
364 }
365 }
366 return final;
367 }
368
369 char * OVS_WARN_UNUSED_RESULT
370 ctl_get_row(struct ctl_context *ctx,
371 const struct ovsdb_idl_table_class *table, const char *record_id,
372 bool must_exist, const struct ovsdb_idl_row **rowp)
373 {
374 const struct ovsdb_idl_row *row = NULL;
375 struct uuid uuid;
376
377 ovs_assert(rowp);
378
379 if (uuid_from_string(&uuid, record_id)) {
380 row = ovsdb_idl_get_row_for_uuid(ctx->idl, table, &uuid);
381 }
382 if (!row) {
383 if (!strcmp(record_id, ".")) {
384 row = ovsdb_idl_first_row(ctx->idl, table);
385 if (row && ovsdb_idl_next_row(row)) {
386 row = NULL;
387 }
388 }
389 }
390 if (!row) {
391 const struct ctl_table_class *ctl_class
392 = &ctl_classes[table - idl_classes];
393 for (int i = 0; i < ARRAY_SIZE(ctl_class->row_ids); i++) {
394 const struct ctl_row_id *id = &ctl_class->row_ids[i];
395 bool multiple_matches;
396
397 row = get_row_by_id(ctx, table, id, record_id, &multiple_matches);
398 if (multiple_matches) {
399 const struct ovsdb_idl_class *class =
400 ovsdb_idl_get_class(ctx->idl);
401 const struct ovsdb_idl_table_class *table_class =
402 ovsdb_idl_table_class_from_column(class, id->name_column);
403 return xasprintf("multiple rows in %s match \"%s\"",
404 table_class->name, record_id);
405 }
406 if (row) {
407 break;
408 }
409 }
410 }
411 if (!row && uuid_is_partial_string(record_id) >= 4) {
412 for (const struct ovsdb_idl_row *r = ovsdb_idl_first_row(ctx->idl,
413 table);
414 r != NULL;
415 r = ovsdb_idl_next_row(r)) {
416 if (uuid_is_partial_match(&r->uuid, record_id)) {
417 if (!row) {
418 row = r;
419 } else {
420 return xasprintf("%s contains 2 or more rows whose UUIDs "
421 "begin with %s: at least "UUID_FMT" "
422 "and "UUID_FMT, table->name, record_id,
423 UUID_ARGS(&row->uuid),
424 UUID_ARGS(&r->uuid));
425 }
426 }
427 }
428 }
429 if (must_exist && !row) {
430 return xasprintf("no row \"%s\" in table %s", record_id, table->name);
431 }
432
433 *rowp = row;
434 return NULL;
435 }
436
437 static char *
438 get_column(const struct ovsdb_idl_table_class *table, const char *column_name,
439 const struct ovsdb_idl_column **columnp)
440 {
441 const struct ovsdb_idl_column *best_match = NULL;
442 unsigned int best_score = 0;
443 size_t i;
444
445 for (i = 0; i < table->n_columns; i++) {
446 const struct ovsdb_idl_column *column = &table->columns[i];
447 unsigned int score = score_partial_match(column->name, column_name);
448 if (score > best_score) {
449 best_match = column;
450 best_score = score;
451 } else if (score == best_score) {
452 best_match = NULL;
453 }
454 }
455
456 *columnp = best_match;
457 if (best_match) {
458 return NULL;
459 } else if (best_score) {
460 return xasprintf("%s contains more than one column whose name "
461 "matches \"%s\"", table->name, column_name);
462 } else {
463 return xasprintf("%s does not contain a column whose name matches "
464 "\"%s\"", table->name, column_name);
465 }
466 }
467
468 static char * OVS_WARN_UNUSED_RESULT
469 pre_get_column(struct ctl_context *ctx,
470 const struct ovsdb_idl_table_class *table,
471 const char *column_name,
472 const struct ovsdb_idl_column **columnp)
473 {
474 char *error = get_column(table, column_name, columnp);
475 if (error) {
476 return error;
477 }
478 ovsdb_idl_add_column(ctx->idl, *columnp);
479 return NULL;
480 }
481
482 static const struct ovsdb_idl_table_class *
483 pre_get_table(struct ctl_context *ctx, const char *table_name)
484 {
485 const struct ovsdb_idl_table_class *table;
486 die_if_error(get_table(table_name, &table));
487 ovsdb_idl_add_table(ctx->idl, table);
488
489 const struct ctl_table_class *ctl = &ctl_classes[table - idl_classes];
490 for (int i = 0; i < ARRAY_SIZE(ctl->row_ids); i++) {
491 const struct ctl_row_id *id = &ctl->row_ids[i];
492 if (id->name_column) {
493 ovsdb_idl_add_column(ctx->idl, id->name_column);
494 }
495 if (id->uuid_column) {
496 ovsdb_idl_add_column(ctx->idl, id->uuid_column);
497 }
498 }
499
500 return table;
501 }
502
503 static char *
504 missing_operator_error(const char *arg, const char **allowed_operators,
505 size_t n_allowed)
506 {
507 struct ds s;
508
509 ds_init(&s);
510 ds_put_format(&s, "%s: argument does not end in ", arg);
511 ds_put_format(&s, "\"%s\"", allowed_operators[0]);
512 if (n_allowed == 2) {
513 ds_put_format(&s, " or \"%s\"", allowed_operators[1]);
514 } else if (n_allowed > 2) {
515 size_t i;
516
517 for (i = 1; i < n_allowed - 1; i++) {
518 ds_put_format(&s, ", \"%s\"", allowed_operators[i]);
519 }
520 ds_put_format(&s, ", or \"%s\"", allowed_operators[i]);
521 }
522 ds_put_format(&s, " followed by a value.");
523
524 return ds_steal_cstr(&s);
525 }
526
527 /* Breaks 'arg' apart into a number of fields in the following order:
528 *
529 * - The name of a column in 'table', stored into '*columnp'. The column
530 * name may be abbreviated.
531 *
532 * - Optionally ':' followed by a key string. The key is stored as a
533 * malloc()'d string into '*keyp', or NULL if no key is present in
534 * 'arg'.
535 *
536 * - If 'valuep' is nonnull, an operator followed by a value string. The
537 * allowed operators are the 'n_allowed' string in 'allowed_operators',
538 * or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
539 * index of the operator within 'allowed_operators' is stored into
540 * '*operatorp'. The value is stored as a malloc()'d string into
541 * '*valuep', or NULL if no value is present in 'arg'.
542 *
543 * On success, returns NULL. On failure, returned a malloc()'d string error
544 * message and stores NULL into all of the nonnull output arguments. */
545 static char * OVS_WARN_UNUSED_RESULT
546 parse_column_key_value(const char *arg,
547 const struct ovsdb_idl_table_class *table,
548 const struct ovsdb_idl_column **columnp, char **keyp,
549 int *operatorp,
550 const char **allowed_operators, size_t n_allowed,
551 char **valuep)
552 {
553 const char *p = arg;
554 char *column_name;
555 char *error;
556
557 ovs_assert(!(operatorp && !valuep));
558 *keyp = NULL;
559 if (valuep) {
560 *valuep = NULL;
561 }
562
563 /* Parse column name. */
564 error = ovsdb_token_parse(&p, &column_name);
565 if (error) {
566 goto error;
567 }
568 if (column_name[0] == '\0') {
569 free(column_name);
570 error = xasprintf("%s: missing column name", arg);
571 goto error;
572 }
573 error = get_column(table, column_name, columnp);
574 free(column_name);
575 if (error) {
576 goto error;
577 }
578
579 /* Parse key string. */
580 if (*p == ':') {
581 p++;
582 error = ovsdb_token_parse(&p, keyp);
583 if (error) {
584 goto error;
585 }
586 }
587
588 /* Parse value string. */
589 if (valuep) {
590 size_t best_len;
591 size_t i;
592 int best;
593
594 if (!allowed_operators) {
595 static const char *equals = "=";
596 allowed_operators = &equals;
597 n_allowed = 1;
598 }
599
600 best = -1;
601 best_len = 0;
602 for (i = 0; i < n_allowed; i++) {
603 const char *op = allowed_operators[i];
604 size_t op_len = strlen(op);
605
606 if (op_len > best_len && !strncmp(op, p, op_len) && p[op_len]) {
607 best_len = op_len;
608 best = i;
609 }
610 }
611 if (best < 0) {
612 error = missing_operator_error(arg, allowed_operators, n_allowed);
613 goto error;
614 }
615
616 if (operatorp) {
617 *operatorp = best;
618 }
619 *valuep = xstrdup(p + best_len);
620 } else {
621 if (*p != '\0') {
622 error = xasprintf("%s: trailing garbage \"%s\" in argument",
623 arg, p);
624 goto error;
625 }
626 }
627 return NULL;
628
629 error:
630 *columnp = NULL;
631 free(*keyp);
632 *keyp = NULL;
633 if (valuep) {
634 free(*valuep);
635 *valuep = NULL;
636 if (operatorp) {
637 *operatorp = -1;
638 }
639 }
640 return error;
641 }
642
643 static const struct ovsdb_idl_column *
644 pre_parse_column_key_value(struct ctl_context *ctx,
645 const char *arg,
646 const struct ovsdb_idl_table_class *table)
647 {
648 const struct ovsdb_idl_column *column;
649 const char *p;
650 char *column_name;
651
652 p = arg;
653 die_if_error(ovsdb_token_parse(&p, &column_name));
654 if (column_name[0] == '\0') {
655 ctl_fatal("%s: missing column name", arg);
656 }
657
658 die_if_error(pre_get_column(ctx, table, column_name, &column));
659 free(column_name);
660
661 return column;
662 }
663
664 /* Checks if the 'column' is mutable. Returns NULL if it is mutable, or a
665 * malloc()'ed error message otherwise. */
666 static char * OVS_WARN_UNUSED_RESULT
667 check_mutable(const struct ovsdb_idl_row *row,
668 const struct ovsdb_idl_column *column)
669 {
670 if (!ovsdb_idl_is_mutable(row, column)) {
671 return xasprintf("cannot modify read-only column %s in table %s",
672 column->name, row->table->class_->name);
673 }
674 return NULL;
675 }
676
677 #define RELOPS \
678 RELOP(RELOP_EQ, "=") \
679 RELOP(RELOP_NE, "!=") \
680 RELOP(RELOP_LT, "<") \
681 RELOP(RELOP_GT, ">") \
682 RELOP(RELOP_LE, "<=") \
683 RELOP(RELOP_GE, ">=") \
684 RELOP(RELOP_SET_EQ, "{=}") \
685 RELOP(RELOP_SET_NE, "{!=}") \
686 RELOP(RELOP_SET_LT, "{<}") \
687 RELOP(RELOP_SET_GT, "{>}") \
688 RELOP(RELOP_SET_LE, "{<=}") \
689 RELOP(RELOP_SET_GE, "{>=}")
690
691 enum relop {
692 #define RELOP(ENUM, STRING) ENUM,
693 RELOPS
694 #undef RELOP
695 };
696
697 static bool
698 is_set_operator(enum relop op)
699 {
700 return (op == RELOP_SET_EQ || op == RELOP_SET_NE ||
701 op == RELOP_SET_LT || op == RELOP_SET_GT ||
702 op == RELOP_SET_LE || op == RELOP_SET_GE);
703 }
704
705 static bool
706 evaluate_relop(const struct ovsdb_datum *a, const struct ovsdb_datum *b,
707 const struct ovsdb_type *type, enum relop op)
708 {
709 switch (op) {
710 case RELOP_EQ:
711 case RELOP_SET_EQ:
712 return ovsdb_datum_compare_3way(a, b, type) == 0;
713 case RELOP_NE:
714 case RELOP_SET_NE:
715 return ovsdb_datum_compare_3way(a, b, type) != 0;
716 case RELOP_LT:
717 return ovsdb_datum_compare_3way(a, b, type) < 0;
718 case RELOP_GT:
719 return ovsdb_datum_compare_3way(a, b, type) > 0;
720 case RELOP_LE:
721 return ovsdb_datum_compare_3way(a, b, type) <= 0;
722 case RELOP_GE:
723 return ovsdb_datum_compare_3way(a, b, type) >= 0;
724
725 case RELOP_SET_LT:
726 return b->n > a->n && ovsdb_datum_includes_all(a, b, type);
727 case RELOP_SET_GT:
728 return a->n > b->n && ovsdb_datum_includes_all(b, a, type);
729 case RELOP_SET_LE:
730 return ovsdb_datum_includes_all(a, b, type);
731 case RELOP_SET_GE:
732 return ovsdb_datum_includes_all(b, a, type);
733
734 default:
735 OVS_NOT_REACHED();
736 }
737 }
738
739 /* Checks if given row satisfies the specified condition. Returns the result of
740 * evaluating the condition in 'satisfied' flag and NULL as a return value on
741 * success. On failure returns a malloc()'ed error message and 'satisfied'
742 * value is not modified. */
743 static char * OVS_WARN_UNUSED_RESULT
744 check_condition(const struct ovsdb_idl_table_class *table,
745 const struct ovsdb_idl_row *row, const char *arg,
746 struct ovsdb_symbol_table *symtab, bool *satisfied)
747 {
748 static const char *operators[] = {
749 #define RELOP(ENUM, STRING) STRING,
750 RELOPS
751 #undef RELOP
752 };
753
754 const struct ovsdb_idl_column *column;
755 const struct ovsdb_datum *have_datum;
756 char *key_string = NULL;
757 char *value_string = NULL;
758 struct ovsdb_type type;
759 int operator;
760 bool retval;
761 char *error;
762
763 ovs_assert(satisfied);
764
765 error = parse_column_key_value(arg, table, &column, &key_string,
766 &operator, operators, ARRAY_SIZE(operators),
767 &value_string);
768 if (error) {
769 goto out;
770 }
771 if (!value_string) {
772 error = xasprintf("%s: missing value", arg);
773 goto out;
774 }
775
776 type = column->type;
777 type.n_max = UINT_MAX;
778
779 have_datum = ovsdb_idl_read(row, column);
780 if (key_string) {
781 union ovsdb_atom want_key;
782 struct ovsdb_datum b;
783 unsigned int idx;
784
785 if (column->type.value.type == OVSDB_TYPE_VOID) {
786 error = xasprintf("cannot specify key to check for non-map column "
787 "%s", column->name);
788 goto out;
789 }
790
791 error = ovsdb_atom_from_string(&want_key, NULL, &column->type.key,
792 key_string, symtab);
793 if (error) {
794 goto out;
795 }
796
797 type.key = type.value;
798 type.value.type = OVSDB_TYPE_VOID;
799 error = ovsdb_datum_from_string(&b, &type, value_string, symtab);
800 if (error) {
801 goto out;
802 }
803
804 idx = ovsdb_datum_find_key(have_datum,
805 &want_key, column->type.key.type);
806 if (idx == UINT_MAX && !is_set_operator(operator)) {
807 retval = false;
808 } else {
809 struct ovsdb_datum a;
810
811 if (idx != UINT_MAX) {
812 a.n = 1;
813 a.keys = &have_datum->values[idx];
814 a.values = NULL;
815 } else {
816 a.n = 0;
817 a.keys = NULL;
818 a.values = NULL;
819 }
820
821 retval = evaluate_relop(&a, &b, &type, operator);
822 }
823
824 ovsdb_atom_destroy(&want_key, column->type.key.type);
825 ovsdb_datum_destroy(&b, &type);
826 } else {
827 struct ovsdb_datum want_datum;
828
829 error = ovsdb_datum_from_string(&want_datum, &column->type,
830 value_string, symtab);
831 if (error) {
832 goto out;
833 }
834 retval = evaluate_relop(have_datum, &want_datum, &type, operator);
835 ovsdb_datum_destroy(&want_datum, &column->type);
836 }
837
838 *satisfied = retval;
839 out:
840 free(key_string);
841 free(value_string);
842
843 return error;
844 }
845
846 static void
847 invalidate_cache(struct ctl_context *ctx)
848 {
849 if (ctx->invalidate_cache_cb) {
850 (ctx->invalidate_cache_cb)(ctx);
851 }
852 }
853 \f
854 static void
855 pre_cmd_get(struct ctl_context *ctx)
856 {
857 const char *id = shash_find_data(&ctx->options, "--id");
858 const char *table_name = ctx->argv[1];
859 const struct ovsdb_idl_table_class *table;
860 int i;
861
862 /* Using "get" without --id or a column name could possibly make sense.
863 * Maybe, for example, a *ctl command run wants to assert that a row
864 * exists. But it is unlikely that an interactive user would want to do
865 * that, so issue a warning if we're running on a terminal. */
866 if (!id && ctx->argc <= 3 && isatty(STDOUT_FILENO)) {
867 VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
868 "possibly erroneous");
869 }
870
871 table = pre_get_table(ctx, table_name);
872 for (i = 3; i < ctx->argc; i++) {
873 if (!strcasecmp(ctx->argv[i], "_uuid")
874 || !strcasecmp(ctx->argv[i], "-uuid")) {
875 continue;
876 }
877
878 pre_parse_column_key_value(ctx, ctx->argv[i], table);
879 }
880 }
881
882 static void
883 cmd_get(struct ctl_context *ctx)
884 {
885 const char *id = shash_find_data(&ctx->options, "--id");
886 bool must_exist = !shash_find(&ctx->options, "--if-exists");
887 const char *table_name = ctx->argv[1];
888 const char *record_id = ctx->argv[2];
889 const struct ovsdb_idl_table_class *table;
890 const struct ovsdb_idl_row *row;
891 struct ds *out = &ctx->output;
892 int i;
893
894 if (id && !must_exist) {
895 ctl_fatal("--if-exists and --id may not be specified together");
896 }
897
898 die_if_error(get_table(table_name, &table));
899 die_if_error(ctl_get_row(ctx, table, record_id, must_exist, &row));
900 if (!row) {
901 return;
902 }
903
904 if (id) {
905 struct ovsdb_symbol *symbol;
906 bool new;
907
908 die_if_error(create_symbol(ctx->symtab, id, &symbol, &new));
909 if (!new) {
910 ctl_fatal("row id \"%s\" specified on \"get\" command was used "
911 "before it was defined", id);
912 }
913 symbol->uuid = row->uuid;
914
915 /* This symbol refers to a row that already exists, so disable warnings
916 * about it being unreferenced. */
917 symbol->strong_ref = true;
918 }
919 for (i = 3; i < ctx->argc; i++) {
920 const struct ovsdb_idl_column *column;
921 const struct ovsdb_datum *datum;
922 char *key_string;
923
924 /* Special case for obtaining the UUID of a row. We can't just do this
925 * through parse_column_key_value() below since it returns a "struct
926 * ovsdb_idl_column" and the UUID column doesn't have one. */
927 if (!strcasecmp(ctx->argv[i], "_uuid")
928 || !strcasecmp(ctx->argv[i], "-uuid")) {
929 ds_put_format(out, UUID_FMT"\n", UUID_ARGS(&row->uuid));
930 continue;
931 }
932
933 die_if_error(parse_column_key_value(ctx->argv[i], table,
934 &column, &key_string,
935 NULL, NULL, 0, NULL));
936
937 ovsdb_idl_txn_verify(row, column);
938 datum = ovsdb_idl_read(row, column);
939 if (key_string) {
940 union ovsdb_atom key;
941 unsigned int idx;
942
943 if (column->type.value.type == OVSDB_TYPE_VOID) {
944 ctl_fatal("cannot specify key to get for non-map column %s",
945 column->name);
946 }
947
948 die_if_error(ovsdb_atom_from_string(&key, NULL,
949 &column->type.key,
950 key_string, ctx->symtab));
951
952 idx = ovsdb_datum_find_key(datum, &key,
953 column->type.key.type);
954 if (idx == UINT_MAX) {
955 if (must_exist) {
956 ctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
957 key_string, table->name, record_id,
958 column->name);
959 }
960 } else {
961 ovsdb_atom_to_string(&datum->values[idx],
962 column->type.value.type, out);
963 }
964 ovsdb_atom_destroy(&key, column->type.key.type);
965 } else {
966 ovsdb_datum_to_string(datum, &column->type, out);
967 }
968 ds_put_char(out, '\n');
969
970 free(key_string);
971 }
972 }
973
974 /* Returns NULL on success or malloc()'ed error message on failure. */
975 static char * OVS_WARN_UNUSED_RESULT
976 parse_column_names(const char *column_names,
977 const struct ovsdb_idl_table_class *table,
978 const struct ovsdb_idl_column ***columnsp,
979 size_t *n_columnsp)
980 {
981 const struct ovsdb_idl_column **columns;
982 size_t n_columns;
983
984 if (!column_names) {
985 size_t i;
986
987 n_columns = table->n_columns + 1;
988 columns = xmalloc(n_columns * sizeof *columns);
989 columns[0] = NULL;
990 for (i = 0; i < table->n_columns; i++) {
991 columns[i + 1] = &table->columns[i];
992 }
993 } else {
994 char *s = xstrdup(column_names);
995 size_t allocated_columns;
996 char *save_ptr = NULL;
997 char *column_name;
998
999 columns = NULL;
1000 allocated_columns = n_columns = 0;
1001 for (column_name = strtok_r(s, ", ", &save_ptr); column_name;
1002 column_name = strtok_r(NULL, ", ", &save_ptr)) {
1003 const struct ovsdb_idl_column *column;
1004
1005 if (!strcasecmp(column_name, "_uuid")) {
1006 column = NULL;
1007 } else {
1008 char *error = get_column(table, column_name, &column);
1009 if (error) {
1010 free(columns);
1011 free(s);
1012 return error;
1013 }
1014 }
1015 if (n_columns >= allocated_columns) {
1016 columns = x2nrealloc(columns, &allocated_columns,
1017 sizeof *columns);
1018 }
1019 columns[n_columns++] = column;
1020 }
1021 free(s);
1022
1023 if (!n_columns) {
1024 return xstrdup("must specify at least one column name");
1025 }
1026 }
1027 *columnsp = columns;
1028 *n_columnsp = n_columns;
1029 return NULL;
1030 }
1031
1032 static void
1033 pre_list_columns(struct ctl_context *ctx,
1034 const struct ovsdb_idl_table_class *table,
1035 const char *column_names)
1036 {
1037 const struct ovsdb_idl_column **columns;
1038 size_t n_columns;
1039 size_t i;
1040
1041 die_if_error(parse_column_names(column_names, table, &columns, &n_columns));
1042 for (i = 0; i < n_columns; i++) {
1043 if (columns[i]) {
1044 ovsdb_idl_add_column(ctx->idl, columns[i]);
1045 }
1046 }
1047 free(columns);
1048 }
1049
1050 static void
1051 pre_cmd_list(struct ctl_context *ctx)
1052 {
1053 const char *column_names = shash_find_data(&ctx->options, "--columns");
1054 const char *table_name = ctx->argv[1];
1055 const struct ovsdb_idl_table_class *table;
1056
1057 table = pre_get_table(ctx, table_name);
1058 pre_list_columns(ctx, table, column_names);
1059 }
1060
1061 static struct table *
1062 list_make_table(const struct ovsdb_idl_column **columns, size_t n_columns)
1063 {
1064 struct table *out;
1065 size_t i;
1066
1067 out = xmalloc(sizeof *out);
1068 table_init(out);
1069
1070 for (i = 0; i < n_columns; i++) {
1071 const struct ovsdb_idl_column *column = columns[i];
1072 const char *column_name = column ? column->name : "_uuid";
1073
1074 table_add_column(out, "%s", column_name);
1075 }
1076
1077 return out;
1078 }
1079
1080 static void
1081 list_record(const struct ovsdb_idl_row *row,
1082 const struct ovsdb_idl_column **columns, size_t n_columns,
1083 struct table *out)
1084 {
1085 size_t i;
1086
1087 if (!row) {
1088 return;
1089 }
1090
1091 table_add_row(out);
1092 for (i = 0; i < n_columns; i++) {
1093 const struct ovsdb_idl_column *column = columns[i];
1094 struct cell *cell = table_add_cell(out);
1095
1096 if (!column) {
1097 struct ovsdb_datum datum;
1098 union ovsdb_atom atom;
1099
1100 atom.uuid = row->uuid;
1101
1102 datum.keys = &atom;
1103 datum.values = NULL;
1104 datum.n = 1;
1105
1106 cell->json = ovsdb_datum_to_json(&datum, &ovsdb_type_uuid);
1107 cell->type = &ovsdb_type_uuid;
1108 } else {
1109 const struct ovsdb_datum *datum = ovsdb_idl_read(row, column);
1110
1111 cell->json = ovsdb_datum_to_json(datum, &column->type);
1112 cell->type = &column->type;
1113 }
1114 }
1115 }
1116
1117 static void
1118 cmd_list(struct ctl_context *ctx)
1119 {
1120 const char *column_names = shash_find_data(&ctx->options, "--columns");
1121 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1122 const struct ovsdb_idl_column **columns;
1123 const char *table_name = ctx->argv[1];
1124 const struct ovsdb_idl_table_class *table;
1125 struct table *out;
1126 size_t n_columns;
1127 int i;
1128
1129 die_if_error(get_table(table_name, &table));
1130 die_if_error(parse_column_names(column_names, table, &columns, &n_columns));
1131 out = ctx->table = list_make_table(columns, n_columns);
1132 if (ctx->argc > 2) {
1133 for (i = 2; i < ctx->argc; i++) {
1134 const struct ovsdb_idl_row *row;
1135
1136 die_if_error(ctl_get_row(ctx, table, ctx->argv[i], must_exist,
1137 &row));
1138 list_record(row, columns, n_columns, out);
1139 }
1140 } else {
1141 const struct ovsdb_idl_row *row;
1142
1143 for (row = ovsdb_idl_first_row(ctx->idl, table); row != NULL;
1144 row = ovsdb_idl_next_row(row)) {
1145 list_record(row, columns, n_columns, out);
1146 }
1147 }
1148 free(columns);
1149 }
1150
1151 /* Finds the "struct ovsdb_idl_table_class *" with 'table_name' by searching
1152 * the tables in these schema. Returns NULL and sets 'tablep' on success, or a
1153 * malloc()'ed error message on failure. */
1154 static char * OVS_WARN_UNUSED_RESULT
1155 get_table(const char *table_name, const struct ovsdb_idl_table_class **tablep)
1156 {
1157 const struct ovsdb_idl_table_class *best_match = NULL;
1158 unsigned int best_score = 0;
1159 char *error = NULL;
1160
1161 for (const struct ovsdb_idl_table_class *table = idl_classes;
1162 table < &idl_classes[n_classes]; table++) {
1163 unsigned int score = score_partial_match(table->name, table_name);
1164 if (score > best_score) {
1165 best_match = table;
1166 best_score = score;
1167 } else if (score == best_score) {
1168 best_match = NULL;
1169 }
1170 }
1171 if (best_match) {
1172 *tablep = best_match;
1173 } else if (best_score) {
1174 error = xasprintf("multiple table names match \"%s\"", table_name);
1175 } else {
1176 error = xasprintf("unknown table \"%s\"", table_name);
1177 }
1178 return error;
1179 }
1180
1181 static void
1182 pre_cmd_find(struct ctl_context *ctx)
1183 {
1184 const char *column_names = shash_find_data(&ctx->options, "--columns");
1185 const char *table_name = ctx->argv[1];
1186 const struct ovsdb_idl_table_class *table;
1187 int i;
1188
1189 table = pre_get_table(ctx, table_name);
1190 pre_list_columns(ctx, table, column_names);
1191 for (i = 2; i < ctx->argc; i++) {
1192 pre_parse_column_key_value(ctx, ctx->argv[i], table);
1193 }
1194 }
1195
1196 static void
1197 cmd_find(struct ctl_context *ctx)
1198 {
1199 const char *column_names = shash_find_data(&ctx->options, "--columns");
1200 const struct ovsdb_idl_column **columns;
1201 const char *table_name = ctx->argv[1];
1202 const struct ovsdb_idl_table_class *table;
1203 const struct ovsdb_idl_row *row;
1204 struct table *out;
1205 size_t n_columns;
1206
1207 die_if_error(get_table(table_name, &table));
1208 die_if_error(parse_column_names(column_names, table, &columns, &n_columns));
1209 out = ctx->table = list_make_table(columns, n_columns);
1210 for (row = ovsdb_idl_first_row(ctx->idl, table); row;
1211 row = ovsdb_idl_next_row(row)) {
1212 int i;
1213
1214 for (i = 2; i < ctx->argc; i++) {
1215 bool satisfied;
1216
1217 die_if_error(check_condition(table, row, ctx->argv[i], ctx->symtab,
1218 &satisfied));
1219 if (!satisfied) {
1220 goto next_row;
1221 }
1222 }
1223 list_record(row, columns, n_columns, out);
1224
1225 next_row: ;
1226 }
1227 free(columns);
1228 }
1229
1230 /* Sets the column of 'row' in 'table'. Returns NULL on success or a
1231 * malloc()'ed error message on failure. */
1232 static char * OVS_WARN_UNUSED_RESULT
1233 set_column(const struct ovsdb_idl_table_class *table,
1234 const struct ovsdb_idl_row *row, const char *arg,
1235 struct ovsdb_symbol_table *symtab)
1236 {
1237 const struct ovsdb_idl_column *column;
1238 char *key_string = NULL;
1239 char *value_string = NULL;
1240 char *error;
1241
1242 error = parse_column_key_value(arg, table, &column, &key_string,
1243 NULL, NULL, 0, &value_string);
1244 if (error) {
1245 goto out;
1246 }
1247 if (!value_string) {
1248 error = xasprintf("%s: missing value", arg);
1249 goto out;
1250 }
1251 error = check_mutable(row, column);
1252 if (error) {
1253 goto out;
1254 }
1255
1256 if (key_string) {
1257 union ovsdb_atom key, value;
1258 struct ovsdb_datum datum;
1259
1260 if (column->type.value.type == OVSDB_TYPE_VOID) {
1261 error = xasprintf("cannot specify key to set for non-map column "
1262 "%s", column->name);
1263 goto out;
1264 }
1265
1266 error = ovsdb_atom_from_string(&key, NULL, &column->type.key,
1267 key_string, symtab);
1268 if (error) {
1269 goto out;
1270 }
1271 error = ovsdb_atom_from_string(&value, NULL, &column->type.value,
1272 value_string, symtab);
1273 if (error) {
1274 goto out;
1275 }
1276
1277 ovsdb_datum_init_empty(&datum);
1278 ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type, NULL);
1279
1280 ovsdb_atom_destroy(&key, column->type.key.type);
1281 ovsdb_atom_destroy(&value, column->type.value.type);
1282
1283 ovsdb_datum_union(&datum, ovsdb_idl_read(row, column),
1284 &column->type, false);
1285 ovsdb_idl_txn_verify(row, column);
1286 ovsdb_idl_txn_write(row, column, &datum);
1287 } else {
1288 struct ovsdb_datum datum;
1289
1290 error = ovsdb_datum_from_string(&datum, &column->type,
1291 value_string, symtab);
1292 if (error) {
1293 goto out;
1294 }
1295 ovsdb_idl_txn_write(row, column, &datum);
1296 }
1297
1298 out:
1299 free(key_string);
1300 free(value_string);
1301
1302 return error;
1303 }
1304
1305 static void
1306 pre_cmd_set(struct ctl_context *ctx)
1307 {
1308 const char *table_name = ctx->argv[1];
1309 const struct ovsdb_idl_table_class *table;
1310 int i;
1311
1312 table = pre_get_table(ctx, table_name);
1313 for (i = 3; i < ctx->argc; i++) {
1314 pre_parse_column_key_value(ctx, ctx->argv[i], table);
1315 }
1316 }
1317
1318 static void
1319 cmd_set(struct ctl_context *ctx)
1320 {
1321 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1322 const char *table_name = ctx->argv[1];
1323 const char *record_id = ctx->argv[2];
1324 const struct ovsdb_idl_table_class *table;
1325 const struct ovsdb_idl_row *row;
1326 int i;
1327
1328 die_if_error(get_table(table_name, &table));
1329 die_if_error(ctl_get_row(ctx, table, record_id, must_exist, &row));
1330 if (!row) {
1331 return;
1332 }
1333
1334 for (i = 3; i < ctx->argc; i++) {
1335 die_if_error(set_column(table, row, ctx->argv[i], ctx->symtab));
1336 }
1337
1338 invalidate_cache(ctx);
1339 }
1340
1341 static void
1342 pre_cmd_add(struct ctl_context *ctx)
1343 {
1344 const char *table_name = ctx->argv[1];
1345 const char *column_name = ctx->argv[3];
1346 const struct ovsdb_idl_table_class *table;
1347 const struct ovsdb_idl_column *column;
1348
1349 table = pre_get_table(ctx, table_name);
1350 die_if_error(pre_get_column(ctx, table, column_name, &column));
1351 }
1352
1353 static void
1354 cmd_add(struct ctl_context *ctx)
1355 {
1356 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1357 const char *table_name = ctx->argv[1];
1358 const char *record_id = ctx->argv[2];
1359 const char *column_name = ctx->argv[3];
1360 const struct ovsdb_idl_table_class *table;
1361 const struct ovsdb_idl_column *column;
1362 const struct ovsdb_idl_row *row;
1363 const struct ovsdb_type *type;
1364 struct ovsdb_datum old;
1365 int i;
1366
1367 die_if_error(get_table(table_name, &table));
1368 die_if_error(get_column(table, column_name, &column));
1369 die_if_error(ctl_get_row(ctx, table, record_id, must_exist, &row));
1370 if (!row) {
1371 return;
1372 }
1373 die_if_error(check_mutable(row, column));
1374
1375 type = &column->type;
1376 ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
1377 for (i = 4; i < ctx->argc; i++) {
1378 struct ovsdb_type add_type;
1379 struct ovsdb_datum add;
1380
1381 add_type = *type;
1382 add_type.n_min = 1;
1383 add_type.n_max = UINT_MAX;
1384 die_if_error(ovsdb_datum_from_string(&add, &add_type, ctx->argv[i],
1385 ctx->symtab));
1386 ovsdb_datum_union(&old, &add, type, false);
1387 ovsdb_datum_destroy(&add, type);
1388 }
1389 if (old.n > type->n_max) {
1390 ctl_fatal("\"add\" operation would put %u %s in column %s of "
1391 "table %s but the maximum number is %u",
1392 old.n,
1393 type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
1394 column->name, table->name, type->n_max);
1395 }
1396 ovsdb_idl_txn_verify(row, column);
1397 ovsdb_idl_txn_write(row, column, &old);
1398
1399 invalidate_cache(ctx);
1400 }
1401
1402 static void
1403 pre_cmd_remove(struct ctl_context *ctx)
1404 {
1405 const char *table_name = ctx->argv[1];
1406 const char *column_name = ctx->argv[3];
1407 const struct ovsdb_idl_table_class *table;
1408 const struct ovsdb_idl_column *column;
1409
1410 table = pre_get_table(ctx, table_name);
1411 die_if_error(pre_get_column(ctx, table, column_name, &column));
1412 }
1413
1414 static void
1415 cmd_remove(struct ctl_context *ctx)
1416 {
1417 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1418 const char *table_name = ctx->argv[1];
1419 const char *record_id = ctx->argv[2];
1420 const char *column_name = ctx->argv[3];
1421 const struct ovsdb_idl_table_class *table;
1422 const struct ovsdb_idl_column *column;
1423 const struct ovsdb_idl_row *row;
1424 const struct ovsdb_type *type;
1425 struct ovsdb_datum old;
1426 int i;
1427
1428 die_if_error(get_table(table_name, &table));
1429 die_if_error(get_column(table, column_name, &column));
1430 die_if_error(ctl_get_row(ctx, table, record_id, must_exist, &row));
1431 if (!row) {
1432 return;
1433 }
1434 die_if_error(check_mutable(row, column));
1435
1436 type = &column->type;
1437 ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
1438 for (i = 4; i < ctx->argc; i++) {
1439 struct ovsdb_type rm_type;
1440 struct ovsdb_datum rm;
1441 char *error;
1442
1443 rm_type = *type;
1444 rm_type.n_min = 1;
1445 rm_type.n_max = UINT_MAX;
1446 error = ovsdb_datum_from_string(&rm, &rm_type,
1447 ctx->argv[i], ctx->symtab);
1448
1449 if (error) {
1450 if (ovsdb_type_is_map(&rm_type)) {
1451 rm_type.value.type = OVSDB_TYPE_VOID;
1452 free(error);
1453 die_if_error(ovsdb_datum_from_string(
1454 &rm, &rm_type, ctx->argv[i], ctx->symtab));
1455 } else {
1456 ctl_fatal("%s", error);
1457 }
1458 }
1459 ovsdb_datum_subtract(&old, type, &rm, &rm_type);
1460 ovsdb_datum_destroy(&rm, &rm_type);
1461 }
1462 if (old.n < type->n_min) {
1463 ctl_fatal("\"remove\" operation would put %u %s in column %s of "
1464 "table %s but the minimum number is %u",
1465 old.n,
1466 type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
1467 column->name, table->name, type->n_min);
1468 }
1469 ovsdb_idl_txn_verify(row, column);
1470 ovsdb_idl_txn_write(row, column, &old);
1471
1472 invalidate_cache(ctx);
1473 }
1474
1475 static void
1476 pre_cmd_clear(struct ctl_context *ctx)
1477 {
1478 const char *table_name = ctx->argv[1];
1479 const struct ovsdb_idl_table_class *table;
1480 int i;
1481
1482 table = pre_get_table(ctx, table_name);
1483 for (i = 3; i < ctx->argc; i++) {
1484 const struct ovsdb_idl_column *column;
1485
1486 die_if_error(pre_get_column(ctx, table, ctx->argv[i], &column));
1487 }
1488 }
1489
1490 static void
1491 cmd_clear(struct ctl_context *ctx)
1492 {
1493 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1494 const char *table_name = ctx->argv[1];
1495 const char *record_id = ctx->argv[2];
1496 const struct ovsdb_idl_table_class *table;
1497 const struct ovsdb_idl_row *row;
1498 int i;
1499
1500 die_if_error(get_table(table_name, &table));
1501 die_if_error(ctl_get_row(ctx, table, record_id, must_exist, &row));
1502 if (!row) {
1503 return;
1504 }
1505
1506 for (i = 3; i < ctx->argc; i++) {
1507 const struct ovsdb_idl_column *column;
1508 const struct ovsdb_type *type;
1509 struct ovsdb_datum datum;
1510
1511 die_if_error(get_column(table, ctx->argv[i], &column));
1512 die_if_error(check_mutable(row, column));
1513
1514 type = &column->type;
1515 if (type->n_min > 0) {
1516 ctl_fatal("\"clear\" operation cannot be applied to column %s "
1517 "of table %s, which is not allowed to be empty",
1518 column->name, table->name);
1519 }
1520
1521 ovsdb_datum_init_empty(&datum);
1522 ovsdb_idl_txn_write(row, column, &datum);
1523 }
1524
1525 invalidate_cache(ctx);
1526 }
1527
1528 static void
1529 pre_create(struct ctl_context *ctx)
1530 {
1531 const char *id = shash_find_data(&ctx->options, "--id");
1532 const char *table_name = ctx->argv[1];
1533 const struct ovsdb_idl_table_class *table;
1534
1535 die_if_error(get_table(table_name, &table));
1536 if (!id && !table->is_root) {
1537 VLOG_WARN("applying \"create\" command to table %s without --id "
1538 "option will have no effect", table->name);
1539 }
1540 }
1541
1542 static void
1543 cmd_create(struct ctl_context *ctx)
1544 {
1545 const char *id = shash_find_data(&ctx->options, "--id");
1546 const char *table_name = ctx->argv[1];
1547 const struct ovsdb_idl_table_class *table;
1548 const struct ovsdb_idl_row *row;
1549 const struct uuid *uuid;
1550 int i;
1551
1552 die_if_error(get_table(table_name, &table));
1553 if (id) {
1554 struct ovsdb_symbol *symbol;
1555
1556 die_if_error(create_symbol(ctx->symtab, id, &symbol, NULL));
1557 if (table->is_root) {
1558 /* This table is in the root set, meaning that rows created in it
1559 * won't disappear even if they are unreferenced, so disable
1560 * warnings about that by pretending that there is a reference. */
1561 symbol->strong_ref = true;
1562 }
1563 uuid = &symbol->uuid;
1564 } else {
1565 uuid = NULL;
1566 }
1567
1568 row = ovsdb_idl_txn_insert(ctx->txn, table, uuid);
1569 for (i = 2; i < ctx->argc; i++) {
1570 die_if_error(set_column(table, row, ctx->argv[i], ctx->symtab));
1571 }
1572 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
1573 }
1574
1575 /* This function may be used as the 'postprocess' function for commands that
1576 * insert new rows into the database. It expects that the command's 'run'
1577 * function prints the UUID reported by ovsdb_idl_txn_insert() as the command's
1578 * sole output. It replaces that output by the row's permanent UUID assigned
1579 * by the database server and appends a new-line.
1580 *
1581 * Currently we use this only for "create", because the higher-level commands
1582 * are supposed to be independent of the actual structure of the vswitch
1583 * configuration. */
1584 static void
1585 post_create(struct ctl_context *ctx)
1586 {
1587 const struct uuid *real;
1588 struct uuid dummy;
1589
1590 if (!uuid_from_string(&dummy, ds_cstr(&ctx->output))) {
1591 OVS_NOT_REACHED();
1592 }
1593 real = ovsdb_idl_txn_get_insert_uuid(ctx->txn, &dummy);
1594 if (real) {
1595 ds_clear(&ctx->output);
1596 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(real));
1597 }
1598 ds_put_char(&ctx->output, '\n');
1599 }
1600
1601 static void
1602 pre_cmd_destroy(struct ctl_context *ctx)
1603 {
1604 const char *table_name = ctx->argv[1];
1605
1606 pre_get_table(ctx, table_name);
1607 }
1608
1609 static void
1610 cmd_destroy(struct ctl_context *ctx)
1611 {
1612 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1613 bool delete_all = shash_find(&ctx->options, "--all");
1614 const char *table_name = ctx->argv[1];
1615 const struct ovsdb_idl_table_class *table;
1616 int i;
1617
1618 die_if_error(get_table(table_name, &table));
1619
1620 if (delete_all && ctx->argc > 2) {
1621 ctl_fatal("--all and records argument should not be specified together");
1622 }
1623
1624 if (delete_all && !must_exist) {
1625 ctl_fatal("--all and --if-exists should not be specified together");
1626 }
1627
1628 if (delete_all) {
1629 const struct ovsdb_idl_row *row;
1630 const struct ovsdb_idl_row *next_row;
1631
1632 for (row = ovsdb_idl_first_row(ctx->idl, table);
1633 row;) {
1634 next_row = ovsdb_idl_next_row(row);
1635 ovsdb_idl_txn_delete(row);
1636 row = next_row;
1637 }
1638 } else {
1639 for (i = 2; i < ctx->argc; i++) {
1640 const struct ovsdb_idl_row *row;
1641
1642 die_if_error(ctl_get_row(ctx, table, ctx->argv[i], must_exist,
1643 &row));
1644 if (row) {
1645 ovsdb_idl_txn_delete(row);
1646 }
1647 }
1648 }
1649 invalidate_cache(ctx);
1650 }
1651
1652 static void
1653 pre_cmd_wait_until(struct ctl_context *ctx)
1654 {
1655 const char *table_name = ctx->argv[1];
1656 const struct ovsdb_idl_table_class *table;
1657 int i;
1658
1659 table = pre_get_table(ctx, table_name);
1660
1661 for (i = 3; i < ctx->argc; i++) {
1662 pre_parse_column_key_value(ctx, ctx->argv[i], table);
1663 }
1664 }
1665
1666 static void
1667 cmd_wait_until(struct ctl_context *ctx)
1668 {
1669 const char *table_name = ctx->argv[1];
1670 const char *record_id = ctx->argv[2];
1671 const struct ovsdb_idl_table_class *table;
1672 const struct ovsdb_idl_row *row;
1673 int i;
1674
1675 die_if_error(get_table(table_name, &table));
1676 die_if_error(ctl_get_row(ctx, table, record_id, false, &row));
1677 if (!row) {
1678 ctx->try_again = true;
1679 return;
1680 }
1681
1682 for (i = 3; i < ctx->argc; i++) {
1683 bool satisfied;
1684
1685 die_if_error(check_condition(table, row, ctx->argv[i], ctx->symtab,
1686 &satisfied));
1687 if (!satisfied) {
1688 ctx->try_again = true;
1689 return;
1690 }
1691 }
1692 }
1693
1694 /* Parses one command. */
1695 static void
1696 parse_command(int argc, char *argv[], struct shash *local_options,
1697 struct ctl_command *command)
1698 {
1699 const struct ctl_command_syntax *p;
1700 struct shash_node *node;
1701 int n_arg;
1702 int i;
1703
1704 shash_init(&command->options);
1705 shash_swap(local_options, &command->options);
1706 for (i = 0; i < argc; i++) {
1707 const char *option = argv[i];
1708 const char *equals;
1709 char *key, *value;
1710
1711 if (option[0] != '-') {
1712 break;
1713 }
1714
1715 equals = strchr(option, '=');
1716 if (equals) {
1717 key = xmemdup0(option, equals - option);
1718 value = xstrdup(equals + 1);
1719 } else {
1720 key = xstrdup(option);
1721 value = NULL;
1722 }
1723
1724 if (shash_find(&command->options, key)) {
1725 ctl_fatal("'%s' option specified multiple times", argv[i]);
1726 }
1727 shash_add_nocopy(&command->options, key, value);
1728 }
1729 if (i == argc) {
1730 ctl_fatal("missing command name (use --help for help)");
1731 }
1732
1733 p = shash_find_data(&all_commands, argv[i]);
1734 if (!p) {
1735 ctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1736 }
1737
1738 SHASH_FOR_EACH (node, &command->options) {
1739 const char *s = strstr(p->options, node->name);
1740 int end = s ? s[strlen(node->name)] : EOF;
1741
1742 if (!strchr("=,? ", end)) {
1743 ctl_fatal("'%s' command has no '%s' option",
1744 argv[i], node->name);
1745 }
1746 if (end != '?' && (end == '=') != (node->data != NULL)) {
1747 if (end == '=') {
1748 ctl_fatal("missing argument to '%s' option on '%s' "
1749 "command", node->name, argv[i]);
1750 } else {
1751 ctl_fatal("'%s' option on '%s' does not accept an "
1752 "argument", node->name, argv[i]);
1753 }
1754 }
1755 }
1756
1757 n_arg = argc - i - 1;
1758 if (n_arg < p->min_args) {
1759 ctl_fatal("'%s' command requires at least %d arguments",
1760 p->name, p->min_args);
1761 } else if (n_arg > p->max_args) {
1762 int j;
1763
1764 for (j = i + 1; j < argc; j++) {
1765 if (argv[j][0] == '-') {
1766 ctl_fatal("'%s' command takes at most %d arguments "
1767 "(note that options must precede command "
1768 "names and follow a \"--\" argument)",
1769 p->name, p->max_args);
1770 }
1771 }
1772
1773 ctl_fatal("'%s' command takes at most %d arguments",
1774 p->name, p->max_args);
1775 }
1776
1777 command->syntax = p;
1778 command->argc = n_arg + 1;
1779 command->argv = &argv[i];
1780 }
1781
1782 static void
1783 pre_cmd_show(struct ctl_context *ctx)
1784 {
1785 const struct cmd_show_table *show;
1786
1787 for (show = cmd_show_tables; show->table; show++) {
1788 size_t i;
1789
1790 ovsdb_idl_add_table(ctx->idl, show->table);
1791 if (show->name_column) {
1792 ovsdb_idl_add_column(ctx->idl, show->name_column);
1793 }
1794 for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
1795 const struct ovsdb_idl_column *column = show->columns[i];
1796 if (column) {
1797 ovsdb_idl_add_column(ctx->idl, column);
1798 }
1799 }
1800 if (show->wref_table.table) {
1801 ovsdb_idl_add_table(ctx->idl, show->wref_table.table);
1802 }
1803 if (show->wref_table.name_column) {
1804 ovsdb_idl_add_column(ctx->idl, show->wref_table.name_column);
1805 }
1806 if (show->wref_table.wref_column) {
1807 ovsdb_idl_add_column(ctx->idl, show->wref_table.wref_column);
1808 }
1809 }
1810 }
1811
1812 static const struct cmd_show_table *
1813 cmd_show_find_table_by_row(const struct ovsdb_idl_row *row)
1814 {
1815 const struct cmd_show_table *show;
1816
1817 for (show = cmd_show_tables; show->table; show++) {
1818 if (show->table == row->table->class_) {
1819 return show;
1820 }
1821 }
1822 return NULL;
1823 }
1824
1825 static const struct cmd_show_table *
1826 cmd_show_find_table_by_name(const char *name)
1827 {
1828 const struct cmd_show_table *show;
1829
1830 for (show = cmd_show_tables; show->table; show++) {
1831 if (!strcmp(show->table->name, name)) {
1832 return show;
1833 }
1834 }
1835 return NULL;
1836 }
1837
1838 /* Prints table entries that weak reference the 'cur_row'. */
1839 static void
1840 cmd_show_weak_ref(struct ctl_context *ctx, const struct cmd_show_table *show,
1841 const struct ovsdb_idl_row *cur_row, int level)
1842 {
1843 const struct ovsdb_idl_row *row_wref;
1844 const struct ovsdb_idl_table_class *table = show->wref_table.table;
1845 const struct ovsdb_idl_column *name_column
1846 = show->wref_table.name_column;
1847 const struct ovsdb_idl_column *wref_column
1848 = show->wref_table.wref_column;
1849
1850 if (!table || !name_column || !wref_column) {
1851 return;
1852 }
1853
1854 for (row_wref = ovsdb_idl_first_row(ctx->idl, table); row_wref;
1855 row_wref = ovsdb_idl_next_row(row_wref)) {
1856 const struct ovsdb_datum *wref_datum
1857 = ovsdb_idl_read(row_wref, wref_column);
1858 /* If weak reference refers to the 'cur_row', prints it. */
1859 if (wref_datum->n
1860 && uuid_equals(&cur_row->uuid, &wref_datum->keys[0].uuid)) {
1861 const struct ovsdb_datum *name_datum
1862 = ovsdb_idl_read(row_wref, name_column);
1863 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1864 ds_put_format(&ctx->output, "%s ", table->name);
1865 ovsdb_datum_to_string(name_datum, &name_column->type, &ctx->output);
1866 ds_put_char(&ctx->output, '\n');
1867 }
1868 }
1869 }
1870
1871 /* 'shown' records the tables that has been displayed by the current
1872 * command to avoid duplicated prints.
1873 */
1874 static void
1875 cmd_show_row(struct ctl_context *ctx, const struct ovsdb_idl_row *row,
1876 int level, struct sset *shown)
1877 {
1878 const struct cmd_show_table *show = cmd_show_find_table_by_row(row);
1879 size_t i;
1880
1881 ds_put_char_multiple(&ctx->output, ' ', level * 4);
1882 if (show && show->name_column) {
1883 const struct ovsdb_datum *datum;
1884
1885 ds_put_format(&ctx->output, "%s ", show->table->name);
1886 datum = ovsdb_idl_read(row, show->name_column);
1887 ovsdb_datum_to_string(datum, &show->name_column->type, &ctx->output);
1888 } else {
1889 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
1890 }
1891 ds_put_char(&ctx->output, '\n');
1892
1893 if (!show || sset_find(shown, show->table->name)) {
1894 return;
1895 }
1896
1897 sset_add(shown, show->table->name);
1898 for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
1899 const struct ovsdb_idl_column *column = show->columns[i];
1900 const struct ovsdb_datum *datum;
1901
1902 if (!column) {
1903 break;
1904 }
1905
1906 datum = ovsdb_idl_read(row, column);
1907 if (column->type.key.type == OVSDB_TYPE_UUID &&
1908 column->type.key.uuid.refTableName) {
1909 const struct cmd_show_table *ref_show;
1910 size_t j;
1911
1912 ref_show = cmd_show_find_table_by_name(
1913 column->type.key.uuid.refTableName);
1914 if (ref_show) {
1915 for (j = 0; j < datum->n; j++) {
1916 const struct ovsdb_idl_row *ref_row;
1917
1918 ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
1919 ref_show->table,
1920 &datum->keys[j].uuid);
1921 if (ref_row) {
1922 cmd_show_row(ctx, ref_row, level + 1, shown);
1923 }
1924 }
1925 continue;
1926 }
1927 } else if (ovsdb_type_is_map(&column->type) &&
1928 column->type.value.type == OVSDB_TYPE_UUID &&
1929 column->type.value.uuid.refTableName) {
1930 const struct cmd_show_table *ref_show;
1931 size_t j;
1932
1933 /* Prints the key to ref'ed table name map if the ref'ed table
1934 * is also defined in 'cmd_show_tables'. */
1935 ref_show = cmd_show_find_table_by_name(
1936 column->type.value.uuid.refTableName);
1937 if (ref_show && ref_show->name_column) {
1938 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1939 ds_put_format(&ctx->output, "%s:\n", column->name);
1940 for (j = 0; j < datum->n; j++) {
1941 const struct ovsdb_idl_row *ref_row;
1942
1943 ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
1944 ref_show->table,
1945 &datum->values[j].uuid);
1946
1947 ds_put_char_multiple(&ctx->output, ' ', (level + 2) * 4);
1948 ovsdb_atom_to_string(&datum->keys[j], column->type.key.type,
1949 &ctx->output);
1950 ds_put_char(&ctx->output, '=');
1951 if (ref_row) {
1952 const struct ovsdb_datum *ref_datum;
1953
1954 ref_datum = ovsdb_idl_read(ref_row,
1955 ref_show->name_column);
1956 ovsdb_datum_to_string(ref_datum,
1957 &ref_show->name_column->type,
1958 &ctx->output);
1959 } else {
1960 ds_put_cstr(&ctx->output, "\"<null>\"");
1961 }
1962 ds_put_char(&ctx->output, '\n');
1963 }
1964 continue;
1965 }
1966 }
1967
1968 if (!ovsdb_datum_is_default(datum, &column->type)) {
1969 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1970 ds_put_format(&ctx->output, "%s: ", column->name);
1971 ovsdb_datum_to_string(datum, &column->type, &ctx->output);
1972 ds_put_char(&ctx->output, '\n');
1973 }
1974 }
1975 cmd_show_weak_ref(ctx, show, row, level);
1976 sset_find_and_delete_assert(shown, show->table->name);
1977 }
1978
1979 static void
1980 cmd_show(struct ctl_context *ctx)
1981 {
1982 const struct ovsdb_idl_row *row;
1983 struct sset shown = SSET_INITIALIZER(&shown);
1984
1985 for (row = ovsdb_idl_first_row(ctx->idl, cmd_show_tables[0].table);
1986 row; row = ovsdb_idl_next_row(row)) {
1987 cmd_show_row(ctx, row, 0, &shown);
1988 }
1989
1990 ovs_assert(sset_is_empty(&shown));
1991 sset_destroy(&shown);
1992 }
1993
1994 \f
1995 /* Given pointer to dynamic array 'options_p', array's current size
1996 * 'allocated_options_p' and number of added options 'n_options_p',
1997 * adds all command options to the array. Enlarges the array if
1998 * necessary. */
1999 void
2000 ctl_add_cmd_options(struct option **options_p, size_t *n_options_p,
2001 size_t *allocated_options_p, int opt_val)
2002 {
2003 struct option *o;
2004 const struct shash_node *node;
2005 size_t n_existing_options = *n_options_p;
2006
2007 SHASH_FOR_EACH (node, &all_commands) {
2008 const struct ctl_command_syntax *p = node->data;
2009
2010 if (p->options[0]) {
2011 char *save_ptr = NULL;
2012 char *name;
2013 char *s;
2014
2015 s = xstrdup(p->options);
2016 for (name = strtok_r(s, ",", &save_ptr); name != NULL;
2017 name = strtok_r(NULL, ",", &save_ptr)) {
2018 ovs_assert(name[0] == '-' && name[1] == '-' && name[2]);
2019 name += 2;
2020
2021 size_t n = strcspn(name, "=?");
2022 int has_arg = (name[n] == '\0' ? no_argument
2023 : name[n] == '=' ? required_argument
2024 : optional_argument);
2025 name[n] = '\0';
2026
2027 o = find_option(name, *options_p, *n_options_p);
2028 if (o) {
2029 ovs_assert(o - *options_p >= n_existing_options);
2030 ovs_assert(o->has_arg == has_arg);
2031 } else {
2032 o = add_option(options_p, n_options_p, allocated_options_p);
2033 o->name = xstrdup(name);
2034 o->has_arg = has_arg;
2035 o->flag = NULL;
2036 o->val = opt_val;
2037 }
2038 }
2039
2040 free(s);
2041 }
2042 }
2043 o = add_option(options_p, n_options_p, allocated_options_p);
2044 memset(o, 0, sizeof *o);
2045 }
2046
2047 /* Parses command-line input for commands. */
2048 struct ctl_command *
2049 ctl_parse_commands(int argc, char *argv[], struct shash *local_options,
2050 size_t *n_commandsp)
2051 {
2052 struct ctl_command *commands;
2053 size_t n_commands, allocated_commands;
2054 int i, start;
2055
2056 commands = NULL;
2057 n_commands = allocated_commands = 0;
2058
2059 for (start = i = 0; i <= argc; i++) {
2060 if (i == argc || !strcmp(argv[i], "--")) {
2061 if (i > start) {
2062 if (n_commands >= allocated_commands) {
2063 struct ctl_command *c;
2064
2065 commands = x2nrealloc(commands, &allocated_commands,
2066 sizeof *commands);
2067 for (c = commands; c < &commands[n_commands]; c++) {
2068 shash_moved(&c->options);
2069 }
2070 }
2071 parse_command(i - start, &argv[start], local_options,
2072 &commands[n_commands++]);
2073 } else if (!shash_is_empty(local_options)) {
2074 ctl_fatal("missing command name (use --help for help)");
2075 }
2076 start = i + 1;
2077 }
2078 }
2079 if (!n_commands) {
2080 ctl_fatal("missing command name (use --help for help)");
2081 }
2082 *n_commandsp = n_commands;
2083 return commands;
2084 }
2085
2086 /* Prints all registered commands. */
2087 void
2088 ctl_print_commands(void)
2089 {
2090 const struct shash_node *node;
2091
2092 SHASH_FOR_EACH (node, &all_commands) {
2093 const struct ctl_command_syntax *p = node->data;
2094 char *options = xstrdup(p->options);
2095 char *options_begin = options;
2096 char *item;
2097
2098 for (item = strsep(&options, ","); item != NULL;
2099 item = strsep(&options, ",")) {
2100 if (item[0] != '\0') {
2101 printf("[%s] ", item);
2102 }
2103 }
2104 printf(",%s,", p->name);
2105 print_command_arguments(p);
2106 printf("\n");
2107
2108 free(options_begin);
2109 }
2110
2111 exit(EXIT_SUCCESS);
2112 }
2113
2114 /* Given array of options 'options', prints them. */
2115 void
2116 ctl_print_options(const struct option *options)
2117 {
2118 for (; options->name; options++) {
2119 const struct option *o = options;
2120
2121 printf("--%s%s\n", o->name, o->has_arg ? "=ARG" : "");
2122 if (o->flag == NULL && o->val > 0 && o->val <= UCHAR_MAX) {
2123 printf("-%c%s\n", o->val, o->has_arg ? " ARG" : "");
2124 }
2125 }
2126
2127 exit(EXIT_SUCCESS);
2128 }
2129
2130 /* Returns the default local database path. */
2131 char *
2132 ctl_default_db(void)
2133 {
2134 static char *def;
2135 if (!def) {
2136 def = xasprintf("unix:%s/db.sock", ovs_rundir());
2137 }
2138 return def;
2139 }
2140
2141 /* Returns true if it looks like this set of arguments might modify the
2142 * database, otherwise false. (Not very smart, so it's prone to false
2143 * positives.) */
2144 bool
2145 ctl_might_write_to_db(const struct ctl_command *commands, size_t n)
2146 {
2147 for (size_t i = 0; i < n; i++) {
2148 if (commands[i].syntax->mode == RW) {
2149 return true;
2150 }
2151 }
2152 return false;
2153 }
2154
2155 void
2156 ctl_fatal(const char *format, ...)
2157 {
2158 char *message;
2159 va_list args;
2160
2161 va_start(args, format);
2162 message = xvasprintf(format, args);
2163 va_end(args);
2164
2165 vlog_set_levels(&this_module, VLF_CONSOLE, VLL_OFF);
2166 VLOG_ERR("%s", message);
2167 ovs_error(0, "%s", message);
2168 ctl_exit(EXIT_FAILURE);
2169 }
2170
2171 /* Frees the current transaction and the underlying IDL and then calls
2172 * exit(status).
2173 *
2174 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2175 * for a clean memory leak report from valgrind in the normal case. That makes
2176 * it easier to notice real memory leaks. */
2177 static void
2178 ctl_exit(int status)
2179 {
2180 if (ctl_exit_func) {
2181 ctl_exit_func(status);
2182 }
2183 exit(status);
2184 }
2185
2186 /* Comman database commands to be registered. */
2187 static const struct ctl_command_syntax db_ctl_commands[] = {
2188 {"comment", 0, INT_MAX, "[ARG]...", NULL, NULL, NULL, "", RO},
2189 {"get", 2, INT_MAX, "TABLE RECORD [COLUMN[:KEY]]...",pre_cmd_get, cmd_get,
2190 NULL, "--if-exists,--id=", RO},
2191 {"list", 1, INT_MAX, "TABLE [RECORD]...", pre_cmd_list, cmd_list, NULL,
2192 "--if-exists,--columns=", RO},
2193 {"find", 1, INT_MAX, "TABLE [COLUMN[:KEY]=VALUE]...", pre_cmd_find,
2194 cmd_find, NULL, "--columns=", RO},
2195 {"set", 3, INT_MAX, "TABLE RECORD COLUMN[:KEY]=VALUE...", pre_cmd_set,
2196 cmd_set, NULL, "--if-exists", RW},
2197 {"add", 4, INT_MAX, "TABLE RECORD COLUMN [KEY=]VALUE...", pre_cmd_add,
2198 cmd_add, NULL, "--if-exists", RW},
2199 {"remove", 4, INT_MAX, "TABLE RECORD COLUMN KEY|VALUE|KEY=VALUE...",
2200 pre_cmd_remove, cmd_remove, NULL, "--if-exists", RW},
2201 {"clear", 3, INT_MAX, "TABLE RECORD COLUMN...", pre_cmd_clear, cmd_clear,
2202 NULL, "--if-exists", RW},
2203 {"create", 2, INT_MAX, "TABLE COLUMN[:KEY]=VALUE...", pre_create,
2204 cmd_create, post_create, "--id=", RW},
2205 {"destroy", 1, INT_MAX, "TABLE [RECORD]...", pre_cmd_destroy, cmd_destroy,
2206 NULL, "--if-exists,--all", RW},
2207 {"wait-until", 2, INT_MAX, "TABLE RECORD [COLUMN[:KEY]=VALUE]...",
2208 pre_cmd_wait_until, cmd_wait_until, NULL, "", RO},
2209 {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
2210 };
2211
2212 static void
2213 ctl_register_command(const struct ctl_command_syntax *command)
2214 {
2215 shash_add_assert(&all_commands, command->name, command);
2216 }
2217
2218 /* Registers commands represented by 'struct ctl_command_syntax's to
2219 * 'all_commands'. The last element of 'commands' must be an all-NULL
2220 * element. */
2221 void
2222 ctl_register_commands(const struct ctl_command_syntax *commands)
2223 {
2224 const struct ctl_command_syntax *p;
2225
2226 for (p = commands; p->name; p++) {
2227 ctl_register_command(p);
2228 }
2229 }
2230
2231 /* Registers the 'db_ctl_commands' to 'all_commands'. */
2232 void
2233 ctl_init__(const struct ovsdb_idl_class *idl_class_,
2234 const struct ctl_table_class *ctl_classes_,
2235 const struct cmd_show_table cmd_show_tables_[],
2236 void (*ctl_exit_func_)(int status))
2237 {
2238 idl_class = idl_class_;
2239 idl_classes = idl_class_->tables;
2240 ctl_classes = ctl_classes_;
2241 n_classes = idl_class->n_tables;
2242 ctl_exit_func = ctl_exit_func_;
2243 ctl_register_commands(db_ctl_commands);
2244
2245 cmd_show_tables = cmd_show_tables_;
2246 if (cmd_show_tables) {
2247 static const struct ctl_command_syntax show =
2248 {"show", 0, 0, "", pre_cmd_show, cmd_show, NULL, "", RO};
2249 ctl_register_command(&show);
2250 }
2251 }
2252
2253 /* Returns the text for the database commands usage. */
2254 const char *
2255 ctl_get_db_cmd_usage(void)
2256 {
2257 return "Database commands:\n\
2258 list TBL [REC] list RECord (or all records) in TBL\n\
2259 find TBL CONDITION... list records satisfying CONDITION in TBL\n\
2260 get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\
2261 set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
2262 add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
2263 remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn\n\
2264 clear TBL REC COL clear values from COLumn in RECord in TBL\n\
2265 create TBL COL[:KEY]=VALUE create and initialize new record\n\
2266 destroy TBL REC delete RECord from TBL\n\
2267 wait-until TBL REC [COL[:KEY]=VALUE] wait until condition is true\n\
2268 Potentially unsafe database commands require --force option.\n";
2269 }
2270
2271 const char *
2272 ctl_list_db_tables_usage(void)
2273 {
2274 static struct ds s = DS_EMPTY_INITIALIZER;
2275 if (s.length) {
2276 return ds_cstr(&s);
2277 }
2278
2279 ds_put_cstr(&s, "Database commands may reference a row in each table in the following ways:\n");
2280 for (int i = 0; i < n_classes; i++) {
2281 struct svec options = SVEC_EMPTY_INITIALIZER;
2282
2283 svec_add(&options, "by UUID");
2284 if (idl_classes[i].is_singleton) {
2285 svec_add(&options, "as \".\"");
2286 }
2287
2288 for (int j = 0; j < ARRAY_SIZE(ctl_classes[i].row_ids); j++) {
2289 const struct ctl_row_id *id = &ctl_classes[i].row_ids[j];
2290 if (!id->name_column) {
2291 continue;
2292 }
2293
2294 struct ds o = DS_EMPTY_INITIALIZER;
2295 if (id->uuid_column) {
2296 ds_put_format(&o, "via \"%s\"", id->uuid_column->name);
2297 const struct ovsdb_idl_table_class *referrer
2298 = ovsdb_idl_table_class_from_column(idl_class,
2299 id->uuid_column);
2300 if (referrer != &idl_classes[i]) {
2301 ds_put_format(&o, " of %s", referrer->name);
2302 }
2303 if (id->key) {
2304 ds_put_format(&o, " with matching \"%s:%s\"",
2305 id->name_column->name, id->key);
2306 } else {
2307 ds_put_format(&o, " with matching \"%s\"", id->name_column->name);
2308 }
2309 } else if (id->key) {
2310 ds_put_format(&o, "by \"%s:%s\"", id->name_column->name, id->key);
2311 } else {
2312 ds_put_format(&o, "by \"%s\"", id->name_column->name);
2313 }
2314 svec_add_nocopy(&options, ds_steal_cstr(&o));
2315 }
2316
2317 ds_put_format(&s, " %s:", idl_classes[i].name);
2318 for (int j = 0; j < options.n; j++) {
2319 ds_put_format(&s, "\n %s", options.names[j]);
2320 }
2321 ds_put_char(&s, '\n');
2322 svec_destroy(&options);
2323 }
2324
2325 return ds_cstr(&s);
2326 }
2327
2328 /* Initializes 'ctx' from 'command'. */
2329 void
2330 ctl_context_init_command(struct ctl_context *ctx,
2331 struct ctl_command *command)
2332 {
2333 ctx->argc = command->argc;
2334 ctx->argv = command->argv;
2335 ctx->options = command->options;
2336
2337 ds_swap(&ctx->output, &command->output);
2338 ctx->table = command->table;
2339 ctx->try_again = false;
2340 }
2341
2342 /* Initializes the entire 'ctx'. */
2343 void
2344 ctl_context_init(struct ctl_context *ctx, struct ctl_command *command,
2345 struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn,
2346 struct ovsdb_symbol_table *symtab,
2347 void (*invalidate_cache_cb)(struct ctl_context *))
2348 {
2349 if (command) {
2350 ctl_context_init_command(ctx, command);
2351 }
2352 ctx->idl = idl;
2353 ctx->txn = txn;
2354 ctx->symtab = symtab;
2355 ctx->invalidate_cache_cb = invalidate_cache_cb;
2356 }
2357
2358 /* Completes processing of 'command' within 'ctx'. */
2359 void
2360 ctl_context_done_command(struct ctl_context *ctx,
2361 struct ctl_command *command)
2362 {
2363 ds_swap(&ctx->output, &command->output);
2364 command->table = ctx->table;
2365 }
2366
2367 /* Finishes up with 'ctx'.
2368 *
2369 * If command is nonnull, first calls ctl_context_done_command() to complete
2370 * processing that command within 'ctx'. */
2371 void
2372 ctl_context_done(struct ctl_context *ctx,
2373 struct ctl_command *command)
2374 {
2375 if (command) {
2376 ctl_context_done_command(ctx, command);
2377 }
2378 invalidate_cache(ctx);
2379 }
2380
2381 void ctl_set_column(const char *table_name,
2382 const struct ovsdb_idl_row *row, const char *arg,
2383 struct ovsdb_symbol_table *symtab)
2384 {
2385 const struct ovsdb_idl_table_class *table;
2386
2387 die_if_error(get_table(table_name, &table));
2388 die_if_error(set_column(table, row, arg, symtab));
2389 }