]> git.proxmox.com Git - mirror_ovs.git/blame - ovn/ovn-nbctl.c
Merge "master" into "ovn".
[mirror_ovs.git] / ovn / ovn-nbctl.c
CommitLineData
a416ff28
RB
1/*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at:
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15#include <config.h>
16
17#include <getopt.h>
bf5fa52a 18#include <inttypes.h>
a416ff28
RB
19#include <stdlib.h>
20#include <stdio.h>
21
22#include "command-line.h"
23#include "dirs.h"
24#include "fatal-signal.h"
e3df8838 25#include "ovn/lib/ovn-nb-idl.h"
a416ff28 26#include "poll-loop.h"
afc9da0b 27#include "process.h"
a416ff28
RB
28#include "stream.h"
29#include "stream-ssl.h"
30#include "util.h"
31#include "openvswitch/vlog.h"
32
33VLOG_DEFINE_THIS_MODULE(ovn_nbctl);
34
35struct nbctl_context {
36 struct ovsdb_idl *idl;
37 struct ovsdb_idl_txn *txn;
38};
39
40static const char *db;
41
42static const char *default_db(void);
43
44static void
45usage(void)
46{
47 printf("\
48%s: OVN northbound DB management utility\n\
49usage: %s [OPTIONS] COMMAND [ARG...]\n\
50\n\
907a0edf
JP
51General commands:\n\
52 show print overview of database contents\n\
6cfe8161 53 show LSWITCH print overview of database contents for LSWITCH\n\
907a0edf 54\n\
a367622a
JP
55Logical switch commands:\n\
56 lswitch-add [LSWITCH] create a logical switch named LSWITCH\n\
57 lswitch-del LSWITCH delete LSWITCH and all its ports\n\
58 lswitch-list print the names of all logical switches\n\
59 lswitch-set-external-id LSWITCH KEY [VALUE]\n\
60 set or delete an external-id on LSWITCH\n\
61 lswitch-get-external-id LSWITCH [KEY]\n\
62 list one or all external-ids on LSWITCH\n\
a416ff28 63\n\
a367622a
JP
64Logical port commands:\n\
65 lport-add LSWITCH LPORT add logical port LPORT on LSWITCH\n\
bf5fa52a
RB
66 lport-add LSWITCH LPORT PARENT TAG\n\
67 add logical port LPORT on LSWITCH with PARENT\n\
68 on TAG\n\
a367622a
JP
69 lport-del LPORT delete LPORT from its attached switch\n\
70 lport-list LSWITCH print the names of all logical ports on LSWITCH\n\
bf5fa52a
RB
71 lport-get-parent LPORT get the parent of LPORT if set\n\
72 lport-get-tag LPORT get the LPORT's tag if set\n\
a367622a
JP
73 lport-set-external-id LPORT KEY [VALUE]\n\
74 set or delete an external-id on LPORT\n\
75 lport-get-external-id LPORT [KEY]\n\
76 list one or all external-ids on LPORT\n\
2de82d90
BP
77 lport-set-macs LPORT [MAC]...\n\
78 set MAC addresses for LPORT.\n\
a367622a 79 lport-get-macs LPORT get a list of MAC addresses on LPORT\n\
92207865
BP
80 lport-set-port-security LPORT [ADDRS]...\n\
81 set port security addresses for LPORT.\n\
82 lport-get-port-security LPORT get LPORT's port security addresses\n\
a367622a 83 lport-get-up LPORT get state of LPORT ('up' or 'down')\n\
a416ff28
RB
84\n\
85Options:\n\
86 --db=DATABASE connect to DATABASE\n\
87 (default: %s)\n\
88 -h, --help display this help message\n\
89 -o, --options list available options\n\
90 -V, --version display version information\n\
91", program_name, program_name, default_db());
92 vlog_usage();
93 stream_usage("database", true, true, false);
94}
95\f
96static const struct nbrec_logical_switch *
97lswitch_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
98{
99 const struct nbrec_logical_switch *lswitch = NULL;
100 bool is_uuid = false;
101 bool duplicate = false;
102 struct uuid lswitch_uuid;
103
104 if (uuid_from_string(&lswitch_uuid, id)) {
105 is_uuid = true;
106 lswitch = nbrec_logical_switch_get_for_uuid(nb_ctx->idl,
107 &lswitch_uuid);
c1f4da63
RB
108 }
109
110 if (!lswitch) {
a416ff28
RB
111 const struct nbrec_logical_switch *iter;
112
113 NBREC_LOGICAL_SWITCH_FOR_EACH(iter, nb_ctx->idl) {
114 if (strcmp(iter->name, id)) {
115 continue;
116 }
117 if (lswitch) {
118 VLOG_WARN("There is more than one logical switch named '%s'. "
119 "Use a UUID.", id);
120 lswitch = NULL;
121 duplicate = true;
122 break;
123 }
124 lswitch = iter;
125 }
126 }
127
128 if (!lswitch && !duplicate) {
129 VLOG_WARN("lswitch not found for %s: '%s'",
130 is_uuid ? "UUID" : "name", id);
131 }
132
133 return lswitch;
134}
135
907a0edf
JP
136static void
137print_lswitch(const struct nbctl_context *nb_ctx,
138 const struct nbrec_logical_switch *lswitch)
139{
140 const struct nbrec_logical_port *lport;
141
142 printf(" lswitch "UUID_FMT" (%s)\n",
143 UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
144
145 NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) {
146 int i;
147
148 if (lport->lswitch == lswitch) {
149 printf(" lport %s\n", lport->name);
150 if (lport->parent_name && lport->n_tag) {
151 printf(" parent: %s, tag:%"PRIu64"\n",
152 lport->parent_name, lport->tag[0]);
153 }
154 if (lport->n_macs) {
155 printf(" macs:");
156 for (i=0; i < lport->n_macs; i++) {
157 printf(" %s", lport->macs[i]);
158 }
159 printf("\n");
160 }
161 }
162 }
163}
164
165static void
166do_show(struct ovs_cmdl_context *ctx)
167{
168 struct nbctl_context *nb_ctx = ctx->pvt;
169 const struct nbrec_logical_switch *lswitch;
170
171 if (ctx->argc == 2) {
172 lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
173 if (lswitch) {
174 print_lswitch(nb_ctx, lswitch);
175 }
176 } else {
177 NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
178 print_lswitch(nb_ctx, lswitch);
179 }
180 }
181}
182
a416ff28
RB
183static void
184do_lswitch_add(struct ovs_cmdl_context *ctx)
185{
186 struct nbctl_context *nb_ctx = ctx->pvt;
187 struct nbrec_logical_switch *lswitch;
188
189 lswitch = nbrec_logical_switch_insert(nb_ctx->txn);
190 if (ctx->argc == 2) {
191 nbrec_logical_switch_set_name(lswitch, ctx->argv[1]);
192 }
193}
194
195static void
196do_lswitch_del(struct ovs_cmdl_context *ctx)
197{
198 struct nbctl_context *nb_ctx = ctx->pvt;
199 const char *id = ctx->argv[1];
200 const struct nbrec_logical_switch *lswitch;
201
202 lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
203 if (!lswitch) {
204 return;
205 }
206
207 nbrec_logical_switch_delete(lswitch);
208}
209
210static void
211do_lswitch_list(struct ovs_cmdl_context *ctx)
212{
213 struct nbctl_context *nb_ctx = ctx->pvt;
214 const struct nbrec_logical_switch *lswitch;
215
216 NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
217 printf(UUID_FMT " (%s)\n",
218 UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
219 }
220}
221
222static void
223do_lswitch_set_external_id(struct ovs_cmdl_context *ctx)
224{
225 struct nbctl_context *nb_ctx = ctx->pvt;
226 const char *id = ctx->argv[1];
227 const struct nbrec_logical_switch *lswitch;
228 struct smap new_external_ids;
229
230 lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
231 if (!lswitch) {
232 return;
233 }
234
235 smap_init(&new_external_ids);
236 smap_clone(&new_external_ids, &lswitch->external_ids);
237 if (ctx->argc == 4) {
238 smap_replace(&new_external_ids, ctx->argv[2], ctx->argv[3]);
239 } else {
240 smap_remove(&new_external_ids, ctx->argv[2]);
241 }
242 nbrec_logical_switch_set_external_ids(lswitch, &new_external_ids);
243 smap_destroy(&new_external_ids);
244}
245
246static void
247do_lswitch_get_external_id(struct ovs_cmdl_context *ctx)
248{
249 struct nbctl_context *nb_ctx = ctx->pvt;
250 const char *id = ctx->argv[1];
251 const struct nbrec_logical_switch *lswitch;
252
253 lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
254 if (!lswitch) {
255 return;
256 }
257
258 if (ctx->argc == 3) {
259 const char *key = ctx->argv[2];
260 const char *value;
261
262 /* List one external ID */
263
264 value = smap_get(&lswitch->external_ids, key);
ee98038f 265 if (value) {
a416ff28 266 printf("%s\n", value);
a416ff28
RB
267 }
268 } else {
269 struct smap_node *node;
270
271 /* List all external IDs */
272
273 SMAP_FOR_EACH(node, &lswitch->external_ids) {
274 printf("%s=%s\n", node->key, node->value);
275 }
276 }
277}
278\f
279static const struct nbrec_logical_port *
280lport_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
281{
282 const struct nbrec_logical_port *lport = NULL;
283 bool is_uuid = false;
284 struct uuid lport_uuid;
285
286 if (uuid_from_string(&lport_uuid, id)) {
287 is_uuid = true;
288 lport = nbrec_logical_port_get_for_uuid(nb_ctx->idl, &lport_uuid);
c1f4da63
RB
289 }
290
291 if (!lport) {
a416ff28
RB
292 NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) {
293 if (!strcmp(lport->name, id)) {
294 break;
295 }
296 }
297 }
298
299 if (!lport) {
300 VLOG_WARN("lport not found for %s: '%s'",
301 is_uuid ? "UUID" : "name", id);
302 }
303
304 return lport;
305}
306
307static void
308do_lport_add(struct ovs_cmdl_context *ctx)
309{
310 struct nbctl_context *nb_ctx = ctx->pvt;
311 struct nbrec_logical_port *lport;
312 const struct nbrec_logical_switch *lswitch;
bf5fa52a 313 int64_t tag;
a416ff28 314
c8453791 315 lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
a416ff28
RB
316 if (!lswitch) {
317 return;
318 }
319
bf5fa52a
RB
320 if (ctx->argc != 3 && ctx->argc != 5) {
321 /* If a parent_name is specififed, a tag must be specified as well. */
322 VLOG_WARN("Invalid arguments to lport-add.");
323 return;
324 }
325
326 if (ctx->argc == 5) {
327 /* Validate tag. */
328 if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag) || tag < 0 || tag > 4095) {
329 VLOG_WARN("Invalid tag '%s'", ctx->argv[4]);
330 return;
331 }
332 }
333
334 /* Finally, create the transaction. */
a416ff28 335 lport = nbrec_logical_port_insert(nb_ctx->txn);
c8453791 336 nbrec_logical_port_set_name(lport, ctx->argv[2]);
a416ff28 337 nbrec_logical_port_set_lswitch(lport, lswitch);
bf5fa52a
RB
338 if (ctx->argc == 5) {
339 nbrec_logical_port_set_parent_name(lport, ctx->argv[3]);
340 nbrec_logical_port_set_tag(lport, &tag, 1);
341 }
a416ff28
RB
342}
343
344static void
345do_lport_del(struct ovs_cmdl_context *ctx)
346{
347 struct nbctl_context *nb_ctx = ctx->pvt;
348 const struct nbrec_logical_port *lport;
349
350 lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
351 if (!lport) {
352 return;
353 }
354
355 nbrec_logical_port_delete(lport);
356}
357
358static bool
359is_lswitch(const struct nbrec_logical_switch *lswitch,
360 struct uuid *lswitch_uuid, const char *name)
361{
362 if (lswitch_uuid) {
363 return uuid_equals(lswitch_uuid, &lswitch->header_.uuid);
364 } else {
365 return !strcmp(lswitch->name, name);
366 }
367}
368
369
370static void
371do_lport_list(struct ovs_cmdl_context *ctx)
372{
373 struct nbctl_context *nb_ctx = ctx->pvt;
374 const char *id = ctx->argv[1];
375 const struct nbrec_logical_port *lport;
376 bool is_uuid = false;
377 struct uuid lswitch_uuid;
378
379 if (uuid_from_string(&lswitch_uuid, id)) {
380 is_uuid = true;
381 }
382
383 NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) {
384 bool match;
385 if (is_uuid) {
386 match = is_lswitch(lport->lswitch, &lswitch_uuid, NULL);
387 } else {
388 match = is_lswitch(lport->lswitch, NULL, id);
389 }
390 if (!match) {
391 continue;
392 }
393 printf(UUID_FMT " (%s)\n",
394 UUID_ARGS(&lport->header_.uuid), lport->name);
395 }
396}
397
bf5fa52a
RB
398static void
399do_lport_get_parent(struct ovs_cmdl_context *ctx)
400{
401 struct nbctl_context *nb_ctx = ctx->pvt;
402 const struct nbrec_logical_port *lport;
403
404 lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
405 if (!lport) {
406 return;
407 }
408
409 if (lport->parent_name) {
410 printf("%s\n", lport->parent_name);
411 }
412}
413
414static void
415do_lport_get_tag(struct ovs_cmdl_context *ctx)
416{
417 struct nbctl_context *nb_ctx = ctx->pvt;
418 const struct nbrec_logical_port *lport;
419
420 lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
421 if (!lport) {
422 return;
423 }
424
425 if (lport->n_tag > 0) {
426 printf("%"PRId64"\n", lport->tag[0]);
427 }
428}
429
a416ff28
RB
430static void
431do_lport_set_external_id(struct ovs_cmdl_context *ctx)
432{
433 struct nbctl_context *nb_ctx = ctx->pvt;
434 const char *id = ctx->argv[1];
435 const struct nbrec_logical_port *lport;
436 struct smap new_external_ids;
437
438 lport = lport_by_name_or_uuid(nb_ctx, id);
439 if (!lport) {
440 return;
441 }
442
443 smap_init(&new_external_ids);
444 smap_clone(&new_external_ids, &lport->external_ids);
445 if (ctx->argc == 4) {
446 smap_replace(&new_external_ids, ctx->argv[2], ctx->argv[3]);
447 } else {
448 smap_remove(&new_external_ids, ctx->argv[2]);
449 }
450 nbrec_logical_port_set_external_ids(lport, &new_external_ids);
451 smap_destroy(&new_external_ids);
452}
453
454static void
455do_lport_get_external_id(struct ovs_cmdl_context *ctx)
456{
457 struct nbctl_context *nb_ctx = ctx->pvt;
458 const char *id = ctx->argv[1];
459 const struct nbrec_logical_port *lport;
460
461 lport = lport_by_name_or_uuid(nb_ctx, id);
462 if (!lport) {
463 return;
464 }
465
466 if (ctx->argc == 3) {
467 const char *key = ctx->argv[2];
468 const char *value;
469
470 /* List one external ID */
471
472 value = smap_get(&lport->external_ids, key);
ee98038f 473 if (value) {
a416ff28 474 printf("%s\n", value);
a416ff28
RB
475 }
476 } else {
477 struct smap_node *node;
478
479 /* List all external IDs */
480
481 SMAP_FOR_EACH(node, &lport->external_ids) {
482 printf("%s=%s\n", node->key, node->value);
483 }
484 }
485}
486
487static void
488do_lport_set_macs(struct ovs_cmdl_context *ctx)
489{
490 struct nbctl_context *nb_ctx = ctx->pvt;
491 const char *id = ctx->argv[1];
492 const struct nbrec_logical_port *lport;
493
494 lport = lport_by_name_or_uuid(nb_ctx, id);
495 if (!lport) {
496 return;
497 }
498
499 nbrec_logical_port_set_macs(lport,
500 (const char **) ctx->argv + 2, ctx->argc - 2);
501}
502
503static void
504do_lport_get_macs(struct ovs_cmdl_context *ctx)
505{
506 struct nbctl_context *nb_ctx = ctx->pvt;
507 const char *id = ctx->argv[1];
508 const struct nbrec_logical_port *lport;
509 size_t i;
510
511 lport = lport_by_name_or_uuid(nb_ctx, id);
512 if (!lport) {
513 return;
514 }
515
516 for (i = 0; i < lport->n_macs; i++) {
517 printf("%s\n", lport->macs[i]);
518 }
519}
65fb6826 520
92207865
BP
521static void
522do_lport_set_port_security(struct ovs_cmdl_context *ctx)
523{
524 struct nbctl_context *nb_ctx = ctx->pvt;
525 const char *id = ctx->argv[1];
526 const struct nbrec_logical_port *lport;
527
528 lport = lport_by_name_or_uuid(nb_ctx, id);
529 if (!lport) {
530 return;
531 }
532
533 nbrec_logical_port_set_port_security(lport,
534 (const char **) ctx->argv + 2, ctx->argc - 2);
535}
536
537static void
538do_lport_get_port_security(struct ovs_cmdl_context *ctx)
539{
540 struct nbctl_context *nb_ctx = ctx->pvt;
541 const char *id = ctx->argv[1];
542 const struct nbrec_logical_port *lport;
543 size_t i;
544
545 lport = lport_by_name_or_uuid(nb_ctx, id);
546 if (!lport) {
547 return;
548 }
549
550 for (i = 0; i < lport->n_port_security; i++) {
551 printf("%s\n", lport->port_security[i]);
552 }
553}
554
65fb6826
RB
555static void
556do_lport_get_up(struct ovs_cmdl_context *ctx)
557{
558 struct nbctl_context *nb_ctx = ctx->pvt;
559 const char *id = ctx->argv[1];
560 const struct nbrec_logical_port *lport;
561
562 lport = lport_by_name_or_uuid(nb_ctx, id);
563 if (!lport) {
564 return;
565 }
566
567 printf("%s\n", (lport->up && *lport->up) ? "up" : "down");
568}
a416ff28
RB
569\f
570static void
571parse_options(int argc, char *argv[])
572{
573 enum {
574 VLOG_OPTION_ENUMS,
575 };
576 static const struct option long_options[] = {
a7ac550b 577 {"db", required_argument, NULL, 'd'},
a416ff28
RB
578 {"help", no_argument, NULL, 'h'},
579 {"options", no_argument, NULL, 'o'},
580 {"version", no_argument, NULL, 'V'},
581 VLOG_LONG_OPTIONS,
582 STREAM_SSL_LONG_OPTIONS,
583 {NULL, 0, NULL, 0},
584 };
585 char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
586
587 for (;;) {
588 int c;
589
590 c = getopt_long(argc, argv, short_options, long_options, NULL);
591 if (c == -1) {
592 break;
593 }
594
595 switch (c) {
596 VLOG_OPTION_HANDLERS;
597 STREAM_SSL_OPTION_HANDLERS;
598
599 case 'd':
600 db = optarg;
601 break;
602
603 case 'h':
604 usage();
605 exit(EXIT_SUCCESS);
606
607 case 'o':
608 ovs_cmdl_print_options(long_options);
609 exit(EXIT_SUCCESS);
610
611 case 'V':
612 ovs_print_version(0, 0);
613 exit(EXIT_SUCCESS);
614
615 default:
616 break;
617 }
618 }
619
620 if (!db) {
621 db = default_db();
622 }
623
624 free(short_options);
625}
626
627static const struct ovs_cmdl_command all_commands[] = {
907a0edf
JP
628 {
629 .name = "show",
630 .usage = "[LSWITCH]",
631 .min_args = 0,
632 .max_args = 1,
633 .handler = do_show,
634 },
a416ff28
RB
635 {
636 .name = "lswitch-add",
a367622a 637 .usage = "[LSWITCH]",
a416ff28
RB
638 .min_args = 0,
639 .max_args = 1,
640 .handler = do_lswitch_add,
641 },
642 {
643 .name = "lswitch-del",
a367622a 644 .usage = "LSWITCH",
a416ff28
RB
645 .min_args = 1,
646 .max_args = 1,
647 .handler = do_lswitch_del,
648 },
649 {
650 .name = "lswitch-list",
651 .usage = "",
652 .min_args = 0,
653 .max_args = 0,
654 .handler = do_lswitch_list,
655 },
656 {
657 .name = "lswitch-set-external-id",
a367622a 658 .usage = "LSWITCH KEY [VALUE]",
a416ff28
RB
659 .min_args = 2,
660 .max_args = 3,
661 .handler = do_lswitch_set_external_id,
662 },
663 {
664 .name = "lswitch-get-external-id",
a367622a 665 .usage = "LSWITCH [KEY]",
a416ff28
RB
666 .min_args = 1,
667 .max_args = 2,
668 .handler = do_lswitch_get_external_id,
669 },
670 {
671 .name = "lport-add",
bf5fa52a 672 .usage = "LSWITCH LPORT [PARENT] [TAG]",
a416ff28 673 .min_args = 2,
bf5fa52a 674 .max_args = 4,
a416ff28
RB
675 .handler = do_lport_add,
676 },
677 {
678 .name = "lport-del",
a367622a 679 .usage = "LPORT",
a416ff28
RB
680 .min_args = 1,
681 .max_args = 1,
682 .handler = do_lport_del,
683 },
684 {
685 .name = "lport-list",
a367622a 686 .usage = "LSWITCH",
a416ff28
RB
687 .min_args = 1,
688 .max_args = 1,
689 .handler = do_lport_list,
690 },
bf5fa52a
RB
691 {
692 .name = "lport-get-parent",
693 .usage = "LPORT",
694 .min_args = 1,
695 .max_args = 1,
696 .handler = do_lport_get_parent,
697 },
698 {
699 .name = "lport-get-tag",
700 .usage = "LPORT",
701 .min_args = 1,
702 .max_args = 1,
703 .handler = do_lport_get_tag,
704 },
a416ff28
RB
705 {
706 .name = "lport-set-external-id",
a367622a 707 .usage = "LPORT KEY [VALUE]",
a416ff28
RB
708 .min_args = 2,
709 .max_args = 3,
710 .handler = do_lport_set_external_id,
711 },
712 {
713 .name = "lport-get-external-id",
a367622a 714 .usage = "LPORT [KEY]",
a416ff28
RB
715 .min_args = 1,
716 .max_args = 2,
717 .handler = do_lport_get_external_id,
718 },
719 {
720 .name = "lport-set-macs",
2de82d90 721 .usage = "LPORT [MAC]...",
a416ff28
RB
722 .min_args = 1,
723 /* Accept however many arguments the system will allow. */
724 .max_args = INT_MAX,
725 .handler = do_lport_set_macs,
726 },
727 {
728 .name = "lport-get-macs",
a367622a 729 .usage = "LPORT",
a416ff28
RB
730 .min_args = 1,
731 .max_args = 1,
732 .handler = do_lport_get_macs,
733 },
92207865
BP
734 {
735 .name = "lport-set-port-security",
736 .usage = "LPORT [ADDRS]...",
737 .min_args = 0,
738 /* Accept however many arguments the system will allow. */
739 .max_args = INT_MAX,
740 .handler = do_lport_set_port_security,
741 },
742 {
743 .name = "lport-get-port-security",
744 .usage = "LPORT",
745 .min_args = 1,
746 .max_args = 1,
747 .handler = do_lport_get_port_security,
748 },
65fb6826
RB
749 {
750 .name = "lport-get-up",
a367622a 751 .usage = "LPORT",
65fb6826
RB
752 .min_args = 1,
753 .max_args = 1,
754 .handler = do_lport_get_up,
755 },
a416ff28
RB
756
757 {
758 /* sentinel */
759 .name = NULL,
760 },
761};
762
763static const struct ovs_cmdl_command *
764get_all_commands(void)
765{
766 return all_commands;
767}
768
769static const char *
770default_db(void)
771{
772 static char *def;
773 if (!def) {
774 def = xasprintf("unix:%s/db.sock", ovs_rundir());
775 }
776 return def;
777}
778
779int
780main(int argc, char *argv[])
781{
782 extern struct vlog_module VLM_reconnect;
783 struct ovs_cmdl_context ctx;
784 struct nbctl_context nb_ctx = { .idl = NULL, };
785 enum ovsdb_idl_txn_status txn_status;
786 unsigned int seqno;
62ce36b2 787 int res = 0;
afc9da0b 788 char *args;
a416ff28
RB
789
790 fatal_ignore_sigpipe();
791 set_program_name(argv[0]);
792 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
793 vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
794 parse_options(argc, argv);
795 nbrec_init();
796
afc9da0b
JP
797 args = process_escape_args(argv);
798
a416ff28
RB
799 nb_ctx.idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
800 ctx.pvt = &nb_ctx;
801 ctx.argc = argc - optind;
802 ctx.argv = argv + optind;
803
804 seqno = ovsdb_idl_get_seqno(nb_ctx.idl);
805 for (;;) {
806 ovsdb_idl_run(nb_ctx.idl);
807
808 if (!ovsdb_idl_is_alive(nb_ctx.idl)) {
809 int retval = ovsdb_idl_get_last_error(nb_ctx.idl);
810 VLOG_ERR("%s: database connection failed (%s)",
811 db, ovs_retval_to_string(retval));
62ce36b2
RB
812 res = 1;
813 break;
a416ff28
RB
814 }
815
816 if (seqno != ovsdb_idl_get_seqno(nb_ctx.idl)) {
817 nb_ctx.txn = ovsdb_idl_txn_create(nb_ctx.idl);
afc9da0b 818 ovsdb_idl_txn_add_comment(nb_ctx.txn, "ovn-nbctl: %s", args);
a416ff28
RB
819 ovs_cmdl_run_command(&ctx, get_all_commands());
820 txn_status = ovsdb_idl_txn_commit_block(nb_ctx.txn);
821 if (txn_status == TXN_TRY_AGAIN) {
6514cf48
RB
822 ovsdb_idl_txn_destroy(nb_ctx.txn);
823 nb_ctx.txn = NULL;
a416ff28
RB
824 continue;
825 } else {
826 break;
827 }
828 }
829
830 if (seqno == ovsdb_idl_get_seqno(nb_ctx.idl)) {
831 ovsdb_idl_wait(nb_ctx.idl);
832 poll_block();
833 }
834 }
835
836 if (nb_ctx.txn) {
837 ovsdb_idl_txn_destroy(nb_ctx.txn);
838 }
839 ovsdb_idl_destroy(nb_ctx.idl);
afc9da0b 840 free(args);
a416ff28 841
62ce36b2 842 exit(res);
a416ff28 843}