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