]> git.proxmox.com Git - mirror_ovs.git/blame - ovn/utilities/ovn-sbctl.c
classifier: Simplify minimask_hash().
[mirror_ovs.git] / ovn / utilities / ovn-sbctl.c
CommitLineData
fed00ab1
AW
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 <errno.h>
21#include <float.h>
22#include <getopt.h>
23#include <inttypes.h>
24#include <signal.h>
25#include <stdarg.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include "db-ctl-base.h"
31
32#include "command-line.h"
33#include "compiler.h"
34#include "dynamic-string.h"
35#include "fatal-signal.h"
36#include "json.h"
37#include "ovsdb-data.h"
38#include "ovsdb-idl.h"
39#include "poll-loop.h"
40#include "process.h"
41#include "sset.h"
42#include "shash.h"
43#include "table.h"
44#include "timeval.h"
45#include "util.h"
46#include "openvswitch/vlog.h"
47#include "ovn/lib/ovn-sb-idl.h"
48
49VLOG_DEFINE_THIS_MODULE(sbctl);
50
51struct sbctl_context;
52
53/* --db: The database server to contact. */
54static const char *db;
55
56/* --oneline: Write each command's output as a single line? */
57static bool oneline;
58
59/* --dry-run: Do not commit any changes. */
60static bool dry_run;
61
62/* --timeout: Time to wait for a connection to 'db'. */
63static int timeout;
64
65/* Format for table output. */
66static struct table_style table_style = TABLE_STYLE_DEFAULT;
67
68/* The IDL we're using and the current transaction, if any.
69 * This is for use by sbctl_exit() only, to allow it to clean up.
70 * Other code should use its context arguments. */
71static struct ovsdb_idl *the_idl;
72static struct ovsdb_idl_txn *the_idl_txn;
73OVS_NO_RETURN static void sbctl_exit(int status);
74
75static void sbctl_cmd_init(void);
76OVS_NO_RETURN static void usage(void);
77static void parse_options(int argc, char *argv[], struct shash *local_options);
78static void run_prerequisites(struct ctl_command[], size_t n_commands,
79 struct ovsdb_idl *);
80static void do_sbctl(const char *args, struct ctl_command *, size_t n,
81 struct ovsdb_idl *);
82
83int
84main(int argc, char *argv[])
85{
86 extern struct vlog_module VLM_reconnect;
87 struct ovsdb_idl *idl;
88 struct ctl_command *commands;
89 struct shash local_options;
90 unsigned int seqno;
91 size_t n_commands;
92 char *args;
93
94 set_program_name(argv[0]);
95 fatal_ignore_sigpipe();
96 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
97 vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
98 sbrec_init();
99
100 sbctl_cmd_init();
101
102 /* Log our arguments. This is often valuable for debugging systems. */
103 args = process_escape_args(argv);
104 VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
105
106 /* Parse command line. */
107 shash_init(&local_options);
108 parse_options(argc, argv, &local_options);
109 commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
110 &n_commands);
111
112 if (timeout) {
113 time_alarm(timeout);
114 }
115
116 /* Initialize IDL. */
117 idl = the_idl = ovsdb_idl_create(db, &sbrec_idl_class, false, false);
118 run_prerequisites(commands, n_commands, idl);
119
120 /* Execute the commands.
121 *
122 * 'seqno' is the database sequence number for which we last tried to
123 * execute our transaction. There's no point in trying to commit more than
124 * once for any given sequence number, because if the transaction fails
125 * it's because the database changed and we need to obtain an up-to-date
126 * view of the database before we try the transaction again. */
127 seqno = ovsdb_idl_get_seqno(idl);
128 for (;;) {
129 ovsdb_idl_run(idl);
130 if (!ovsdb_idl_is_alive(idl)) {
131 int retval = ovsdb_idl_get_last_error(idl);
132 ctl_fatal("%s: database connection failed (%s)",
133 db, ovs_retval_to_string(retval));
134 }
135
136 if (seqno != ovsdb_idl_get_seqno(idl)) {
137 seqno = ovsdb_idl_get_seqno(idl);
138 do_sbctl(args, commands, n_commands, idl);
139 }
140
141 if (seqno == ovsdb_idl_get_seqno(idl)) {
142 ovsdb_idl_wait(idl);
143 poll_block();
144 }
145 }
146}
147
148static void
149parse_options(int argc, char *argv[], struct shash *local_options)
150{
151 enum {
152 OPT_DB = UCHAR_MAX + 1,
153 OPT_ONELINE,
154 OPT_NO_SYSLOG,
155 OPT_DRY_RUN,
156 OPT_PEER_CA_CERT,
157 OPT_LOCAL,
158 OPT_COMMANDS,
159 OPT_OPTIONS,
160 VLOG_OPTION_ENUMS,
161 TABLE_OPTION_ENUMS
162 };
163 static const struct option global_long_options[] = {
164 {"db", required_argument, NULL, OPT_DB},
165 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
166 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
167 {"oneline", no_argument, NULL, OPT_ONELINE},
168 {"timeout", required_argument, NULL, 't'},
169 {"help", no_argument, NULL, 'h'},
170 {"commands", no_argument, NULL, OPT_COMMANDS},
171 {"options", no_argument, NULL, OPT_OPTIONS},
172 {"version", no_argument, NULL, 'V'},
173 VLOG_LONG_OPTIONS,
174 TABLE_LONG_OPTIONS,
175 {NULL, 0, NULL, 0},
176 };
177 const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
178 char *tmp, *short_options;
179
180 struct option *options;
181 size_t allocated_options;
182 size_t n_options;
183 size_t i;
184
185 tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
186 short_options = xasprintf("+%s", tmp);
187 free(tmp);
188
189 /* We want to parse both global and command-specific options here, but
190 * getopt_long() isn't too convenient for the job. We copy our global
191 * options into a dynamic array, then append all of the command-specific
192 * options. */
193 options = xmemdup(global_long_options, sizeof global_long_options);
194 allocated_options = ARRAY_SIZE(global_long_options);
195 n_options = n_global_long_options;
196 ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
197 table_style.format = TF_LIST;
198
199 for (;;) {
200 int idx;
201 int c;
202
203 c = getopt_long(argc, argv, short_options, options, &idx);
204 if (c == -1) {
205 break;
206 }
207
208 switch (c) {
209 case OPT_DB:
210 db = optarg;
211 break;
212
213 case OPT_ONELINE:
214 oneline = true;
215 break;
216
217 case OPT_NO_SYSLOG:
218 vlog_set_levels(&VLM_sbctl, VLF_SYSLOG, VLL_WARN);
219 break;
220
221 case OPT_DRY_RUN:
222 dry_run = true;
223 break;
224
225 case OPT_LOCAL:
226 if (shash_find(local_options, options[idx].name)) {
227 ctl_fatal("'%s' option specified multiple times",
228 options[idx].name);
229 }
230 shash_add_nocopy(local_options,
231 xasprintf("--%s", options[idx].name),
232 optarg ? xstrdup(optarg) : NULL);
233 break;
234
235 case 'h':
236 usage();
237
238 case OPT_COMMANDS:
239 ctl_print_commands();
240
241 case OPT_OPTIONS:
242 ctl_print_options(global_long_options);
243
244 case 'V':
245 ovs_print_version(0, 0);
246 printf("DB Schema %s\n", sbrec_get_db_version());
247 exit(EXIT_SUCCESS);
248
249 case 't':
250 timeout = strtoul(optarg, NULL, 10);
251 if (timeout < 0) {
252 ctl_fatal("value %s on -t or --timeout is invalid",
253 optarg);
254 }
255 break;
256
257 VLOG_OPTION_HANDLERS
258 TABLE_OPTION_HANDLERS(&table_style)
259
260 case '?':
261 exit(EXIT_FAILURE);
262
263 default:
264 abort();
265 }
266 }
267 free(short_options);
268
269 if (!db) {
270 db = ctl_default_db();
271 }
272
273 for (i = n_global_long_options; options[i].name; i++) {
274 free(CONST_CAST(char *, options[i].name));
275 }
276 free(options);
277}
278
279static void
280usage(void)
281{
282 printf("\
283%s: ovs-vswitchd management utility\n\
284\n\
285for debugging and testing only, never use it in production\n\
286\n\
287usage: %s [OPTIONS] COMMAND [ARG...]\n\
288\n\
289SouthBound DB commands:\n\
290 show print overview of database contents\n\
291\n\
292Chassis commands:\n\
293 chassis-add CHASSIS ENCAP-TYPE ENCAP-IP create a new chassis named\n\
294 CHASSIS with one encapsulation\n\
295 entry of ENCAP-TYPE and ENCAP-IP\n\
296 chassis-del CHASSIS delete CHASSIS and all of its encaps,\n\
297 and gateway_ports\n\
298\n\
299Port binding commands:\n\
300 lport-bind LPORT CHASSIS bind logical port LPORT to CHASSIS\n\
301 lport-unbind LPORT reset the port binding of logical port LPORT\n\
302\n\
303%s\
304\n\
305Options:\n\
306 --db=DATABASE connect to DATABASE\n\
307 (default: %s)\n\
308 -t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
309 --dry-run do not commit changes to database\n\
310 --oneline print exactly one line of output per command\n",
311 program_name, program_name, ctl_get_db_cmd_usage(), ctl_default_db());
312 vlog_usage();
313 printf("\
314 --no-syslog equivalent to --verbose=sbctl:syslog:warn\n");
315 printf("\n\
316Other options:\n\
317 -h, --help display this help message\n\
318 -V, --version display version information\n");
319 exit(EXIT_SUCCESS);
320}
321
322\f
323/* ovs-sbctl specific context. Inherits the 'struct ctl_context' as base. */
324struct sbctl_context {
325 struct ctl_context base;
326
327 /* A cache of the contents of the database.
328 *
329 * A command that needs to use any of this information must first call
330 * sbctl_context_populate_cache(). A command that changes anything that
331 * could invalidate the cache must either call
332 * sbctl_context_invalidate_cache() or manually update the cache to
333 * maintain its correctness. */
334 bool cache_valid;
335 /* Maps from chassis name to struct sbctl_chassis. */
336 struct shash chassis;
337 /* Maps from lport name to struct sbctl_port_binding. */
338 struct shash port_bindings;
339};
340
341/* Casts 'base' into 'strcut sbctl_context'. */
342static struct sbctl_context *
343sbctl_context_cast(struct ctl_context *base)
344{
345 return CONTAINER_OF(base, struct sbctl_context, base);
346}
347
348struct sbctl_chassis {
349 const struct sbrec_chassis *ch_cfg;
350};
351
352struct sbctl_port_binding {
353 const struct sbrec_port_binding *bd_cfg;
354};
355
356static void
357sbctl_context_invalidate_cache(struct ctl_context *ctx)
358{
359 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
360
361 if (!sbctl_ctx->cache_valid) {
362 return;
363 }
364 sbctl_ctx->cache_valid = false;
365 shash_destroy_free_data(&sbctl_ctx->chassis);
366 shash_destroy_free_data(&sbctl_ctx->port_bindings);
367}
368
369static void
370sbctl_context_populate_cache(struct ctl_context *ctx)
371{
372 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
373 const struct sbrec_chassis *chassis_rec;
374 const struct sbrec_port_binding *port_binding_rec;
375 struct sset chassis, port_bindings;
376
377 if (sbctl_ctx->cache_valid) {
378 /* Cache is already populated. */
379 return;
380 }
381 sbctl_ctx->cache_valid = true;
382 shash_init(&sbctl_ctx->chassis);
383 shash_init(&sbctl_ctx->port_bindings);
384 sset_init(&chassis);
385 SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->idl) {
386 struct sbctl_chassis *ch;
387
388 if (!sset_add(&chassis, chassis_rec->name)) {
389 VLOG_WARN("database contains duplicate chassis name (%s)",
390 chassis_rec->name);
391 continue;
392 }
393
394 ch = xmalloc(sizeof *ch);
395 ch->ch_cfg = chassis_rec;
396 shash_add(&sbctl_ctx->chassis, chassis_rec->name, ch);
397 }
398 sset_destroy(&chassis);
399
400 sset_init(&port_bindings);
401 SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->idl) {
402 struct sbctl_port_binding *bd;
403
404 if (!sset_add(&port_bindings, port_binding_rec->logical_port)) {
405 VLOG_WARN("database contains duplicate port binding for logical "
406 "port (%s)",
407 port_binding_rec->logical_port);
408 continue;
409 }
410
411 bd = xmalloc(sizeof *bd);
412 bd->bd_cfg = port_binding_rec;
413 shash_add(&sbctl_ctx->port_bindings, port_binding_rec->logical_port,
414 bd);
415 }
416 sset_destroy(&port_bindings);
417}
418
419static void
420check_conflicts(struct sbctl_context *sbctl_ctx, const char *name,
421 char *msg)
422{
423 if (shash_find(&sbctl_ctx->chassis, name)) {
424 ctl_fatal("%s because a chassis named %s already exists",
425 msg, name);
426 }
427 free(msg);
428}
429
430static struct sbctl_chassis *
431find_chassis(struct sbctl_context *sbctl_ctx, const char *name,
432 bool must_exist)
433{
434 struct sbctl_chassis *sbctl_ch;
435
436 ovs_assert(sbctl_ctx->cache_valid);
437
438 sbctl_ch = shash_find_data(&sbctl_ctx->chassis, name);
439 if (must_exist && !sbctl_ch) {
440 ctl_fatal("no chassis named %s", name);
441 }
442
443 return sbctl_ch;
444}
445
446static struct sbctl_port_binding *
447find_port_binding(struct sbctl_context *sbctl_ctx, const char *name,
448 bool must_exist)
449{
450 struct sbctl_port_binding *bd;
451
452 ovs_assert(sbctl_ctx->cache_valid);
453
454 bd = shash_find_data(&sbctl_ctx->port_bindings, name);
455 if (must_exist && !bd) {
456 ctl_fatal("no port named %s", name);
457 }
458
459 return bd;
460}
461
462static void
463pre_get_info(struct ctl_context *ctx)
464{
465 ovsdb_idl_add_column(ctx->idl, &sbrec_chassis_col_name);
466 ovsdb_idl_add_column(ctx->idl, &sbrec_chassis_col_encaps);
467
468 ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_type);
469 ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_ip);
470
471 ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_logical_port);
472 ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
473}
474
475static struct cmd_show_table cmd_show_tables[] = {
476 {&sbrec_table_chassis,
477 &sbrec_chassis_col_name,
478 {&sbrec_chassis_col_encaps,
479 NULL,
480 NULL}},
481
482 {&sbrec_table_encap,
483 &sbrec_encap_col_type,
484 {&sbrec_encap_col_ip,
485 &sbrec_encap_col_options,
486 NULL}},
487
488 {NULL, NULL, {NULL, NULL, NULL}},
489};
490
491static void
492cmd_chassis_add(struct ctl_context *ctx)
493{
494 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
495 struct sbrec_chassis *ch;
496 struct sbrec_encap *encap;
497 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
498 const char *ch_name, *encap_type, *encap_ip;
499
500 ch_name = ctx->argv[1];
501 encap_type = ctx->argv[2];
502 encap_ip = ctx->argv[3];
503
504 sbctl_context_populate_cache(ctx);
505 if (may_exist) {
506 struct sbctl_chassis *sbctl_ch;
507
508 sbctl_ch = find_chassis(sbctl_ctx, ch_name, false);
509 if (sbctl_ch) {
510 return;
511 }
512 }
513 check_conflicts(sbctl_ctx, ch_name,
514 xasprintf("cannot create a chassis named %s", ch_name));
515 ch = sbrec_chassis_insert(ctx->txn);
516 sbrec_chassis_set_name(ch, ch_name);
517 encap = sbrec_encap_insert(ctx->txn);
518 sbrec_encap_set_type(encap, encap_type);
519 sbrec_encap_set_ip(encap, encap_ip);
520 sbrec_chassis_set_encaps(ch, &encap, 1);
521 sbctl_context_invalidate_cache(ctx);
522}
523
524static void
525cmd_chassis_del(struct ctl_context *ctx)
526{
527 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
528 bool must_exist = !shash_find(&ctx->options, "--if-exists");
529 struct sbctl_chassis *sbctl_ch;
530
531 sbctl_context_populate_cache(ctx);
532 sbctl_ch = find_chassis(sbctl_ctx, ctx->argv[1], must_exist);
533 if (sbctl_ch) {
534 if (sbctl_ch->ch_cfg) {
535 sbrec_chassis_delete(sbctl_ch->ch_cfg);
536 }
537 shash_find_and_delete(&sbctl_ctx->chassis, ctx->argv[1]);
538 free(sbctl_ch);
539 }
540}
541
542static void
543cmd_lport_bind(struct ctl_context *ctx)
544{
545 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
546 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
547 struct sbctl_chassis *sbctl_ch;
548 struct sbctl_port_binding *sbctl_bd;
549 char *lport_name, *ch_name;
550
551 /* port_binding must exist, chassis must exist! */
552 lport_name = ctx->argv[1];
553 ch_name = ctx->argv[2];
554
555 sbctl_context_populate_cache(ctx);
556 sbctl_bd = find_port_binding(sbctl_ctx, lport_name, true);
557 sbctl_ch = find_chassis(sbctl_ctx, ch_name, true);
558
559 if (sbctl_bd->bd_cfg->chassis) {
560 if (may_exist && sbctl_bd->bd_cfg->chassis == sbctl_ch->ch_cfg) {
561 return;
562 } else {
563 ctl_fatal("lport (%s) has already been binded to chassis (%s)",
564 lport_name, sbctl_bd->bd_cfg->chassis->name);
565 }
566 }
567 sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, sbctl_ch->ch_cfg);
568 sbctl_context_invalidate_cache(ctx);
569}
570
571static void
572cmd_lport_unbind(struct ctl_context *ctx)
573{
574 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
575 bool must_exist = !shash_find(&ctx->options, "--if-exists");
576 struct sbctl_port_binding *sbctl_bd;
577 char *lport_name;
578
579 lport_name = ctx->argv[1];
580 sbctl_context_populate_cache(ctx);
581 sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist);
582 if (sbctl_bd) {
583 sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, NULL);
584 }
585}
586
587\f
588static const struct ctl_table_class tables[] = {
589 {&sbrec_table_chassis,
590 {{&sbrec_table_chassis, &sbrec_chassis_col_name, NULL},
591 {NULL, NULL, NULL}}},
592
593 {&sbrec_table_encap,
594 {{NULL, NULL, NULL},
595 {NULL, NULL, NULL}}},
596
597 {&sbrec_table_logical_flow,
598 {{&sbrec_table_logical_flow, NULL,
599 &sbrec_logical_flow_col_logical_datapath},
600 {NULL, NULL, NULL}}},
601
602 {&sbrec_table_multicast_group,
603 {{NULL, NULL, NULL},
604 {NULL, NULL, NULL}}},
605
606 {&sbrec_table_datapath_binding,
607 {{NULL, NULL, NULL},
608 {NULL, NULL, NULL}}},
609
610 {&sbrec_table_port_binding,
611 {{&sbrec_table_port_binding, &sbrec_port_binding_col_logical_port, NULL},
612 {NULL, NULL, NULL}}},
613
614 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
615};
616
617\f
618static void
619sbctl_context_init_command(struct sbctl_context *sbctl_ctx,
620 struct ctl_command *command)
621{
622 ctl_context_init_command(&sbctl_ctx->base, command);
623}
624
625static void
626sbctl_context_init(struct sbctl_context *sbctl_ctx,
627 struct ctl_command *command, struct ovsdb_idl *idl,
628 struct ovsdb_idl_txn *txn,
629 struct ovsdb_symbol_table *symtab)
630{
631 ctl_context_init(&sbctl_ctx->base, command, idl, txn, symtab,
632 sbctl_context_invalidate_cache);
633 sbctl_ctx->cache_valid = false;
634}
635
636static void
637sbctl_context_done_command(struct sbctl_context *sbctl_ctx,
638 struct ctl_command *command)
639{
640 ctl_context_done_command(&sbctl_ctx->base, command);
641}
642
643static void
644sbctl_context_done(struct sbctl_context *sbctl_ctx,
645 struct ctl_command *command)
646{
647 ctl_context_done(&sbctl_ctx->base, command);
648}
649
650static void
651run_prerequisites(struct ctl_command *commands, size_t n_commands,
652 struct ovsdb_idl *idl)
653{
654 struct ctl_command *c;
655
656 for (c = commands; c < &commands[n_commands]; c++) {
657 if (c->syntax->prerequisites) {
658 struct sbctl_context sbctl_ctx;
659
660 ds_init(&c->output);
661 c->table = NULL;
662
663 sbctl_context_init(&sbctl_ctx, c, idl, NULL, NULL);
664 (c->syntax->prerequisites)(&sbctl_ctx.base);
665 sbctl_context_done(&sbctl_ctx, c);
666
667 ovs_assert(!c->output.string);
668 ovs_assert(!c->table);
669 }
670 }
671}
672
673static void
674do_sbctl(const char *args, struct ctl_command *commands, size_t n_commands,
675 struct ovsdb_idl *idl)
676{
677 struct ovsdb_idl_txn *txn;
678 enum ovsdb_idl_txn_status status;
679 struct ovsdb_symbol_table *symtab;
680 struct sbctl_context sbctl_ctx;
681 struct ctl_command *c;
682 struct shash_node *node;
683 char *error = NULL;
684
685 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
686 if (dry_run) {
687 ovsdb_idl_txn_set_dry_run(txn);
688 }
689
690 ovsdb_idl_txn_add_comment(txn, "ovs-sbctl: %s", args);
691
692 symtab = ovsdb_symbol_table_create();
693 for (c = commands; c < &commands[n_commands]; c++) {
694 ds_init(&c->output);
695 c->table = NULL;
696 }
697 sbctl_context_init(&sbctl_ctx, NULL, idl, txn, symtab);
698 for (c = commands; c < &commands[n_commands]; c++) {
699 sbctl_context_init_command(&sbctl_ctx, c);
700 if (c->syntax->run) {
701 (c->syntax->run)(&sbctl_ctx.base);
702 }
703 sbctl_context_done_command(&sbctl_ctx, c);
704
705 if (sbctl_ctx.base.try_again) {
706 sbctl_context_done(&sbctl_ctx, NULL);
707 goto try_again;
708 }
709 }
710 sbctl_context_done(&sbctl_ctx, NULL);
711
712 SHASH_FOR_EACH (node, &symtab->sh) {
713 struct ovsdb_symbol *symbol = node->data;
714 if (!symbol->created) {
715 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
716 "with \"-- --id=%s create ...\")",
717 node->name, node->name);
718 }
719 if (!symbol->strong_ref) {
720 if (!symbol->weak_ref) {
721 VLOG_WARN("row id \"%s\" was created but no reference to it "
722 "was inserted, so it will not actually appear in "
723 "the database", node->name);
724 } else {
725 VLOG_WARN("row id \"%s\" was created but only a weak "
726 "reference to it was inserted, so it will not "
727 "actually appear in the database", node->name);
728 }
729 }
730 }
731
732 status = ovsdb_idl_txn_commit_block(txn);
733 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
734 for (c = commands; c < &commands[n_commands]; c++) {
735 if (c->syntax->postprocess) {
736 sbctl_context_init(&sbctl_ctx, c, idl, txn, symtab);
737 (c->syntax->postprocess)(&sbctl_ctx.base);
738 sbctl_context_done(&sbctl_ctx, c);
739 }
740 }
741 }
742 error = xstrdup(ovsdb_idl_txn_get_error(txn));
743
744 switch (status) {
745 case TXN_UNCOMMITTED:
746 case TXN_INCOMPLETE:
747 OVS_NOT_REACHED();
748
749 case TXN_ABORTED:
750 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
751 ctl_fatal("transaction aborted");
752
753 case TXN_UNCHANGED:
754 case TXN_SUCCESS:
755 break;
756
757 case TXN_TRY_AGAIN:
758 goto try_again;
759
760 case TXN_ERROR:
761 ctl_fatal("transaction error: %s", error);
762
763 case TXN_NOT_LOCKED:
764 /* Should not happen--we never call ovsdb_idl_set_lock(). */
765 ctl_fatal("database not locked");
766
767 default:
768 OVS_NOT_REACHED();
769 }
770 free(error);
771
772 ovsdb_symbol_table_destroy(symtab);
773
774 for (c = commands; c < &commands[n_commands]; c++) {
775 struct ds *ds = &c->output;
776
777 if (c->table) {
778 table_print(c->table, &table_style);
779 } else if (oneline) {
780 size_t j;
781
782 ds_chomp(ds, '\n');
783 for (j = 0; j < ds->length; j++) {
784 int ch = ds->string[j];
785 switch (ch) {
786 case '\n':
787 fputs("\\n", stdout);
788 break;
789
790 case '\\':
791 fputs("\\\\", stdout);
792 break;
793
794 default:
795 putchar(ch);
796 }
797 }
798 putchar('\n');
799 } else {
800 fputs(ds_cstr(ds), stdout);
801 }
802 ds_destroy(&c->output);
803 table_destroy(c->table);
804 free(c->table);
805
806 shash_destroy_free_data(&c->options);
807 }
808 free(commands);
809 ovsdb_idl_txn_destroy(txn);
810 ovsdb_idl_destroy(idl);
811
812 exit(EXIT_SUCCESS);
813
814try_again:
815 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
816 * resources and return so that the caller can try again. */
817 if (txn) {
818 ovsdb_idl_txn_abort(txn);
819 ovsdb_idl_txn_destroy(txn);
820 the_idl_txn = NULL;
821 }
822 ovsdb_symbol_table_destroy(symtab);
823 for (c = commands; c < &commands[n_commands]; c++) {
824 ds_destroy(&c->output);
825 table_destroy(c->table);
826 free(c->table);
827 }
828 free(error);
829}
830
831/* Frees the current transaction and the underlying IDL and then calls
832 * exit(status).
833 *
834 * Freeing the transaction and the IDL is not strictly necessary, but it makes
835 * for a clean memory leak report from valgrind in the normal case. That makes
836 * it easier to notice real memory leaks. */
837static void
838sbctl_exit(int status)
839{
840 if (the_idl_txn) {
841 ovsdb_idl_txn_abort(the_idl_txn);
842 ovsdb_idl_txn_destroy(the_idl_txn);
843 }
844 ovsdb_idl_destroy(the_idl);
845 exit(status);
846}
847
848static const struct ctl_command_syntax sbctl_commands[] = {
849 /* Chassis commands. */
850 {"chassis-add", 3, 3, "CHASSIS ENCAP-TYPE ENCAP-IP", pre_get_info,
851 cmd_chassis_add, NULL, "--may-exist", RW},
852 {"chassis-del", 1, 1, "CHASSIS", pre_get_info, cmd_chassis_del, NULL,
853 "--if-exists", RW},
854
855 /* Port binding commands. */
856 {"lport-bind", 2, 2, "LPORT CHASSIS", pre_get_info, cmd_lport_bind, NULL,
857 "--may-exist", RW},
858 {"lport-unbind", 1, 1, "LPORT", pre_get_info, cmd_lport_unbind, NULL,
859 "--if-exists", RW},
860
861 /* SSL commands (To Be Added). */
862
863 {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
864};
865
866/* Registers sbctl and common db commands. */
867static void
868sbctl_cmd_init(void)
869{
870 ctl_init(tables, cmd_show_tables, sbctl_exit);
871 ctl_register_commands(sbctl_commands);
872}