2 * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
31 #include "command-line.h"
34 #include "dynamic-string.h"
36 #include "ovsdb-data.h"
37 #include "ovsdb-idl.h"
38 #include "poll-loop.h"
41 #include "stream-ssl.h"
44 #include "vswitchd/vswitch-idl.h"
51 VLOG_DEFINE_THIS_MODULE(vsctl
);
53 /* vsctl_fatal() also logs the error, so it is preferred in this file. */
54 #define ovs_fatal please_use_vsctl_fatal_instead_of_ovs_fatal
58 /* A command supported by ovs-vsctl. */
59 struct vsctl_command_syntax
{
60 const char *name
; /* e.g. "add-br" */
61 int min_args
; /* Min number of arguments following name. */
62 int max_args
; /* Max number of arguments following name. */
64 /* If nonnull, calls ovsdb_idl_add_column() or ovsdb_idl_add_table() for
65 * each column or table in ctx->idl that it uses. */
66 void (*prerequisites
)(struct vsctl_context
*ctx
);
68 /* Does the actual work of the command and puts the command's output, if
69 * any, in ctx->output or ctx->table.
71 * Alternatively, if some prerequisite of the command is not met and the
72 * caller should wait for something to change and then retry, it may set
73 * ctx->try_again to true. (Only the "wait-until" command currently does
75 void (*run
)(struct vsctl_context
*ctx
);
77 /* If nonnull, called after the transaction has been successfully
78 * committed. ctx->output is the output from the "run" function, which
79 * this function may modify and otherwise postprocess as needed. (Only the
80 * "create" command currently does any postprocessing.) */
81 void (*postprocess
)(struct vsctl_context
*ctx
);
83 /* A comma-separated list of supported options, e.g. "--a,--b", or the
84 * empty string if the command does not support any options. */
86 enum { RO
, RW
} mode
; /* Does this command modify the database? */
89 struct vsctl_command
{
90 /* Data that remains constant after initialization. */
91 const struct vsctl_command_syntax
*syntax
;
96 /* Data modified by commands. */
101 /* --db: The database server to contact. */
102 static const char *db
;
104 /* --oneline: Write each command's output as a single line? */
107 /* --dry-run: Do not commit any changes. */
110 /* --no-wait: Wait for ovs-vswitchd to reload its configuration? */
111 static bool wait_for_reload
= true;
113 /* --timeout: Time to wait for a connection to 'db'. */
116 /* Format for table output. */
117 static struct table_style table_style
= TABLE_STYLE_DEFAULT
;
119 /* All supported commands. */
120 static const struct vsctl_command_syntax all_commands
[];
122 /* The IDL we're using and the current transaction, if any.
123 * This is for use by vsctl_exit() only, to allow it to clean up.
124 * Other code should use its context arguments. */
125 static struct ovsdb_idl
*the_idl
;
126 static struct ovsdb_idl_txn
*the_idl_txn
;
128 static void vsctl_exit(int status
) NO_RETURN
;
129 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN
;
130 static char *default_db(void);
131 static void usage(void) NO_RETURN
;
132 static void parse_options(int argc
, char *argv
[]);
133 static bool might_write_to_db(char **argv
);
135 static struct vsctl_command
*parse_commands(int argc
, char *argv
[],
136 size_t *n_commandsp
);
137 static void parse_command(int argc
, char *argv
[], struct vsctl_command
*);
138 static const struct vsctl_command_syntax
*find_command(const char *name
);
139 static void run_prerequisites(struct vsctl_command
[], size_t n_commands
,
141 static enum ovsdb_idl_txn_status
do_vsctl(const char *args
,
142 struct vsctl_command
*, size_t n
,
145 static const struct vsctl_table_class
*get_table(const char *table_name
);
146 static void set_column(const struct vsctl_table_class
*,
147 const struct ovsdb_idl_row
*, const char *arg
,
148 struct ovsdb_symbol_table
*);
150 static bool is_condition_satisfied(const struct vsctl_table_class
*,
151 const struct ovsdb_idl_row
*,
153 struct ovsdb_symbol_table
*);
156 main(int argc
, char *argv
[])
158 extern struct vlog_module VLM_reconnect
;
159 enum ovsdb_idl_txn_status status
;
160 struct ovsdb_idl
*idl
;
161 struct vsctl_command
*commands
;
165 set_program_name(argv
[0]);
166 signal(SIGPIPE
, SIG_IGN
);
167 vlog_set_levels(NULL
, VLF_CONSOLE
, VLL_WARN
);
168 vlog_set_levels(&VLM_reconnect
, VLF_ANY_FACILITY
, VLL_WARN
);
171 /* Log our arguments. This is often valuable for debugging systems. */
172 args
= process_escape_args(argv
);
173 VLOG(might_write_to_db(argv
) ? VLL_INFO
: VLL_DBG
, "Called as %s", args
);
175 /* Parse command line. */
176 parse_options(argc
, argv
);
177 commands
= parse_commands(argc
- optind
, argv
+ optind
, &n_commands
);
183 /* Initialize IDL. */
184 idl
= the_idl
= ovsdb_idl_create(db
, &ovsrec_idl_class
, false);
185 run_prerequisites(commands
, n_commands
, idl
);
187 /* Now execute the commands. */
188 status
= TXN_AGAIN_WAIT
;
190 if (ovsdb_idl_run(idl
) || status
== TXN_AGAIN_NOW
) {
191 status
= do_vsctl(args
, commands
, n_commands
, idl
);
194 if (status
!= TXN_AGAIN_NOW
) {
202 parse_options(int argc
, char *argv
[])
205 OPT_DB
= UCHAR_MAX
+ 1,
214 static struct option long_options
[] = {
215 {"db", required_argument
, NULL
, OPT_DB
},
216 {"no-syslog", no_argument
, NULL
, OPT_NO_SYSLOG
},
217 {"no-wait", no_argument
, NULL
, OPT_NO_WAIT
},
218 {"dry-run", no_argument
, NULL
, OPT_DRY_RUN
},
219 {"oneline", no_argument
, NULL
, OPT_ONELINE
},
220 {"timeout", required_argument
, NULL
, 't'},
221 {"help", no_argument
, NULL
, 'h'},
222 {"version", no_argument
, NULL
, 'V'},
225 STREAM_SSL_LONG_OPTIONS
,
226 {"peer-ca-cert", required_argument
, NULL
, OPT_PEER_CA_CERT
},
229 char *tmp
, *short_options
;
231 tmp
= long_options_to_short_options(long_options
);
232 short_options
= xasprintf("+%s", tmp
);
235 table_style
.format
= TF_LIST
;
240 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
255 vlog_set_levels(&VLM_vsctl
, VLF_SYSLOG
, VLL_WARN
);
259 wait_for_reload
= false;
270 ovs_print_version(0, 0);
274 timeout
= strtoul(optarg
, NULL
, 10);
276 vsctl_fatal("value %s on -t or --timeout is invalid",
282 TABLE_OPTION_HANDLERS(&table_style
)
284 STREAM_SSL_OPTION_HANDLERS
286 case OPT_PEER_CA_CERT
:
287 stream_ssl_set_peer_ca_cert_file(optarg
);
304 static struct vsctl_command
*
305 parse_commands(int argc
, char *argv
[], size_t *n_commandsp
)
307 struct vsctl_command
*commands
;
308 size_t n_commands
, allocated_commands
;
312 n_commands
= allocated_commands
= 0;
314 for (start
= i
= 0; i
<= argc
; i
++) {
315 if (i
== argc
|| !strcmp(argv
[i
], "--")) {
317 if (n_commands
>= allocated_commands
) {
318 struct vsctl_command
*c
;
320 commands
= x2nrealloc(commands
, &allocated_commands
,
322 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
323 shash_moved(&c
->options
);
326 parse_command(i
- start
, &argv
[start
],
327 &commands
[n_commands
++]);
333 vsctl_fatal("missing command name (use --help for help)");
335 *n_commandsp
= n_commands
;
340 parse_command(int argc
, char *argv
[], struct vsctl_command
*command
)
342 const struct vsctl_command_syntax
*p
;
343 struct shash_node
*node
;
347 shash_init(&command
->options
);
348 for (i
= 0; i
< argc
; i
++) {
349 const char *option
= argv
[i
];
353 if (option
[0] != '-') {
357 equals
= strchr(option
, '=');
359 key
= xmemdup0(option
, equals
- option
);
360 value
= xstrdup(equals
+ 1);
362 key
= xstrdup(option
);
366 if (shash_find(&command
->options
, key
)) {
367 vsctl_fatal("'%s' option specified multiple times", argv
[i
]);
369 shash_add_nocopy(&command
->options
, key
, value
);
372 vsctl_fatal("missing command name");
375 p
= find_command(argv
[i
]);
377 vsctl_fatal("unknown command '%s'; use --help for help", argv
[i
]);
380 SHASH_FOR_EACH (node
, &command
->options
) {
381 const char *s
= strstr(p
->options
, node
->name
);
382 int end
= s
? s
[strlen(node
->name
)] : EOF
;
384 if (end
!= '=' && end
!= ',' && end
!= ' ' && end
!= '\0') {
385 vsctl_fatal("'%s' command has no '%s' option",
386 argv
[i
], node
->name
);
388 if ((end
== '=') != (node
->data
!= NULL
)) {
390 vsctl_fatal("missing argument to '%s' option on '%s' "
391 "command", node
->name
, argv
[i
]);
393 vsctl_fatal("'%s' option on '%s' does not accept an "
394 "argument", node
->name
, argv
[i
]);
399 n_arg
= argc
- i
- 1;
400 if (n_arg
< p
->min_args
) {
401 vsctl_fatal("'%s' command requires at least %d arguments",
402 p
->name
, p
->min_args
);
403 } else if (n_arg
> p
->max_args
) {
406 for (j
= i
+ 1; j
< argc
; j
++) {
407 if (argv
[j
][0] == '-') {
408 vsctl_fatal("'%s' command takes at most %d arguments "
409 "(note that options must precede command "
410 "names and follow a \"--\" argument)",
411 p
->name
, p
->max_args
);
415 vsctl_fatal("'%s' command takes at most %d arguments",
416 p
->name
, p
->max_args
);
420 command
->argc
= n_arg
+ 1;
421 command
->argv
= &argv
[i
];
424 /* Returns the "struct vsctl_command_syntax" for a given command 'name', or a
425 * null pointer if there is none. */
426 static const struct vsctl_command_syntax
*
427 find_command(const char *name
)
429 static struct shash commands
= SHASH_INITIALIZER(&commands
);
431 if (shash_is_empty(&commands
)) {
432 const struct vsctl_command_syntax
*p
;
434 for (p
= all_commands
; p
->name
; p
++) {
435 shash_add_assert(&commands
, p
->name
, p
);
439 return shash_find_data(&commands
, name
);
443 vsctl_fatal(const char *format
, ...)
448 va_start(args
, format
);
449 message
= xvasprintf(format
, args
);
452 vlog_set_levels(&VLM_vsctl
, VLF_CONSOLE
, VLL_OFF
);
453 VLOG_ERR("%s", message
);
454 ovs_error(0, "%s", message
);
455 vsctl_exit(EXIT_FAILURE
);
458 /* Frees the current transaction and the underlying IDL and then calls
461 * Freeing the transaction and the IDL is not strictly necessary, but it makes
462 * for a clean memory leak report from valgrind in the normal case. That makes
463 * it easier to notice real memory leaks. */
465 vsctl_exit(int status
)
468 ovsdb_idl_txn_abort(the_idl_txn
);
469 ovsdb_idl_txn_destroy(the_idl_txn
);
471 ovsdb_idl_destroy(the_idl
);
479 %s: ovs-vswitchd management utility\n\
480 usage: %s [OPTIONS] COMMAND [ARG...]\n\
482 Open vSwitch commands:\n\
483 init initialize database, if not yet initialized\n\
484 show print overview of database contents\n\
485 emer-reset reset configuration to clean state\n\
488 add-br BRIDGE create a new bridge named BRIDGE\n\
489 add-br BRIDGE PARENT VLAN create new fake BRIDGE in PARENT on VLAN\n\
490 del-br BRIDGE delete BRIDGE and all of its ports\n\
491 list-br print the names of all the bridges\n\
492 br-exists BRIDGE test whether BRIDGE exists\n\
493 br-to-vlan BRIDGE print the VLAN which BRIDGE is on\n\
494 br-to-parent BRIDGE print the parent of BRIDGE\n\
495 br-set-external-id BRIDGE KEY VALUE set KEY on BRIDGE to VALUE\n\
496 br-set-external-id BRIDGE KEY unset KEY on BRIDGE\n\
497 br-get-external-id BRIDGE KEY print value of KEY on BRIDGE\n\
498 br-get-external-id BRIDGE list key-value pairs on BRIDGE\n\
500 Port commands (a bond is considered to be a single port):\n\
501 list-ports BRIDGE print the names of all the ports on BRIDGE\n\
502 add-port BRIDGE PORT add network device PORT to BRIDGE\n\
503 add-bond BRIDGE PORT IFACE... add bonded port PORT in BRIDGE from IFACES\n\
504 del-port [BRIDGE] PORT delete PORT (which may be bonded) from BRIDGE\n\
505 port-to-br PORT print name of bridge that contains PORT\n\
507 Interface commands (a bond consists of multiple interfaces):\n\
508 list-ifaces BRIDGE print the names of all interfaces on BRIDGE\n\
509 iface-to-br IFACE print name of bridge that contains IFACE\n\
511 Controller commands:\n\
512 get-controller BRIDGE print the controllers for BRIDGE\n\
513 del-controller BRIDGE delete the controllers for BRIDGE\n\
514 set-controller BRIDGE TARGET... set the controllers for BRIDGE\n\
515 get-fail-mode BRIDGE print the fail-mode for BRIDGE\n\
516 del-fail-mode BRIDGE delete the fail-mode for BRIDGE\n\
517 set-fail-mode BRIDGE MODE set the fail-mode for BRIDGE to MODE\n\
520 get-manager print the managers\n\
521 del-manager delete the managers\n\
522 set-manager TARGET... set the list of managers to TARGET...\n\
525 get-ssl print the SSL configuration\n\
526 del-ssl delete the SSL configuration\n\
527 set-ssl PRIV-KEY CERT CA-CERT set the SSL configuration\n\
530 emer-reset reset switch to known good state\n\
532 Database commands:\n\
533 list TBL [REC] list RECord (or all records) in TBL\n\
534 find TBL CONDITION... list records satisfying CONDITION in TBL\n\
535 get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\
536 set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
537 add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
538 remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn\n\
539 clear TBL REC COL clear values from COLumn in RECord in TBL\n\
540 create TBL COL[:KEY]=VALUE create and initialize new record\n\
541 destroy TBL REC delete RECord from TBL\n\
542 wait-until TBL REC [COL[:KEY]=VALUE] wait until condition is true\n\
543 Potentially unsafe database commands require --force option.\n\
546 --db=DATABASE connect to DATABASE\n\
548 --no-wait do not wait for ovs-vswitchd to reconfigure\n\
549 -t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
550 --dry-run do not commit changes to database\n\
551 --oneline print exactly one line of output per command\n",
552 program_name
, program_name
, default_db());
555 --no-syslog equivalent to --verbose=vsctl:syslog:warn\n");
556 stream_usage("database", true, true, false);
559 -h, --help display this help message\n\
560 -V, --version display version information\n");
569 def
= xasprintf("unix:%s/db.sock", ovs_rundir());
574 /* Returns true if it looks like this set of arguments might modify the
575 * database, otherwise false. (Not very smart, so it's prone to false
578 might_write_to_db(char **argv
)
580 for (; *argv
; argv
++) {
581 const struct vsctl_command_syntax
*p
= find_command(*argv
);
582 if (p
&& p
->mode
== RW
) {
589 struct vsctl_context
{
593 struct shash options
;
595 /* Modifiable state. */
598 struct ovsdb_idl
*idl
;
599 struct ovsdb_idl_txn
*txn
;
600 struct ovsdb_symbol_table
*symtab
;
601 const struct ovsrec_open_vswitch
*ovs
;
604 /* A command may set this member to true if some prerequisite is not met
605 * and the caller should wait for something to change and then retry. */
609 struct vsctl_bridge
{
610 struct ovsrec_bridge
*br_cfg
;
612 struct ovsrec_controller
**ctrl
;
615 struct vsctl_bridge
*parent
;
620 struct ovsrec_port
*port_cfg
;
621 struct vsctl_bridge
*bridge
;
625 struct ovsrec_interface
*iface_cfg
;
626 struct vsctl_port
*port
;
630 struct vsctl_context
*ctx
;
631 struct shash bridges
; /* Maps from bridge name to struct vsctl_bridge. */
632 struct shash ports
; /* Maps from port name to struct vsctl_port. */
633 struct shash ifaces
; /* Maps from port name to struct vsctl_iface. */
637 vsctl_context_to_string(const struct vsctl_context
*ctx
)
639 const struct shash_node
*node
;
645 SHASH_FOR_EACH (node
, &ctx
->options
) {
646 svec_add(&words
, node
->name
);
648 for (i
= 0; i
< ctx
->argc
; i
++) {
649 svec_add(&words
, ctx
->argv
[i
]);
651 svec_terminate(&words
);
653 s
= process_escape_args(words
.names
);
655 svec_destroy(&words
);
661 verify_ports(struct vsctl_context
*ctx
)
663 if (!ctx
->verified_ports
) {
664 const struct ovsrec_bridge
*bridge
;
665 const struct ovsrec_port
*port
;
667 ovsrec_open_vswitch_verify_bridges(ctx
->ovs
);
668 OVSREC_BRIDGE_FOR_EACH (bridge
, ctx
->idl
) {
669 ovsrec_bridge_verify_ports(bridge
);
671 OVSREC_PORT_FOR_EACH (port
, ctx
->idl
) {
672 ovsrec_port_verify_interfaces(port
);
675 ctx
->verified_ports
= true;
679 static struct vsctl_bridge
*
680 add_bridge(struct vsctl_info
*b
,
681 struct ovsrec_bridge
*br_cfg
, const char *name
,
682 struct vsctl_bridge
*parent
, int vlan
)
684 struct vsctl_bridge
*br
= xmalloc(sizeof *br
);
686 br
->name
= xstrdup(name
);
690 br
->ctrl
= parent
->br_cfg
->controller
;
691 br
->n_ctrl
= parent
->br_cfg
->n_controller
;
692 br
->fail_mode
= parent
->br_cfg
->fail_mode
;
694 br
->ctrl
= br_cfg
->controller
;
695 br
->n_ctrl
= br_cfg
->n_controller
;
696 br
->fail_mode
= br_cfg
->fail_mode
;
698 shash_add(&b
->bridges
, br
->name
, br
);
703 port_is_fake_bridge(const struct ovsrec_port
*port_cfg
)
705 return (port_cfg
->fake_bridge
707 && *port_cfg
->tag
>= 1 && *port_cfg
->tag
<= 4095);
710 static struct vsctl_bridge
*
711 find_vlan_bridge(struct vsctl_info
*info
,
712 struct vsctl_bridge
*parent
, int vlan
)
714 struct shash_node
*node
;
716 SHASH_FOR_EACH (node
, &info
->bridges
) {
717 struct vsctl_bridge
*br
= node
->data
;
718 if (br
->parent
== parent
&& br
->vlan
== vlan
) {
727 free_info(struct vsctl_info
*info
)
729 struct shash_node
*node
;
731 SHASH_FOR_EACH (node
, &info
->bridges
) {
732 struct vsctl_bridge
*bridge
= node
->data
;
736 shash_destroy(&info
->bridges
);
738 shash_destroy_free_data(&info
->ports
);
739 shash_destroy_free_data(&info
->ifaces
);
743 pre_get_info(struct vsctl_context
*ctx
)
745 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_bridges
);
747 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_name
);
748 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_controller
);
749 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_fail_mode
);
750 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_ports
);
752 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_port_col_name
);
753 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_port_col_fake_bridge
);
754 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_port_col_tag
);
755 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_port_col_interfaces
);
757 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_interface_col_name
);
761 get_info(struct vsctl_context
*ctx
, struct vsctl_info
*info
)
763 const struct ovsrec_open_vswitch
*ovs
= ctx
->ovs
;
764 struct sset bridges
, ports
;
768 shash_init(&info
->bridges
);
769 shash_init(&info
->ports
);
770 shash_init(&info
->ifaces
);
774 for (i
= 0; i
< ovs
->n_bridges
; i
++) {
775 struct ovsrec_bridge
*br_cfg
= ovs
->bridges
[i
];
776 struct vsctl_bridge
*br
;
779 if (!sset_add(&bridges
, br_cfg
->name
)) {
780 VLOG_WARN("%s: database contains duplicate bridge name",
784 br
= add_bridge(info
, br_cfg
, br_cfg
->name
, NULL
, 0);
789 for (j
= 0; j
< br_cfg
->n_ports
; j
++) {
790 struct ovsrec_port
*port_cfg
= br_cfg
->ports
[j
];
792 if (!sset_add(&ports
, port_cfg
->name
)) {
793 /* Duplicate port name. (We will warn about that later.) */
797 if (port_is_fake_bridge(port_cfg
)
798 && sset_add(&bridges
, port_cfg
->name
)) {
799 add_bridge(info
, NULL
, port_cfg
->name
, br
, *port_cfg
->tag
);
803 sset_destroy(&bridges
);
804 sset_destroy(&ports
);
807 for (i
= 0; i
< ovs
->n_bridges
; i
++) {
808 struct ovsrec_bridge
*br_cfg
= ovs
->bridges
[i
];
809 struct vsctl_bridge
*br
;
812 if (!sset_add(&bridges
, br_cfg
->name
)) {
815 br
= shash_find_data(&info
->bridges
, br_cfg
->name
);
816 for (j
= 0; j
< br_cfg
->n_ports
; j
++) {
817 struct ovsrec_port
*port_cfg
= br_cfg
->ports
[j
];
818 struct vsctl_port
*port
;
821 port
= shash_find_data(&info
->ports
, port_cfg
->name
);
823 if (port_cfg
== port
->port_cfg
) {
824 VLOG_WARN("%s: port is in multiple bridges (%s and %s)",
825 port_cfg
->name
, br
->name
, port
->bridge
->name
);
827 /* Log as an error because this violates the database's
828 * uniqueness constraints, so the database server shouldn't
829 * have allowed it. */
830 VLOG_ERR("%s: database contains duplicate port name",
836 if (port_is_fake_bridge(port_cfg
)
837 && !sset_add(&bridges
, port_cfg
->name
)) {
841 port
= xmalloc(sizeof *port
);
842 port
->port_cfg
= port_cfg
;
844 && *port_cfg
->tag
>= 1 && *port_cfg
->tag
<= 4095) {
845 port
->bridge
= find_vlan_bridge(info
, br
, *port_cfg
->tag
);
852 shash_add(&info
->ports
, port_cfg
->name
, port
);
854 for (k
= 0; k
< port_cfg
->n_interfaces
; k
++) {
855 struct ovsrec_interface
*iface_cfg
= port_cfg
->interfaces
[k
];
856 struct vsctl_iface
*iface
;
858 iface
= shash_find_data(&info
->ifaces
, iface_cfg
->name
);
860 if (iface_cfg
== iface
->iface_cfg
) {
861 VLOG_WARN("%s: interface is in multiple ports "
864 iface
->port
->port_cfg
->name
,
865 port
->port_cfg
->name
);
867 /* Log as an error because this violates the database's
868 * uniqueness constraints, so the database server
869 * shouldn't have allowed it. */
870 VLOG_ERR("%s: database contains duplicate interface "
871 "name", iface_cfg
->name
);
876 iface
= xmalloc(sizeof *iface
);
877 iface
->iface_cfg
= iface_cfg
;
879 shash_add(&info
->ifaces
, iface_cfg
->name
, iface
);
883 sset_destroy(&bridges
);
887 check_conflicts(struct vsctl_info
*info
, const char *name
,
890 struct vsctl_iface
*iface
;
891 struct vsctl_port
*port
;
893 verify_ports(info
->ctx
);
895 if (shash_find(&info
->bridges
, name
)) {
896 vsctl_fatal("%s because a bridge named %s already exists",
900 port
= shash_find_data(&info
->ports
, name
);
902 vsctl_fatal("%s because a port named %s already exists on "
903 "bridge %s", msg
, name
, port
->bridge
->name
);
906 iface
= shash_find_data(&info
->ifaces
, name
);
908 vsctl_fatal("%s because an interface named %s already exists "
909 "on bridge %s", msg
, name
, iface
->port
->bridge
->name
);
915 static struct vsctl_bridge
*
916 find_bridge(struct vsctl_info
*info
, const char *name
, bool must_exist
)
918 struct vsctl_bridge
*br
= shash_find_data(&info
->bridges
, name
);
919 if (must_exist
&& !br
) {
920 vsctl_fatal("no bridge named %s", name
);
922 ovsrec_open_vswitch_verify_bridges(info
->ctx
->ovs
);
926 static struct vsctl_bridge
*
927 find_real_bridge(struct vsctl_info
*info
, const char *name
, bool must_exist
)
929 struct vsctl_bridge
*br
= find_bridge(info
, name
, must_exist
);
930 if (br
&& br
->parent
) {
931 vsctl_fatal("%s is a fake bridge", name
);
936 static struct vsctl_port
*
937 find_port(struct vsctl_info
*info
, const char *name
, bool must_exist
)
939 struct vsctl_port
*port
= shash_find_data(&info
->ports
, name
);
940 if (port
&& !strcmp(name
, port
->bridge
->name
)) {
943 if (must_exist
&& !port
) {
944 vsctl_fatal("no port named %s", name
);
946 verify_ports(info
->ctx
);
950 static struct vsctl_iface
*
951 find_iface(struct vsctl_info
*info
, const char *name
, bool must_exist
)
953 struct vsctl_iface
*iface
= shash_find_data(&info
->ifaces
, name
);
954 if (iface
&& !strcmp(name
, iface
->port
->bridge
->name
)) {
957 if (must_exist
&& !iface
) {
958 vsctl_fatal("no interface named %s", name
);
960 verify_ports(info
->ctx
);
965 bridge_insert_port(struct ovsrec_bridge
*br
, struct ovsrec_port
*port
)
967 struct ovsrec_port
**ports
;
970 ports
= xmalloc(sizeof *br
->ports
* (br
->n_ports
+ 1));
971 for (i
= 0; i
< br
->n_ports
; i
++) {
972 ports
[i
] = br
->ports
[i
];
974 ports
[br
->n_ports
] = port
;
975 ovsrec_bridge_set_ports(br
, ports
, br
->n_ports
+ 1);
980 bridge_delete_port(struct ovsrec_bridge
*br
, struct ovsrec_port
*port
)
982 struct ovsrec_port
**ports
;
985 ports
= xmalloc(sizeof *br
->ports
* br
->n_ports
);
986 for (i
= n
= 0; i
< br
->n_ports
; i
++) {
987 if (br
->ports
[i
] != port
) {
988 ports
[n
++] = br
->ports
[i
];
991 ovsrec_bridge_set_ports(br
, ports
, n
);
996 ovs_insert_bridge(const struct ovsrec_open_vswitch
*ovs
,
997 struct ovsrec_bridge
*bridge
)
999 struct ovsrec_bridge
**bridges
;
1002 bridges
= xmalloc(sizeof *ovs
->bridges
* (ovs
->n_bridges
+ 1));
1003 for (i
= 0; i
< ovs
->n_bridges
; i
++) {
1004 bridges
[i
] = ovs
->bridges
[i
];
1006 bridges
[ovs
->n_bridges
] = bridge
;
1007 ovsrec_open_vswitch_set_bridges(ovs
, bridges
, ovs
->n_bridges
+ 1);
1012 ovs_delete_bridge(const struct ovsrec_open_vswitch
*ovs
,
1013 struct ovsrec_bridge
*bridge
)
1015 struct ovsrec_bridge
**bridges
;
1018 bridges
= xmalloc(sizeof *ovs
->bridges
* ovs
->n_bridges
);
1019 for (i
= n
= 0; i
< ovs
->n_bridges
; i
++) {
1020 if (ovs
->bridges
[i
] != bridge
) {
1021 bridges
[n
++] = ovs
->bridges
[i
];
1024 ovsrec_open_vswitch_set_bridges(ovs
, bridges
, n
);
1029 cmd_init(struct vsctl_context
*ctx OVS_UNUSED
)
1033 struct cmd_show_table
{
1034 const struct ovsdb_idl_table_class
*table
;
1035 const struct ovsdb_idl_column
*name_column
;
1036 const struct ovsdb_idl_column
*columns
[3];
1040 static struct cmd_show_table cmd_show_tables
[] = {
1041 {&ovsrec_table_open_vswitch
,
1043 {&ovsrec_open_vswitch_col_manager_options
,
1044 &ovsrec_open_vswitch_col_bridges
,
1045 &ovsrec_open_vswitch_col_ovs_version
},
1048 {&ovsrec_table_bridge
,
1049 &ovsrec_bridge_col_name
,
1050 {&ovsrec_bridge_col_controller
,
1051 &ovsrec_bridge_col_fail_mode
,
1052 &ovsrec_bridge_col_ports
},
1055 {&ovsrec_table_port
,
1056 &ovsrec_port_col_name
,
1057 {&ovsrec_port_col_tag
,
1058 &ovsrec_port_col_trunks
,
1059 &ovsrec_port_col_interfaces
},
1062 {&ovsrec_table_interface
,
1063 &ovsrec_interface_col_name
,
1064 {&ovsrec_interface_col_type
,
1065 &ovsrec_interface_col_options
,
1069 {&ovsrec_table_controller
,
1070 &ovsrec_controller_col_target
,
1071 {&ovsrec_controller_col_is_connected
,
1076 {&ovsrec_table_manager
,
1077 &ovsrec_manager_col_target
,
1078 {&ovsrec_manager_col_is_connected
,
1085 pre_cmd_show(struct vsctl_context
*ctx
)
1087 struct cmd_show_table
*show
;
1089 for (show
= cmd_show_tables
;
1090 show
< &cmd_show_tables
[ARRAY_SIZE(cmd_show_tables
)];
1094 ovsdb_idl_add_table(ctx
->idl
, show
->table
);
1095 if (show
->name_column
) {
1096 ovsdb_idl_add_column(ctx
->idl
, show
->name_column
);
1098 for (i
= 0; i
< ARRAY_SIZE(show
->columns
); i
++) {
1099 const struct ovsdb_idl_column
*column
= show
->columns
[i
];
1101 ovsdb_idl_add_column(ctx
->idl
, column
);
1107 static struct cmd_show_table
*
1108 cmd_show_find_table_by_row(const struct ovsdb_idl_row
*row
)
1110 struct cmd_show_table
*show
;
1112 for (show
= cmd_show_tables
;
1113 show
< &cmd_show_tables
[ARRAY_SIZE(cmd_show_tables
)];
1115 if (show
->table
== row
->table
->class) {
1122 static struct cmd_show_table
*
1123 cmd_show_find_table_by_name(const char *name
)
1125 struct cmd_show_table
*show
;
1127 for (show
= cmd_show_tables
;
1128 show
< &cmd_show_tables
[ARRAY_SIZE(cmd_show_tables
)];
1130 if (!strcmp(show
->table
->name
, name
)) {
1138 cmd_show_row(struct vsctl_context
*ctx
, const struct ovsdb_idl_row
*row
,
1141 struct cmd_show_table
*show
= cmd_show_find_table_by_row(row
);
1144 ds_put_char_multiple(&ctx
->output
, ' ', level
* 4);
1145 if (show
&& show
->name_column
) {
1146 const struct ovsdb_datum
*datum
;
1148 ds_put_format(&ctx
->output
, "%s ", show
->table
->name
);
1149 datum
= ovsdb_idl_read(row
, show
->name_column
);
1150 ovsdb_datum_to_string(datum
, &show
->name_column
->type
, &ctx
->output
);
1152 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
1154 ds_put_char(&ctx
->output
, '\n');
1156 if (!show
|| show
->recurse
) {
1160 show
->recurse
= true;
1161 for (i
= 0; i
< ARRAY_SIZE(show
->columns
); i
++) {
1162 const struct ovsdb_idl_column
*column
= show
->columns
[i
];
1163 const struct ovsdb_datum
*datum
;
1169 datum
= ovsdb_idl_read(row
, column
);
1170 if (column
->type
.key
.type
== OVSDB_TYPE_UUID
&&
1171 column
->type
.key
.u
.uuid
.refTableName
) {
1172 struct cmd_show_table
*ref_show
;
1175 ref_show
= cmd_show_find_table_by_name(
1176 column
->type
.key
.u
.uuid
.refTableName
);
1178 for (j
= 0; j
< datum
->n
; j
++) {
1179 const struct ovsdb_idl_row
*ref_row
;
1181 ref_row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
,
1183 &datum
->keys
[j
].uuid
);
1185 cmd_show_row(ctx
, ref_row
, level
+ 1);
1192 if (!ovsdb_datum_is_default(datum
, &column
->type
)) {
1193 ds_put_char_multiple(&ctx
->output
, ' ', (level
+ 1) * 4);
1194 ds_put_format(&ctx
->output
, "%s: ", column
->name
);
1195 ovsdb_datum_to_string(datum
, &column
->type
, &ctx
->output
);
1196 ds_put_char(&ctx
->output
, '\n');
1199 show
->recurse
= false;
1203 cmd_show(struct vsctl_context
*ctx
)
1205 const struct ovsdb_idl_row
*row
;
1207 for (row
= ovsdb_idl_first_row(ctx
->idl
, cmd_show_tables
[0].table
);
1208 row
; row
= ovsdb_idl_next_row(row
)) {
1209 cmd_show_row(ctx
, row
, 0);
1214 pre_cmd_emer_reset(struct vsctl_context
*ctx
)
1216 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_manager_options
);
1217 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_ssl
);
1219 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_controller
);
1220 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_fail_mode
);
1221 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_mirrors
);
1222 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_netflow
);
1223 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_sflow
);
1224 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_flood_vlans
);
1225 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_other_config
);
1227 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_port_col_other_config
);
1229 ovsdb_idl_add_column(ctx
->idl
,
1230 &ovsrec_interface_col_ingress_policing_rate
);
1231 ovsdb_idl_add_column(ctx
->idl
,
1232 &ovsrec_interface_col_ingress_policing_burst
);
1236 cmd_emer_reset(struct vsctl_context
*ctx
)
1238 const struct ovsdb_idl
*idl
= ctx
->idl
;
1239 const struct ovsrec_bridge
*br
;
1240 const struct ovsrec_port
*port
;
1241 const struct ovsrec_interface
*iface
;
1242 const struct ovsrec_mirror
*mirror
, *next_mirror
;
1243 const struct ovsrec_controller
*ctrl
, *next_ctrl
;
1244 const struct ovsrec_manager
*mgr
, *next_mgr
;
1245 const struct ovsrec_netflow
*nf
, *next_nf
;
1246 const struct ovsrec_ssl
*ssl
, *next_ssl
;
1247 const struct ovsrec_sflow
*sflow
, *next_sflow
;
1249 /* Reset the Open_vSwitch table. */
1250 ovsrec_open_vswitch_set_manager_options(ctx
->ovs
, NULL
, 0);
1251 ovsrec_open_vswitch_set_ssl(ctx
->ovs
, NULL
);
1253 OVSREC_BRIDGE_FOR_EACH (br
, idl
) {
1255 char *hw_key
= "hwaddr";
1256 char *hw_val
= NULL
;
1258 ovsrec_bridge_set_controller(br
, NULL
, 0);
1259 ovsrec_bridge_set_fail_mode(br
, NULL
);
1260 ovsrec_bridge_set_mirrors(br
, NULL
, 0);
1261 ovsrec_bridge_set_netflow(br
, NULL
);
1262 ovsrec_bridge_set_sflow(br
, NULL
);
1263 ovsrec_bridge_set_flood_vlans(br
, NULL
, 0);
1265 /* We only want to save the "hwaddr" key from other_config. */
1266 for (i
=0; i
< br
->n_other_config
; i
++) {
1267 if (!strcmp(br
->key_other_config
[i
], hw_key
)) {
1268 hw_val
= br
->value_other_config
[i
];
1273 char *val
= xstrdup(hw_val
);
1274 ovsrec_bridge_set_other_config(br
, &hw_key
, &val
, 1);
1277 ovsrec_bridge_set_other_config(br
, NULL
, NULL
, 0);
1281 OVSREC_PORT_FOR_EACH (port
, idl
) {
1282 ovsrec_port_set_other_config(port
, NULL
, NULL
, 0);
1285 OVSREC_INTERFACE_FOR_EACH (iface
, idl
) {
1286 /* xxx What do we do about gre/patch devices created by mgr? */
1288 ovsrec_interface_set_ingress_policing_rate(iface
, 0);
1289 ovsrec_interface_set_ingress_policing_burst(iface
, 0);
1292 OVSREC_MIRROR_FOR_EACH_SAFE (mirror
, next_mirror
, idl
) {
1293 ovsrec_mirror_delete(mirror
);
1296 OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl
, next_ctrl
, idl
) {
1297 ovsrec_controller_delete(ctrl
);
1300 OVSREC_MANAGER_FOR_EACH_SAFE (mgr
, next_mgr
, idl
) {
1301 ovsrec_manager_delete(mgr
);
1304 OVSREC_NETFLOW_FOR_EACH_SAFE (nf
, next_nf
, idl
) {
1305 ovsrec_netflow_delete(nf
);
1308 OVSREC_SSL_FOR_EACH_SAFE (ssl
, next_ssl
, idl
) {
1309 ovsrec_ssl_delete(ssl
);
1312 OVSREC_SFLOW_FOR_EACH_SAFE (sflow
, next_sflow
, idl
) {
1313 ovsrec_sflow_delete(sflow
);
1318 cmd_add_br(struct vsctl_context
*ctx
)
1320 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
1321 const char *br_name
, *parent_name
;
1322 struct vsctl_info info
;
1325 br_name
= ctx
->argv
[1];
1326 if (ctx
->argc
== 2) {
1329 } else if (ctx
->argc
== 4) {
1330 parent_name
= ctx
->argv
[2];
1331 vlan
= atoi(ctx
->argv
[3]);
1332 if (vlan
< 1 || vlan
> 4095) {
1333 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx
->argv
[0]);
1336 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
1340 get_info(ctx
, &info
);
1342 struct vsctl_bridge
*br
;
1344 br
= find_bridge(&info
, br_name
, false);
1348 vsctl_fatal("\"--may-exist add-br %s\" but %s is "
1349 "a VLAN bridge for VLAN %d",
1350 br_name
, br_name
, br
->vlan
);
1354 vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
1355 "is not a VLAN bridge",
1356 br_name
, parent_name
, vlan
, br_name
);
1357 } else if (strcmp(br
->parent
->name
, parent_name
)) {
1358 vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
1359 "has the wrong parent %s",
1360 br_name
, parent_name
, vlan
,
1361 br_name
, br
->parent
->name
);
1362 } else if (br
->vlan
!= vlan
) {
1363 vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
1364 "is a VLAN bridge for the wrong VLAN %d",
1365 br_name
, parent_name
, vlan
, br_name
, br
->vlan
);
1371 check_conflicts(&info
, br_name
,
1372 xasprintf("cannot create a bridge named %s", br_name
));
1375 struct ovsrec_port
*port
;
1376 struct ovsrec_interface
*iface
;
1377 struct ovsrec_bridge
*br
;
1379 iface
= ovsrec_interface_insert(ctx
->txn
);
1380 ovsrec_interface_set_name(iface
, br_name
);
1381 ovsrec_interface_set_type(iface
, "internal");
1383 port
= ovsrec_port_insert(ctx
->txn
);
1384 ovsrec_port_set_name(port
, br_name
);
1385 ovsrec_port_set_interfaces(port
, &iface
, 1);
1387 br
= ovsrec_bridge_insert(ctx
->txn
);
1388 ovsrec_bridge_set_name(br
, br_name
);
1389 ovsrec_bridge_set_ports(br
, &port
, 1);
1391 ovs_insert_bridge(ctx
->ovs
, br
);
1393 struct vsctl_bridge
*parent
;
1394 struct ovsrec_port
*port
;
1395 struct ovsrec_interface
*iface
;
1396 struct ovsrec_bridge
*br
;
1399 parent
= find_bridge(&info
, parent_name
, false);
1400 if (parent
&& parent
->vlan
) {
1401 vsctl_fatal("cannot create bridge with fake bridge as parent");
1404 vsctl_fatal("parent bridge %s does not exist", parent_name
);
1406 br
= parent
->br_cfg
;
1408 iface
= ovsrec_interface_insert(ctx
->txn
);
1409 ovsrec_interface_set_name(iface
, br_name
);
1410 ovsrec_interface_set_type(iface
, "internal");
1412 port
= ovsrec_port_insert(ctx
->txn
);
1413 ovsrec_port_set_name(port
, br_name
);
1414 ovsrec_port_set_interfaces(port
, &iface
, 1);
1415 ovsrec_port_set_fake_bridge(port
, true);
1416 ovsrec_port_set_tag(port
, &tag
, 1);
1418 bridge_insert_port(br
, port
);
1425 del_port(struct vsctl_info
*info
, struct vsctl_port
*port
)
1427 struct shash_node
*node
;
1429 SHASH_FOR_EACH (node
, &info
->ifaces
) {
1430 struct vsctl_iface
*iface
= node
->data
;
1431 if (iface
->port
== port
) {
1432 ovsrec_interface_delete(iface
->iface_cfg
);
1435 ovsrec_port_delete(port
->port_cfg
);
1437 bridge_delete_port((port
->bridge
->parent
1438 ? port
->bridge
->parent
->br_cfg
1439 : port
->bridge
->br_cfg
), port
->port_cfg
);
1443 cmd_del_br(struct vsctl_context
*ctx
)
1445 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1446 struct vsctl_bridge
*bridge
;
1447 struct vsctl_info info
;
1449 get_info(ctx
, &info
);
1450 bridge
= find_bridge(&info
, ctx
->argv
[1], must_exist
);
1452 struct shash_node
*node
;
1454 SHASH_FOR_EACH (node
, &info
.ports
) {
1455 struct vsctl_port
*port
= node
->data
;
1456 if (port
->bridge
== bridge
|| port
->bridge
->parent
== bridge
1457 || !strcmp(port
->port_cfg
->name
, bridge
->name
)) {
1458 del_port(&info
, port
);
1461 if (bridge
->br_cfg
) {
1462 ovsrec_bridge_delete(bridge
->br_cfg
);
1463 ovs_delete_bridge(ctx
->ovs
, bridge
->br_cfg
);
1470 output_sorted(struct svec
*svec
, struct ds
*output
)
1476 SVEC_FOR_EACH (i
, name
, svec
) {
1477 ds_put_format(output
, "%s\n", name
);
1482 cmd_list_br(struct vsctl_context
*ctx
)
1484 struct shash_node
*node
;
1485 struct vsctl_info info
;
1486 struct svec bridges
;
1488 get_info(ctx
, &info
);
1490 svec_init(&bridges
);
1491 SHASH_FOR_EACH (node
, &info
.bridges
) {
1492 struct vsctl_bridge
*br
= node
->data
;
1493 svec_add(&bridges
, br
->name
);
1495 output_sorted(&bridges
, &ctx
->output
);
1496 svec_destroy(&bridges
);
1502 cmd_br_exists(struct vsctl_context
*ctx
)
1504 struct vsctl_info info
;
1506 get_info(ctx
, &info
);
1507 if (!find_bridge(&info
, ctx
->argv
[1], false)) {
1513 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
1514 * equals 'a', false otherwise. */
1516 key_matches(const char *a
,
1517 const char *b_prefix
, size_t b_prefix_len
, const char *b
)
1519 return !strncmp(a
, b_prefix
, b_prefix_len
) && !strcmp(a
+ b_prefix_len
, b
);
1523 set_external_id(char **old_keys
, char **old_values
, size_t old_n
,
1524 char *key
, char *value
,
1525 char ***new_keysp
, char ***new_valuesp
, size_t *new_np
)
1532 new_keys
= xmalloc(sizeof *new_keys
* (old_n
+ 1));
1533 new_values
= xmalloc(sizeof *new_values
* (old_n
+ 1));
1535 for (i
= 0; i
< old_n
; i
++) {
1536 if (strcmp(key
, old_keys
[i
])) {
1537 new_keys
[new_n
] = old_keys
[i
];
1538 new_values
[new_n
] = old_values
[i
];
1543 new_keys
[new_n
] = key
;
1544 new_values
[new_n
] = value
;
1547 *new_keysp
= new_keys
;
1548 *new_valuesp
= new_values
;
1553 pre_cmd_br_set_external_id(struct vsctl_context
*ctx
)
1556 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_bridge_col_external_ids
);
1557 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_port_col_external_ids
);
1561 cmd_br_set_external_id(struct vsctl_context
*ctx
)
1563 struct vsctl_info info
;
1564 struct vsctl_bridge
*bridge
;
1565 char **keys
, **values
;
1568 get_info(ctx
, &info
);
1569 bridge
= find_bridge(&info
, ctx
->argv
[1], true);
1570 if (bridge
->br_cfg
) {
1571 set_external_id(bridge
->br_cfg
->key_external_ids
,
1572 bridge
->br_cfg
->value_external_ids
,
1573 bridge
->br_cfg
->n_external_ids
,
1574 ctx
->argv
[2], ctx
->argc
>= 4 ? ctx
->argv
[3] : NULL
,
1575 &keys
, &values
, &n
);
1576 ovsrec_bridge_verify_external_ids(bridge
->br_cfg
);
1577 ovsrec_bridge_set_external_ids(bridge
->br_cfg
, keys
, values
, n
);
1579 char *key
= xasprintf("fake-bridge-%s", ctx
->argv
[2]);
1580 struct vsctl_port
*port
= shash_find_data(&info
.ports
, ctx
->argv
[1]);
1581 set_external_id(port
->port_cfg
->key_external_ids
,
1582 port
->port_cfg
->value_external_ids
,
1583 port
->port_cfg
->n_external_ids
,
1584 key
, ctx
->argc
>= 4 ? ctx
->argv
[3] : NULL
,
1585 &keys
, &values
, &n
);
1586 ovsrec_port_verify_external_ids(port
->port_cfg
);
1587 ovsrec_port_set_external_ids(port
->port_cfg
, keys
, values
, n
);
1597 get_external_id(char **keys
, char **values
, size_t n
,
1598 const char *prefix
, const char *key
,
1601 size_t prefix_len
= strlen(prefix
);
1606 for (i
= 0; i
< n
; i
++) {
1607 if (!key
&& !strncmp(keys
[i
], prefix
, prefix_len
)) {
1608 svec_add_nocopy(&svec
, xasprintf("%s=%s",
1609 keys
[i
] + prefix_len
, values
[i
]));
1610 } else if (key
&& key_matches(keys
[i
], prefix
, prefix_len
, key
)) {
1611 svec_add(&svec
, values
[i
]);
1615 output_sorted(&svec
, output
);
1616 svec_destroy(&svec
);
1620 pre_cmd_br_get_external_id(struct vsctl_context
*ctx
)
1622 pre_cmd_br_set_external_id(ctx
);
1626 cmd_br_get_external_id(struct vsctl_context
*ctx
)
1628 struct vsctl_info info
;
1629 struct vsctl_bridge
*bridge
;
1631 get_info(ctx
, &info
);
1632 bridge
= find_bridge(&info
, ctx
->argv
[1], true);
1633 if (bridge
->br_cfg
) {
1634 ovsrec_bridge_verify_external_ids(bridge
->br_cfg
);
1635 get_external_id(bridge
->br_cfg
->key_external_ids
,
1636 bridge
->br_cfg
->value_external_ids
,
1637 bridge
->br_cfg
->n_external_ids
,
1638 "", ctx
->argc
>= 3 ? ctx
->argv
[2] : NULL
,
1641 struct vsctl_port
*port
= shash_find_data(&info
.ports
, ctx
->argv
[1]);
1642 ovsrec_port_verify_external_ids(port
->port_cfg
);
1643 get_external_id(port
->port_cfg
->key_external_ids
,
1644 port
->port_cfg
->value_external_ids
,
1645 port
->port_cfg
->n_external_ids
,
1646 "fake-bridge-", ctx
->argc
>= 3 ? ctx
->argv
[2] : NULL
, &ctx
->output
);
1653 cmd_list_ports(struct vsctl_context
*ctx
)
1655 struct vsctl_bridge
*br
;
1656 struct shash_node
*node
;
1657 struct vsctl_info info
;
1660 get_info(ctx
, &info
);
1661 br
= find_bridge(&info
, ctx
->argv
[1], true);
1662 ovsrec_bridge_verify_ports(br
->br_cfg
? br
->br_cfg
: br
->parent
->br_cfg
);
1665 SHASH_FOR_EACH (node
, &info
.ports
) {
1666 struct vsctl_port
*port
= node
->data
;
1668 if (strcmp(port
->port_cfg
->name
, br
->name
) && br
== port
->bridge
) {
1669 svec_add(&ports
, port
->port_cfg
->name
);
1672 output_sorted(&ports
, &ctx
->output
);
1673 svec_destroy(&ports
);
1679 add_port(struct vsctl_context
*ctx
,
1680 const char *br_name
, const char *port_name
,
1681 bool may_exist
, bool fake_iface
,
1682 char *iface_names
[], int n_ifaces
,
1683 char *settings
[], int n_settings
)
1685 struct vsctl_info info
;
1686 struct vsctl_bridge
*bridge
;
1687 struct ovsrec_interface
**ifaces
;
1688 struct ovsrec_port
*port
;
1691 get_info(ctx
, &info
);
1693 struct vsctl_port
*vsctl_port
;
1695 vsctl_port
= find_port(&info
, port_name
, false);
1697 struct svec want_names
, have_names
;
1699 svec_init(&want_names
);
1700 for (i
= 0; i
< n_ifaces
; i
++) {
1701 svec_add(&want_names
, iface_names
[i
]);
1703 svec_sort(&want_names
);
1705 svec_init(&have_names
);
1706 for (i
= 0; i
< vsctl_port
->port_cfg
->n_interfaces
; i
++) {
1707 svec_add(&have_names
,
1708 vsctl_port
->port_cfg
->interfaces
[i
]->name
);
1710 svec_sort(&have_names
);
1712 if (strcmp(vsctl_port
->bridge
->name
, br_name
)) {
1713 char *command
= vsctl_context_to_string(ctx
);
1714 vsctl_fatal("\"%s\" but %s is actually attached to bridge %s",
1715 command
, port_name
, vsctl_port
->bridge
->name
);
1718 if (!svec_equal(&want_names
, &have_names
)) {
1719 char *have_names_string
= svec_join(&have_names
, ", ", "");
1720 char *command
= vsctl_context_to_string(ctx
);
1722 vsctl_fatal("\"%s\" but %s actually has interface(s) %s",
1723 command
, port_name
, have_names_string
);
1726 svec_destroy(&want_names
);
1727 svec_destroy(&have_names
);
1732 check_conflicts(&info
, port_name
,
1733 xasprintf("cannot create a port named %s", port_name
));
1734 for (i
= 0; i
< n_ifaces
; i
++) {
1735 check_conflicts(&info
, iface_names
[i
],
1736 xasprintf("cannot create an interface named %s",
1739 bridge
= find_bridge(&info
, br_name
, true);
1741 ifaces
= xmalloc(n_ifaces
* sizeof *ifaces
);
1742 for (i
= 0; i
< n_ifaces
; i
++) {
1743 ifaces
[i
] = ovsrec_interface_insert(ctx
->txn
);
1744 ovsrec_interface_set_name(ifaces
[i
], iface_names
[i
]);
1747 port
= ovsrec_port_insert(ctx
->txn
);
1748 ovsrec_port_set_name(port
, port_name
);
1749 ovsrec_port_set_interfaces(port
, ifaces
, n_ifaces
);
1750 ovsrec_port_set_bond_fake_iface(port
, fake_iface
);
1754 int64_t tag
= bridge
->vlan
;
1755 ovsrec_port_set_tag(port
, &tag
, 1);
1758 for (i
= 0; i
< n_settings
; i
++) {
1759 set_column(get_table("Port"), &port
->header_
, settings
[i
],
1763 bridge_insert_port((bridge
->parent
? bridge
->parent
->br_cfg
1764 : bridge
->br_cfg
), port
);
1770 cmd_add_port(struct vsctl_context
*ctx
)
1772 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
1774 add_port(ctx
, ctx
->argv
[1], ctx
->argv
[2], may_exist
, false,
1775 &ctx
->argv
[2], 1, &ctx
->argv
[3], ctx
->argc
- 3);
1779 cmd_add_bond(struct vsctl_context
*ctx
)
1781 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
1782 bool fake_iface
= shash_find(&ctx
->options
, "--fake-iface");
1786 n_ifaces
= ctx
->argc
- 3;
1787 for (i
= 3; i
< ctx
->argc
; i
++) {
1788 if (strchr(ctx
->argv
[i
], '=')) {
1794 vsctl_fatal("add-bond requires at least 2 interfaces, but only "
1795 "%d were specified", n_ifaces
);
1798 add_port(ctx
, ctx
->argv
[1], ctx
->argv
[2], may_exist
, fake_iface
,
1799 &ctx
->argv
[3], n_ifaces
,
1800 &ctx
->argv
[n_ifaces
+ 3], ctx
->argc
- 3 - n_ifaces
);
1804 cmd_del_port(struct vsctl_context
*ctx
)
1806 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1807 bool with_iface
= shash_find(&ctx
->options
, "--with-iface") != NULL
;
1808 struct vsctl_port
*port
;
1809 struct vsctl_info info
;
1811 get_info(ctx
, &info
);
1813 port
= find_port(&info
, ctx
->argv
[ctx
->argc
- 1], must_exist
);
1815 const char *target
= ctx
->argv
[ctx
->argc
- 1];
1816 struct vsctl_iface
*iface
;
1818 port
= find_port(&info
, target
, false);
1820 iface
= find_iface(&info
, target
, false);
1825 if (must_exist
&& !port
) {
1826 vsctl_fatal("no port or interface named %s", target
);
1831 if (ctx
->argc
== 3) {
1832 struct vsctl_bridge
*bridge
;
1834 bridge
= find_bridge(&info
, ctx
->argv
[1], true);
1835 if (port
->bridge
!= bridge
) {
1836 if (port
->bridge
->parent
== bridge
) {
1837 vsctl_fatal("bridge %s does not have a port %s (although "
1838 "its parent bridge %s does)",
1839 ctx
->argv
[1], ctx
->argv
[2],
1840 bridge
->parent
->name
);
1842 vsctl_fatal("bridge %s does not have a port %s",
1843 ctx
->argv
[1], ctx
->argv
[2]);
1848 del_port(&info
, port
);
1855 cmd_port_to_br(struct vsctl_context
*ctx
)
1857 struct vsctl_port
*port
;
1858 struct vsctl_info info
;
1860 get_info(ctx
, &info
);
1861 port
= find_port(&info
, ctx
->argv
[1], true);
1862 ds_put_format(&ctx
->output
, "%s\n", port
->bridge
->name
);
1867 cmd_br_to_vlan(struct vsctl_context
*ctx
)
1869 struct vsctl_bridge
*bridge
;
1870 struct vsctl_info info
;
1872 get_info(ctx
, &info
);
1873 bridge
= find_bridge(&info
, ctx
->argv
[1], true);
1874 ds_put_format(&ctx
->output
, "%d\n", bridge
->vlan
);
1879 cmd_br_to_parent(struct vsctl_context
*ctx
)
1881 struct vsctl_bridge
*bridge
;
1882 struct vsctl_info info
;
1884 get_info(ctx
, &info
);
1885 bridge
= find_bridge(&info
, ctx
->argv
[1], true);
1886 if (bridge
->parent
) {
1887 bridge
= bridge
->parent
;
1889 ds_put_format(&ctx
->output
, "%s\n", bridge
->name
);
1894 cmd_list_ifaces(struct vsctl_context
*ctx
)
1896 struct vsctl_bridge
*br
;
1897 struct shash_node
*node
;
1898 struct vsctl_info info
;
1901 get_info(ctx
, &info
);
1902 br
= find_bridge(&info
, ctx
->argv
[1], true);
1906 SHASH_FOR_EACH (node
, &info
.ifaces
) {
1907 struct vsctl_iface
*iface
= node
->data
;
1909 if (strcmp(iface
->iface_cfg
->name
, br
->name
)
1910 && br
== iface
->port
->bridge
) {
1911 svec_add(&ifaces
, iface
->iface_cfg
->name
);
1914 output_sorted(&ifaces
, &ctx
->output
);
1915 svec_destroy(&ifaces
);
1921 cmd_iface_to_br(struct vsctl_context
*ctx
)
1923 struct vsctl_iface
*iface
;
1924 struct vsctl_info info
;
1926 get_info(ctx
, &info
);
1927 iface
= find_iface(&info
, ctx
->argv
[1], true);
1928 ds_put_format(&ctx
->output
, "%s\n", iface
->port
->bridge
->name
);
1933 verify_controllers(struct ovsrec_bridge
*bridge
)
1938 ovsrec_bridge_verify_controller(bridge
);
1939 for (i
= 0; i
< bridge
->n_controller
; i
++) {
1940 ovsrec_controller_verify_target(bridge
->controller
[i
]);
1946 pre_controller(struct vsctl_context
*ctx
)
1950 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_controller_col_target
);
1954 cmd_get_controller(struct vsctl_context
*ctx
)
1956 struct vsctl_info info
;
1957 struct vsctl_bridge
*br
;
1958 struct svec targets
;
1961 get_info(ctx
, &info
);
1962 br
= find_bridge(&info
, ctx
->argv
[1], true);
1963 verify_controllers(br
->br_cfg
);
1965 /* Print the targets in sorted order for reproducibility. */
1966 svec_init(&targets
);
1967 for (i
= 0; i
< br
->n_ctrl
; i
++) {
1968 svec_add(&targets
, br
->ctrl
[i
]->target
);
1971 svec_sort(&targets
);
1972 for (i
= 0; i
< targets
.n
; i
++) {
1973 ds_put_format(&ctx
->output
, "%s\n", targets
.names
[i
]);
1975 svec_destroy(&targets
);
1981 delete_controllers(struct ovsrec_controller
**controllers
,
1982 size_t n_controllers
)
1986 for (i
= 0; i
< n_controllers
; i
++) {
1987 ovsrec_controller_delete(controllers
[i
]);
1992 cmd_del_controller(struct vsctl_context
*ctx
)
1994 struct vsctl_info info
;
1995 struct vsctl_bridge
*br
;
1997 get_info(ctx
, &info
);
1999 br
= find_real_bridge(&info
, ctx
->argv
[1], true);
2000 verify_controllers(br
->br_cfg
);
2003 delete_controllers(br
->ctrl
, br
->n_ctrl
);
2004 ovsrec_bridge_set_controller(br
->br_cfg
, NULL
, 0);
2010 static struct ovsrec_controller
**
2011 insert_controllers(struct ovsdb_idl_txn
*txn
, char *targets
[], size_t n
)
2013 struct ovsrec_controller
**controllers
;
2016 controllers
= xmalloc(n
* sizeof *controllers
);
2017 for (i
= 0; i
< n
; i
++) {
2018 if (vconn_verify_name(targets
[i
]) && pvconn_verify_name(targets
[i
])) {
2019 VLOG_WARN("target type \"%s\" is possibly erroneous", targets
[i
]);
2021 controllers
[i
] = ovsrec_controller_insert(txn
);
2022 ovsrec_controller_set_target(controllers
[i
], targets
[i
]);
2029 cmd_set_controller(struct vsctl_context
*ctx
)
2031 struct vsctl_info info
;
2032 struct vsctl_bridge
*br
;
2033 struct ovsrec_controller
**controllers
;
2036 get_info(ctx
, &info
);
2037 br
= find_real_bridge(&info
, ctx
->argv
[1], true);
2038 verify_controllers(br
->br_cfg
);
2040 delete_controllers(br
->ctrl
, br
->n_ctrl
);
2043 controllers
= insert_controllers(ctx
->txn
, &ctx
->argv
[2], n
);
2044 ovsrec_bridge_set_controller(br
->br_cfg
, controllers
, n
);
2051 cmd_get_fail_mode(struct vsctl_context
*ctx
)
2053 struct vsctl_info info
;
2054 struct vsctl_bridge
*br
;
2056 get_info(ctx
, &info
);
2057 br
= find_bridge(&info
, ctx
->argv
[1], true);
2060 ovsrec_bridge_verify_fail_mode(br
->br_cfg
);
2062 if (br
->fail_mode
&& strlen(br
->fail_mode
)) {
2063 ds_put_format(&ctx
->output
, "%s\n", br
->fail_mode
);
2070 cmd_del_fail_mode(struct vsctl_context
*ctx
)
2072 struct vsctl_info info
;
2073 struct vsctl_bridge
*br
;
2075 get_info(ctx
, &info
);
2076 br
= find_real_bridge(&info
, ctx
->argv
[1], true);
2078 ovsrec_bridge_set_fail_mode(br
->br_cfg
, NULL
);
2084 cmd_set_fail_mode(struct vsctl_context
*ctx
)
2086 struct vsctl_info info
;
2087 struct vsctl_bridge
*br
;
2088 const char *fail_mode
= ctx
->argv
[2];
2090 get_info(ctx
, &info
);
2091 br
= find_real_bridge(&info
, ctx
->argv
[1], true);
2093 if (strcmp(fail_mode
, "standalone") && strcmp(fail_mode
, "secure")) {
2094 vsctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
2097 ovsrec_bridge_set_fail_mode(br
->br_cfg
, fail_mode
);
2103 verify_managers(const struct ovsrec_open_vswitch
*ovs
)
2107 ovsrec_open_vswitch_verify_manager_options(ovs
);
2109 for (i
= 0; i
< ovs
->n_manager_options
; ++i
) {
2110 const struct ovsrec_manager
*mgr
= ovs
->manager_options
[i
];
2112 ovsrec_manager_verify_target(mgr
);
2117 pre_manager(struct vsctl_context
*ctx
)
2119 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_manager_options
);
2120 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_manager_col_target
);
2124 cmd_get_manager(struct vsctl_context
*ctx
)
2126 const struct ovsrec_open_vswitch
*ovs
= ctx
->ovs
;
2127 struct svec targets
;
2130 verify_managers(ovs
);
2132 /* Print the targets in sorted order for reproducibility. */
2133 svec_init(&targets
);
2135 for (i
= 0; i
< ovs
->n_manager_options
; i
++) {
2136 svec_add(&targets
, ovs
->manager_options
[i
]->target
);
2139 svec_sort_unique(&targets
);
2140 for (i
= 0; i
< targets
.n
; i
++) {
2141 ds_put_format(&ctx
->output
, "%s\n", targets
.names
[i
]);
2143 svec_destroy(&targets
);
2147 delete_managers(const struct vsctl_context
*ctx
)
2149 const struct ovsrec_open_vswitch
*ovs
= ctx
->ovs
;
2152 /* Delete Manager rows pointed to by 'manager_options' column. */
2153 for (i
= 0; i
< ovs
->n_manager_options
; i
++) {
2154 ovsrec_manager_delete(ovs
->manager_options
[i
]);
2157 /* Delete 'Manager' row refs in 'manager_options' column. */
2158 ovsrec_open_vswitch_set_manager_options(ovs
, NULL
, 0);
2162 cmd_del_manager(struct vsctl_context
*ctx
)
2164 const struct ovsrec_open_vswitch
*ovs
= ctx
->ovs
;
2166 verify_managers(ovs
);
2167 delete_managers(ctx
);
2171 insert_managers(struct vsctl_context
*ctx
, char *targets
[], size_t n
)
2173 struct ovsrec_manager
**managers
;
2176 /* Insert each manager in a new row in Manager table. */
2177 managers
= xmalloc(n
* sizeof *managers
);
2178 for (i
= 0; i
< n
; i
++) {
2179 if (stream_verify_name(targets
[i
]) && pstream_verify_name(targets
[i
])) {
2180 VLOG_WARN("target type \"%s\" is possibly erroneous", targets
[i
]);
2182 managers
[i
] = ovsrec_manager_insert(ctx
->txn
);
2183 ovsrec_manager_set_target(managers
[i
], targets
[i
]);
2186 /* Store uuids of new Manager rows in 'manager_options' column. */
2187 ovsrec_open_vswitch_set_manager_options(ctx
->ovs
, managers
, n
);
2192 cmd_set_manager(struct vsctl_context
*ctx
)
2194 const size_t n
= ctx
->argc
- 1;
2196 verify_managers(ctx
->ovs
);
2197 delete_managers(ctx
);
2198 insert_managers(ctx
, &ctx
->argv
[1], n
);
2202 pre_cmd_get_ssl(struct vsctl_context
*ctx
)
2204 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_ssl
);
2206 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_ssl_col_private_key
);
2207 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_ssl_col_certificate
);
2208 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_ssl_col_ca_cert
);
2209 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_ssl_col_bootstrap_ca_cert
);
2213 cmd_get_ssl(struct vsctl_context
*ctx
)
2215 struct ovsrec_ssl
*ssl
= ctx
->ovs
->ssl
;
2217 ovsrec_open_vswitch_verify_ssl(ctx
->ovs
);
2219 ovsrec_ssl_verify_private_key(ssl
);
2220 ovsrec_ssl_verify_certificate(ssl
);
2221 ovsrec_ssl_verify_ca_cert(ssl
);
2222 ovsrec_ssl_verify_bootstrap_ca_cert(ssl
);
2224 ds_put_format(&ctx
->output
, "Private key: %s\n", ssl
->private_key
);
2225 ds_put_format(&ctx
->output
, "Certificate: %s\n", ssl
->certificate
);
2226 ds_put_format(&ctx
->output
, "CA Certificate: %s\n", ssl
->ca_cert
);
2227 ds_put_format(&ctx
->output
, "Bootstrap: %s\n",
2228 ssl
->bootstrap_ca_cert
? "true" : "false");
2233 pre_cmd_del_ssl(struct vsctl_context
*ctx
)
2235 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_ssl
);
2239 cmd_del_ssl(struct vsctl_context
*ctx
)
2241 struct ovsrec_ssl
*ssl
= ctx
->ovs
->ssl
;
2244 ovsrec_open_vswitch_verify_ssl(ctx
->ovs
);
2245 ovsrec_ssl_delete(ssl
);
2246 ovsrec_open_vswitch_set_ssl(ctx
->ovs
, NULL
);
2251 pre_cmd_set_ssl(struct vsctl_context
*ctx
)
2253 ovsdb_idl_add_column(ctx
->idl
, &ovsrec_open_vswitch_col_ssl
);
2257 cmd_set_ssl(struct vsctl_context
*ctx
)
2259 bool bootstrap
= shash_find(&ctx
->options
, "--bootstrap");
2260 struct ovsrec_ssl
*ssl
= ctx
->ovs
->ssl
;
2262 ovsrec_open_vswitch_verify_ssl(ctx
->ovs
);
2264 ovsrec_ssl_delete(ssl
);
2266 ssl
= ovsrec_ssl_insert(ctx
->txn
);
2268 ovsrec_ssl_set_private_key(ssl
, ctx
->argv
[1]);
2269 ovsrec_ssl_set_certificate(ssl
, ctx
->argv
[2]);
2270 ovsrec_ssl_set_ca_cert(ssl
, ctx
->argv
[3]);
2272 ovsrec_ssl_set_bootstrap_ca_cert(ssl
, bootstrap
);
2274 ovsrec_open_vswitch_set_ssl(ctx
->ovs
, ssl
);
2277 /* Parameter commands. */
2279 struct vsctl_row_id
{
2280 const struct ovsdb_idl_table_class
*table
;
2281 const struct ovsdb_idl_column
*name_column
;
2282 const struct ovsdb_idl_column
*uuid_column
;
2285 struct vsctl_table_class
{
2286 struct ovsdb_idl_table_class
*class;
2287 struct vsctl_row_id row_ids
[2];
2290 static const struct vsctl_table_class tables
[] = {
2291 {&ovsrec_table_bridge
,
2292 {{&ovsrec_table_bridge
, &ovsrec_bridge_col_name
, NULL
},
2293 {NULL
, NULL
, NULL
}}},
2295 {&ovsrec_table_controller
,
2296 {{&ovsrec_table_bridge
,
2297 &ovsrec_bridge_col_name
,
2298 &ovsrec_bridge_col_controller
}}},
2300 {&ovsrec_table_interface
,
2301 {{&ovsrec_table_interface
, &ovsrec_interface_col_name
, NULL
},
2302 {NULL
, NULL
, NULL
}}},
2304 {&ovsrec_table_mirror
,
2305 {{&ovsrec_table_mirror
, &ovsrec_mirror_col_name
, NULL
},
2306 {NULL
, NULL
, NULL
}}},
2308 {&ovsrec_table_manager
,
2309 {{&ovsrec_table_manager
, &ovsrec_manager_col_target
, NULL
},
2310 {NULL
, NULL
, NULL
}}},
2312 {&ovsrec_table_netflow
,
2313 {{&ovsrec_table_bridge
,
2314 &ovsrec_bridge_col_name
,
2315 &ovsrec_bridge_col_netflow
},
2316 {NULL
, NULL
, NULL
}}},
2318 {&ovsrec_table_open_vswitch
,
2319 {{&ovsrec_table_open_vswitch
, NULL
, NULL
},
2320 {NULL
, NULL
, NULL
}}},
2322 {&ovsrec_table_port
,
2323 {{&ovsrec_table_port
, &ovsrec_port_col_name
, NULL
},
2324 {NULL
, NULL
, NULL
}}},
2327 {{&ovsrec_table_port
, &ovsrec_port_col_name
, &ovsrec_port_col_qos
},
2328 {NULL
, NULL
, NULL
}}},
2330 {&ovsrec_table_queue
,
2331 {{NULL
, NULL
, NULL
},
2332 {NULL
, NULL
, NULL
}}},
2335 {{&ovsrec_table_open_vswitch
, NULL
, &ovsrec_open_vswitch_col_ssl
}}},
2337 {&ovsrec_table_sflow
,
2338 {{&ovsrec_table_bridge
,
2339 &ovsrec_bridge_col_name
,
2340 &ovsrec_bridge_col_sflow
},
2341 {NULL
, NULL
, NULL
}}},
2343 {&ovsrec_table_flow_table
,
2344 {{&ovsrec_table_flow_table
, &ovsrec_flow_table_col_name
, NULL
},
2345 {NULL
, NULL
, NULL
}}},
2347 {NULL
, {{NULL
, NULL
, NULL
}, {NULL
, NULL
, NULL
}}}
2351 die_if_error(char *error
)
2354 vsctl_fatal("%s", error
);
2359 to_lower_and_underscores(unsigned c
)
2361 return c
== '-' ? '_' : tolower(c
);
2365 score_partial_match(const char *name
, const char *s
)
2369 if (!strcmp(name
, s
)) {
2372 for (score
= 0; ; score
++, name
++, s
++) {
2373 if (to_lower_and_underscores(*name
) != to_lower_and_underscores(*s
)) {
2375 } else if (*name
== '\0') {
2376 return UINT_MAX
- 1;
2379 return *s
== '\0' ? score
: 0;
2382 static const struct vsctl_table_class
*
2383 get_table(const char *table_name
)
2385 const struct vsctl_table_class
*table
;
2386 const struct vsctl_table_class
*best_match
= NULL
;
2387 unsigned int best_score
= 0;
2389 for (table
= tables
; table
->class; table
++) {
2390 unsigned int score
= score_partial_match(table
->class->name
,
2392 if (score
> best_score
) {
2395 } else if (score
== best_score
) {
2401 } else if (best_score
) {
2402 vsctl_fatal("multiple table names match \"%s\"", table_name
);
2404 vsctl_fatal("unknown table \"%s\"", table_name
);
2408 static const struct vsctl_table_class
*
2409 pre_get_table(struct vsctl_context
*ctx
, const char *table_name
)
2411 const struct vsctl_table_class
*table_class
;
2414 table_class
= get_table(table_name
);
2415 ovsdb_idl_add_table(ctx
->idl
, table_class
->class);
2417 for (i
= 0; i
< ARRAY_SIZE(table_class
->row_ids
); i
++) {
2418 const struct vsctl_row_id
*id
= &table_class
->row_ids
[i
];
2420 ovsdb_idl_add_table(ctx
->idl
, id
->table
);
2422 if (id
->name_column
) {
2423 ovsdb_idl_add_column(ctx
->idl
, id
->name_column
);
2425 if (id
->uuid_column
) {
2426 ovsdb_idl_add_column(ctx
->idl
, id
->uuid_column
);
2433 static const struct ovsdb_idl_row
*
2434 get_row_by_id(struct vsctl_context
*ctx
, const struct vsctl_table_class
*table
,
2435 const struct vsctl_row_id
*id
, const char *record_id
)
2437 const struct ovsdb_idl_row
*referrer
, *final
;
2443 if (!id
->name_column
) {
2444 if (strcmp(record_id
, ".")) {
2447 referrer
= ovsdb_idl_first_row(ctx
->idl
, id
->table
);
2448 if (!referrer
|| ovsdb_idl_next_row(referrer
)) {
2452 const struct ovsdb_idl_row
*row
;
2455 for (row
= ovsdb_idl_first_row(ctx
->idl
, id
->table
);
2457 row
= ovsdb_idl_next_row(row
))
2459 const struct ovsdb_datum
*name
;
2461 name
= ovsdb_idl_get(row
, id
->name_column
,
2462 OVSDB_TYPE_STRING
, OVSDB_TYPE_VOID
);
2463 if (name
->n
== 1 && !strcmp(name
->keys
[0].string
, record_id
)) {
2465 vsctl_fatal("multiple rows in %s match \"%s\"",
2466 table
->class->name
, record_id
);
2477 if (id
->uuid_column
) {
2478 const struct ovsdb_datum
*uuid
;
2480 ovsdb_idl_txn_verify(referrer
, id
->uuid_column
);
2481 uuid
= ovsdb_idl_get(referrer
, id
->uuid_column
,
2482 OVSDB_TYPE_UUID
, OVSDB_TYPE_VOID
);
2484 final
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
->class,
2485 &uuid
->keys
[0].uuid
);
2494 static const struct ovsdb_idl_row
*
2495 get_row (struct vsctl_context
*ctx
,
2496 const struct vsctl_table_class
*table
, const char *record_id
)
2498 const struct ovsdb_idl_row
*row
;
2501 if (uuid_from_string(&uuid
, record_id
)) {
2502 row
= ovsdb_idl_get_row_for_uuid(ctx
->idl
, table
->class, &uuid
);
2506 for (i
= 0; i
< ARRAY_SIZE(table
->row_ids
); i
++) {
2507 row
= get_row_by_id(ctx
, table
, &table
->row_ids
[i
], record_id
);
2516 static const struct ovsdb_idl_row
*
2517 must_get_row(struct vsctl_context
*ctx
,
2518 const struct vsctl_table_class
*table
, const char *record_id
)
2520 const struct ovsdb_idl_row
*row
= get_row(ctx
, table
, record_id
);
2522 vsctl_fatal("no row \"%s\" in table %s",
2523 record_id
, table
->class->name
);
2529 get_column(const struct vsctl_table_class
*table
, const char *column_name
,
2530 const struct ovsdb_idl_column
**columnp
)
2532 const struct ovsdb_idl_column
*best_match
= NULL
;
2533 unsigned int best_score
= 0;
2536 for (i
= 0; i
< table
->class->n_columns
; i
++) {
2537 const struct ovsdb_idl_column
*column
= &table
->class->columns
[i
];
2538 unsigned int score
= score_partial_match(column
->name
, column_name
);
2539 if (score
> best_score
) {
2540 best_match
= column
;
2542 } else if (score
== best_score
) {
2547 *columnp
= best_match
;
2550 } else if (best_score
) {
2551 return xasprintf("%s contains more than one column whose name "
2552 "matches \"%s\"", table
->class->name
, column_name
);
2554 return xasprintf("%s does not contain a column whose name matches "
2555 "\"%s\"", table
->class->name
, column_name
);
2559 static struct ovsdb_symbol
*
2560 create_symbol(struct ovsdb_symbol_table
*symtab
, const char *id
, bool *newp
)
2562 struct ovsdb_symbol
*symbol
;
2565 vsctl_fatal("row id \"%s\" does not begin with \"@\"", id
);
2569 *newp
= ovsdb_symbol_table_get(symtab
, id
) == NULL
;
2572 symbol
= ovsdb_symbol_table_insert(symtab
, id
);
2573 if (symbol
->created
) {
2574 vsctl_fatal("row id \"%s\" may only be specified on one --id option",
2577 symbol
->created
= true;
2582 pre_get_column(struct vsctl_context
*ctx
,
2583 const struct vsctl_table_class
*table
, const char *column_name
,
2584 const struct ovsdb_idl_column
**columnp
)
2586 die_if_error(get_column(table
, column_name
, columnp
));
2587 ovsdb_idl_add_column(ctx
->idl
, *columnp
);
2591 missing_operator_error(const char *arg
, const char **allowed_operators
,
2597 ds_put_format(&s
, "%s: argument does not end in ", arg
);
2598 ds_put_format(&s
, "\"%s\"", allowed_operators
[0]);
2599 if (n_allowed
== 2) {
2600 ds_put_format(&s
, " or \"%s\"", allowed_operators
[1]);
2601 } else if (n_allowed
> 2) {
2604 for (i
= 1; i
< n_allowed
- 1; i
++) {
2605 ds_put_format(&s
, ", \"%s\"", allowed_operators
[i
]);
2607 ds_put_format(&s
, ", or \"%s\"", allowed_operators
[i
]);
2609 ds_put_format(&s
, " followed by a value.");
2611 return ds_steal_cstr(&s
);
2614 /* Breaks 'arg' apart into a number of fields in the following order:
2616 * - The name of a column in 'table', stored into '*columnp'. The column
2617 * name may be abbreviated.
2619 * - Optionally ':' followed by a key string. The key is stored as a
2620 * malloc()'d string into '*keyp', or NULL if no key is present in
2623 * - If 'valuep' is nonnull, an operator followed by a value string. The
2624 * allowed operators are the 'n_allowed' string in 'allowed_operators',
2625 * or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
2626 * index of the operator within 'allowed_operators' is stored into
2627 * '*operatorp'. The value is stored as a malloc()'d string into
2628 * '*valuep', or NULL if no value is present in 'arg'.
2630 * On success, returns NULL. On failure, returned a malloc()'d string error
2631 * message and stores NULL into all of the nonnull output arguments. */
2632 static char * WARN_UNUSED_RESULT
2633 parse_column_key_value(const char *arg
,
2634 const struct vsctl_table_class
*table
,
2635 const struct ovsdb_idl_column
**columnp
, char **keyp
,
2637 const char **allowed_operators
, size_t n_allowed
,
2640 const char *p
= arg
;
2644 assert(!(operatorp
&& !valuep
));
2650 /* Parse column name. */
2651 error
= ovsdb_token_parse(&p
, &column_name
);
2655 if (column_name
[0] == '\0') {
2657 error
= xasprintf("%s: missing column name", arg
);
2660 error
= get_column(table
, column_name
, columnp
);
2666 /* Parse key string. */
2669 error
= ovsdb_token_parse(&p
, keyp
);
2675 /* Parse value string. */
2681 if (!allowed_operators
) {
2682 static const char *equals
= "=";
2683 allowed_operators
= &equals
;
2689 for (i
= 0; i
< n_allowed
; i
++) {
2690 const char *op
= allowed_operators
[i
];
2691 size_t op_len
= strlen(op
);
2693 if (op_len
> best_len
&& !strncmp(op
, p
, op_len
) && p
[op_len
]) {
2699 error
= missing_operator_error(arg
, allowed_operators
, n_allowed
);
2706 *valuep
= xstrdup(p
+ best_len
);
2709 error
= xasprintf("%s: trailing garbage \"%s\" in argument",
2731 pre_parse_column_key_value(struct vsctl_context
*ctx
,
2733 const struct vsctl_table_class
*table
)
2735 const struct ovsdb_idl_column
*column
;
2740 die_if_error(ovsdb_token_parse(&p
, &column_name
));
2741 if (column_name
[0] == '\0') {
2742 vsctl_fatal("%s: missing column name", arg
);
2745 pre_get_column(ctx
, table
, column_name
, &column
);
2750 pre_cmd_get(struct vsctl_context
*ctx
)
2752 const char *id
= shash_find_data(&ctx
->options
, "--id");
2753 const char *table_name
= ctx
->argv
[1];
2754 const struct vsctl_table_class
*table
;
2757 /* Using "get" without --id or a column name could possibly make sense.
2758 * Maybe, for example, a ovs-vsctl run wants to assert that a row exists.
2759 * But it is unlikely that an interactive user would want to do that, so
2760 * issue a warning if we're running on a terminal. */
2761 if (!id
&& ctx
->argc
<= 3 && isatty(STDOUT_FILENO
)) {
2762 VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
2763 "possibly erroneous");
2766 table
= pre_get_table(ctx
, table_name
);
2767 for (i
= 3; i
< ctx
->argc
; i
++) {
2768 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
2769 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
2773 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
2778 cmd_get(struct vsctl_context
*ctx
)
2780 const char *id
= shash_find_data(&ctx
->options
, "--id");
2781 bool if_exists
= shash_find(&ctx
->options
, "--if-exists");
2782 const char *table_name
= ctx
->argv
[1];
2783 const char *record_id
= ctx
->argv
[2];
2784 const struct vsctl_table_class
*table
;
2785 const struct ovsdb_idl_row
*row
;
2786 struct ds
*out
= &ctx
->output
;
2789 table
= get_table(table_name
);
2790 row
= must_get_row(ctx
, table
, record_id
);
2792 struct ovsdb_symbol
*symbol
;
2795 symbol
= create_symbol(ctx
->symtab
, id
, &new);
2797 vsctl_fatal("row id \"%s\" specified on \"get\" command was used "
2798 "before it was defined", id
);
2800 symbol
->uuid
= row
->uuid
;
2802 /* This symbol refers to a row that already exists, so disable warnings
2803 * about it being unreferenced. */
2804 symbol
->strong_ref
= true;
2806 for (i
= 3; i
< ctx
->argc
; i
++) {
2807 const struct ovsdb_idl_column
*column
;
2808 const struct ovsdb_datum
*datum
;
2811 /* Special case for obtaining the UUID of a row. We can't just do this
2812 * through parse_column_key_value() below since it returns a "struct
2813 * ovsdb_idl_column" and the UUID column doesn't have one. */
2814 if (!strcasecmp(ctx
->argv
[i
], "_uuid")
2815 || !strcasecmp(ctx
->argv
[i
], "-uuid")) {
2816 ds_put_format(out
, UUID_FMT
"\n", UUID_ARGS(&row
->uuid
));
2820 die_if_error(parse_column_key_value(ctx
->argv
[i
], table
,
2821 &column
, &key_string
,
2822 NULL
, NULL
, 0, NULL
));
2824 ovsdb_idl_txn_verify(row
, column
);
2825 datum
= ovsdb_idl_read(row
, column
);
2827 union ovsdb_atom key
;
2830 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
2831 vsctl_fatal("cannot specify key to get for non-map column %s",
2835 die_if_error(ovsdb_atom_from_string(&key
,
2837 key_string
, ctx
->symtab
));
2839 idx
= ovsdb_datum_find_key(datum
, &key
,
2840 column
->type
.key
.type
);
2841 if (idx
== UINT_MAX
) {
2843 vsctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
2844 key_string
, table
->class->name
, record_id
,
2848 ovsdb_atom_to_string(&datum
->values
[idx
],
2849 column
->type
.value
.type
, out
);
2851 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
2853 ovsdb_datum_to_string(datum
, &column
->type
, out
);
2855 ds_put_char(out
, '\n');
2862 parse_column_names(const char *column_names
,
2863 const struct vsctl_table_class
*table
,
2864 const struct ovsdb_idl_column
***columnsp
,
2867 const struct ovsdb_idl_column
**columns
;
2870 if (!column_names
) {
2873 n_columns
= table
->class->n_columns
+ 1;
2874 columns
= xmalloc(n_columns
* sizeof *columns
);
2876 for (i
= 0; i
< table
->class->n_columns
; i
++) {
2877 columns
[i
+ 1] = &table
->class->columns
[i
];
2880 char *s
= xstrdup(column_names
);
2881 size_t allocated_columns
;
2882 char *save_ptr
= NULL
;
2886 allocated_columns
= n_columns
= 0;
2887 for (column_name
= strtok_r(s
, ", ", &save_ptr
); column_name
;
2888 column_name
= strtok_r(NULL
, ", ", &save_ptr
)) {
2889 const struct ovsdb_idl_column
*column
;
2891 if (!strcasecmp(column_name
, "_uuid")) {
2894 die_if_error(get_column(table
, column_name
, &column
));
2896 if (n_columns
>= allocated_columns
) {
2897 columns
= x2nrealloc(columns
, &allocated_columns
,
2900 columns
[n_columns
++] = column
;
2905 vsctl_fatal("must specify at least one column name");
2908 *columnsp
= columns
;
2909 *n_columnsp
= n_columns
;
2914 pre_list_columns(struct vsctl_context
*ctx
,
2915 const struct vsctl_table_class
*table
,
2916 const char *column_names
)
2918 const struct ovsdb_idl_column
**columns
;
2922 parse_column_names(column_names
, table
, &columns
, &n_columns
);
2923 for (i
= 0; i
< n_columns
; i
++) {
2925 ovsdb_idl_add_column(ctx
->idl
, columns
[i
]);
2932 pre_cmd_list(struct vsctl_context
*ctx
)
2934 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
2935 const char *table_name
= ctx
->argv
[1];
2936 const struct vsctl_table_class
*table
;
2938 table
= pre_get_table(ctx
, table_name
);
2939 pre_list_columns(ctx
, table
, column_names
);
2942 static struct table
*
2943 list_make_table(const struct ovsdb_idl_column
**columns
, size_t n_columns
)
2948 out
= xmalloc(sizeof *out
);
2951 for (i
= 0; i
< n_columns
; i
++) {
2952 const struct ovsdb_idl_column
*column
= columns
[i
];
2953 const char *column_name
= column
? column
->name
: "_uuid";
2955 table_add_column(out
, "%s", column_name
);
2962 list_record(const struct ovsdb_idl_row
*row
,
2963 const struct ovsdb_idl_column
**columns
, size_t n_columns
,
2969 for (i
= 0; i
< n_columns
; i
++) {
2970 const struct ovsdb_idl_column
*column
= columns
[i
];
2971 struct cell
*cell
= table_add_cell(out
);
2974 struct ovsdb_datum datum
;
2975 union ovsdb_atom atom
;
2977 atom
.uuid
= row
->uuid
;
2980 datum
.values
= NULL
;
2983 cell
->json
= ovsdb_datum_to_json(&datum
, &ovsdb_type_uuid
);
2984 cell
->type
= &ovsdb_type_uuid
;
2986 const struct ovsdb_datum
*datum
= ovsdb_idl_read(row
, column
);
2988 cell
->json
= ovsdb_datum_to_json(datum
, &column
->type
);
2989 cell
->type
= &column
->type
;
2995 cmd_list(struct vsctl_context
*ctx
)
2997 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
2998 const struct ovsdb_idl_column
**columns
;
2999 const char *table_name
= ctx
->argv
[1];
3000 const struct vsctl_table_class
*table
;
3005 table
= get_table(table_name
);
3006 parse_column_names(column_names
, table
, &columns
, &n_columns
);
3007 out
= ctx
->table
= list_make_table(columns
, n_columns
);
3008 if (ctx
->argc
> 2) {
3009 for (i
= 2; i
< ctx
->argc
; i
++) {
3010 list_record(must_get_row(ctx
, table
, ctx
->argv
[i
]),
3011 columns
, n_columns
, out
);
3014 const struct ovsdb_idl_row
*row
;
3016 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
->class); row
!= NULL
;
3017 row
= ovsdb_idl_next_row(row
)) {
3018 list_record(row
, columns
, n_columns
, out
);
3025 pre_cmd_find(struct vsctl_context
*ctx
)
3027 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
3028 const char *table_name
= ctx
->argv
[1];
3029 const struct vsctl_table_class
*table
;
3032 table
= pre_get_table(ctx
, table_name
);
3033 pre_list_columns(ctx
, table
, column_names
);
3034 for (i
= 2; i
< ctx
->argc
; i
++) {
3035 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
3040 cmd_find(struct vsctl_context
*ctx
)
3042 const char *column_names
= shash_find_data(&ctx
->options
, "--columns");
3043 const struct ovsdb_idl_column
**columns
;
3044 const char *table_name
= ctx
->argv
[1];
3045 const struct vsctl_table_class
*table
;
3046 const struct ovsdb_idl_row
*row
;
3050 table
= get_table(table_name
);
3051 parse_column_names(column_names
, table
, &columns
, &n_columns
);
3052 out
= ctx
->table
= list_make_table(columns
, n_columns
);
3053 for (row
= ovsdb_idl_first_row(ctx
->idl
, table
->class); row
;
3054 row
= ovsdb_idl_next_row(row
)) {
3057 for (i
= 2; i
< ctx
->argc
; i
++) {
3058 if (!is_condition_satisfied(table
, row
, ctx
->argv
[i
],
3063 list_record(row
, columns
, n_columns
, out
);
3071 pre_cmd_set(struct vsctl_context
*ctx
)
3073 const char *table_name
= ctx
->argv
[1];
3074 const struct vsctl_table_class
*table
;
3077 table
= pre_get_table(ctx
, table_name
);
3078 for (i
= 3; i
< ctx
->argc
; i
++) {
3079 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
3084 set_column(const struct vsctl_table_class
*table
,
3085 const struct ovsdb_idl_row
*row
, const char *arg
,
3086 struct ovsdb_symbol_table
*symtab
)
3088 const struct ovsdb_idl_column
*column
;
3089 char *key_string
, *value_string
;
3092 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
3093 NULL
, NULL
, 0, &value_string
);
3094 die_if_error(error
);
3095 if (!value_string
) {
3096 vsctl_fatal("%s: missing value", arg
);
3100 union ovsdb_atom key
, value
;
3101 struct ovsdb_datum datum
;
3103 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
3104 vsctl_fatal("cannot specify key to set for non-map column %s",
3108 die_if_error(ovsdb_atom_from_string(&key
, &column
->type
.key
,
3109 key_string
, symtab
));
3110 die_if_error(ovsdb_atom_from_string(&value
, &column
->type
.value
,
3111 value_string
, symtab
));
3113 ovsdb_datum_init_empty(&datum
);
3114 ovsdb_datum_add_unsafe(&datum
, &key
, &value
, &column
->type
);
3116 ovsdb_atom_destroy(&key
, column
->type
.key
.type
);
3117 ovsdb_atom_destroy(&value
, column
->type
.value
.type
);
3119 ovsdb_datum_union(&datum
, ovsdb_idl_read(row
, column
),
3120 &column
->type
, false);
3121 ovsdb_idl_txn_write(row
, column
, &datum
);
3123 struct ovsdb_datum datum
;
3125 die_if_error(ovsdb_datum_from_string(&datum
, &column
->type
,
3126 value_string
, symtab
));
3127 ovsdb_idl_txn_write(row
, column
, &datum
);
3135 cmd_set(struct vsctl_context
*ctx
)
3137 const char *table_name
= ctx
->argv
[1];
3138 const char *record_id
= ctx
->argv
[2];
3139 const struct vsctl_table_class
*table
;
3140 const struct ovsdb_idl_row
*row
;
3143 table
= get_table(table_name
);
3144 row
= must_get_row(ctx
, table
, record_id
);
3145 for (i
= 3; i
< ctx
->argc
; i
++) {
3146 set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
3151 pre_cmd_add(struct vsctl_context
*ctx
)
3153 const char *table_name
= ctx
->argv
[1];
3154 const char *column_name
= ctx
->argv
[3];
3155 const struct vsctl_table_class
*table
;
3156 const struct ovsdb_idl_column
*column
;
3158 table
= pre_get_table(ctx
, table_name
);
3159 pre_get_column(ctx
, table
, column_name
, &column
);
3163 cmd_add(struct vsctl_context
*ctx
)
3165 const char *table_name
= ctx
->argv
[1];
3166 const char *record_id
= ctx
->argv
[2];
3167 const char *column_name
= ctx
->argv
[3];
3168 const struct vsctl_table_class
*table
;
3169 const struct ovsdb_idl_column
*column
;
3170 const struct ovsdb_idl_row
*row
;
3171 const struct ovsdb_type
*type
;
3172 struct ovsdb_datum old
;
3175 table
= get_table(table_name
);
3176 row
= must_get_row(ctx
, table
, record_id
);
3177 die_if_error(get_column(table
, column_name
, &column
));
3179 type
= &column
->type
;
3180 ovsdb_datum_clone(&old
, ovsdb_idl_read(row
, column
), &column
->type
);
3181 for (i
= 4; i
< ctx
->argc
; i
++) {
3182 struct ovsdb_type add_type
;
3183 struct ovsdb_datum add
;
3187 add_type
.n_max
= UINT_MAX
;
3188 die_if_error(ovsdb_datum_from_string(&add
, &add_type
, ctx
->argv
[i
],
3190 ovsdb_datum_union(&old
, &add
, type
, false);
3191 ovsdb_datum_destroy(&add
, type
);
3193 if (old
.n
> type
->n_max
) {
3194 vsctl_fatal("\"add\" operation would put %u %s in column %s of "
3195 "table %s but the maximum number is %u",
3197 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
3198 column
->name
, table
->class->name
, type
->n_max
);
3200 ovsdb_idl_txn_verify(row
, column
);
3201 ovsdb_idl_txn_write(row
, column
, &old
);
3205 pre_cmd_remove(struct vsctl_context
*ctx
)
3207 const char *table_name
= ctx
->argv
[1];
3208 const char *column_name
= ctx
->argv
[3];
3209 const struct vsctl_table_class
*table
;
3210 const struct ovsdb_idl_column
*column
;
3212 table
= pre_get_table(ctx
, table_name
);
3213 pre_get_column(ctx
, table
, column_name
, &column
);
3217 cmd_remove(struct vsctl_context
*ctx
)
3219 const char *table_name
= ctx
->argv
[1];
3220 const char *record_id
= ctx
->argv
[2];
3221 const char *column_name
= ctx
->argv
[3];
3222 const struct vsctl_table_class
*table
;
3223 const struct ovsdb_idl_column
*column
;
3224 const struct ovsdb_idl_row
*row
;
3225 const struct ovsdb_type
*type
;
3226 struct ovsdb_datum old
;
3229 table
= get_table(table_name
);
3230 row
= must_get_row(ctx
, table
, record_id
);
3231 die_if_error(get_column(table
, column_name
, &column
));
3233 type
= &column
->type
;
3234 ovsdb_datum_clone(&old
, ovsdb_idl_read(row
, column
), &column
->type
);
3235 for (i
= 4; i
< ctx
->argc
; i
++) {
3236 struct ovsdb_type rm_type
;
3237 struct ovsdb_datum rm
;
3242 rm_type
.n_max
= UINT_MAX
;
3243 error
= ovsdb_datum_from_string(&rm
, &rm_type
,
3244 ctx
->argv
[i
], ctx
->symtab
);
3245 if (error
&& ovsdb_type_is_map(&rm_type
)) {
3247 rm_type
.value
.type
= OVSDB_TYPE_VOID
;
3248 die_if_error(ovsdb_datum_from_string(&rm
, &rm_type
,
3249 ctx
->argv
[i
], ctx
->symtab
));
3251 ovsdb_datum_subtract(&old
, type
, &rm
, &rm_type
);
3252 ovsdb_datum_destroy(&rm
, &rm_type
);
3254 if (old
.n
< type
->n_min
) {
3255 vsctl_fatal("\"remove\" operation would put %u %s in column %s of "
3256 "table %s but the minimum number is %u",
3258 type
->value
.type
== OVSDB_TYPE_VOID
? "values" : "pairs",
3259 column
->name
, table
->class->name
, type
->n_min
);
3261 ovsdb_idl_txn_verify(row
, column
);
3262 ovsdb_idl_txn_write(row
, column
, &old
);
3266 pre_cmd_clear(struct vsctl_context
*ctx
)
3268 const char *table_name
= ctx
->argv
[1];
3269 const struct vsctl_table_class
*table
;
3272 table
= pre_get_table(ctx
, table_name
);
3273 for (i
= 3; i
< ctx
->argc
; i
++) {
3274 const struct ovsdb_idl_column
*column
;
3276 pre_get_column(ctx
, table
, ctx
->argv
[i
], &column
);
3281 cmd_clear(struct vsctl_context
*ctx
)
3283 const char *table_name
= ctx
->argv
[1];
3284 const char *record_id
= ctx
->argv
[2];
3285 const struct vsctl_table_class
*table
;
3286 const struct ovsdb_idl_row
*row
;
3289 table
= get_table(table_name
);
3290 row
= must_get_row(ctx
, table
, record_id
);
3291 for (i
= 3; i
< ctx
->argc
; i
++) {
3292 const struct ovsdb_idl_column
*column
;
3293 const struct ovsdb_type
*type
;
3294 struct ovsdb_datum datum
;
3296 die_if_error(get_column(table
, ctx
->argv
[i
], &column
));
3298 type
= &column
->type
;
3299 if (type
->n_min
> 0) {
3300 vsctl_fatal("\"clear\" operation cannot be applied to column %s "
3301 "of table %s, which is not allowed to be empty",
3302 column
->name
, table
->class->name
);
3305 ovsdb_datum_init_empty(&datum
);
3306 ovsdb_idl_txn_write(row
, column
, &datum
);
3311 pre_create(struct vsctl_context
*ctx
)
3313 const char *id
= shash_find_data(&ctx
->options
, "--id");
3314 const char *table_name
= ctx
->argv
[1];
3315 const struct vsctl_table_class
*table
;
3317 table
= get_table(table_name
);
3318 if (!id
&& !table
->class->is_root
) {
3319 VLOG_WARN("applying \"create\" command to table %s without --id "
3320 "option will have no effect", table
->class->name
);
3325 cmd_create(struct vsctl_context
*ctx
)
3327 const char *id
= shash_find_data(&ctx
->options
, "--id");
3328 const char *table_name
= ctx
->argv
[1];
3329 const struct vsctl_table_class
*table
= get_table(table_name
);
3330 const struct ovsdb_idl_row
*row
;
3331 const struct uuid
*uuid
;
3335 struct ovsdb_symbol
*symbol
= create_symbol(ctx
->symtab
, id
, NULL
);
3336 if (table
->class->is_root
) {
3337 /* This table is in the root set, meaning that rows created in it
3338 * won't disappear even if they are unreferenced, so disable
3339 * warnings about that by pretending that there is a reference. */
3340 symbol
->strong_ref
= true;
3342 uuid
= &symbol
->uuid
;
3347 row
= ovsdb_idl_txn_insert(ctx
->txn
, table
->class, uuid
);
3348 for (i
= 2; i
< ctx
->argc
; i
++) {
3349 set_column(table
, row
, ctx
->argv
[i
], ctx
->symtab
);
3351 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(&row
->uuid
));
3354 /* This function may be used as the 'postprocess' function for commands that
3355 * insert new rows into the database. It expects that the command's 'run'
3356 * function prints the UUID reported by ovsdb_idl_txn_insert() as the command's
3357 * sole output. It replaces that output by the row's permanent UUID assigned
3358 * by the database server and appends a new-line.
3360 * Currently we use this only for "create", because the higher-level commands
3361 * are supposed to be independent of the actual structure of the vswitch
3364 post_create(struct vsctl_context
*ctx
)
3366 const struct uuid
*real
;
3369 if (!uuid_from_string(&dummy
, ds_cstr(&ctx
->output
))) {
3372 real
= ovsdb_idl_txn_get_insert_uuid(ctx
->txn
, &dummy
);
3374 ds_clear(&ctx
->output
);
3375 ds_put_format(&ctx
->output
, UUID_FMT
, UUID_ARGS(real
));
3377 ds_put_char(&ctx
->output
, '\n');
3381 pre_cmd_destroy(struct vsctl_context
*ctx
)
3383 const char *table_name
= ctx
->argv
[1];
3385 pre_get_table(ctx
, table_name
);
3389 cmd_destroy(struct vsctl_context
*ctx
)
3391 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
3392 const char *table_name
= ctx
->argv
[1];
3393 const struct vsctl_table_class
*table
;
3396 table
= get_table(table_name
);
3397 for (i
= 2; i
< ctx
->argc
; i
++) {
3398 const struct ovsdb_idl_row
*row
;
3400 row
= (must_exist
? must_get_row
: get_row
)(ctx
, table
, ctx
->argv
[i
]);
3402 ovsdb_idl_txn_delete(row
);
3408 RELOP(RELOP_EQ, "=") \
3409 RELOP(RELOP_NE, "!=") \
3410 RELOP(RELOP_LT, "<") \
3411 RELOP(RELOP_GT, ">") \
3412 RELOP(RELOP_LE, "<=") \
3413 RELOP(RELOP_GE, ">=") \
3414 RELOP(RELOP_SET_EQ, "{=}") \
3415 RELOP(RELOP_SET_NE, "{!=}") \
3416 RELOP(RELOP_SET_LT, "{<}") \
3417 RELOP(RELOP_SET_GT, "{>}") \
3418 RELOP(RELOP_SET_LE, "{<=}") \
3419 RELOP(RELOP_SET_GE, "{>=}")
3422 #define RELOP(ENUM, STRING) ENUM,
3428 is_set_operator(enum relop op
)
3430 return (op
== RELOP_SET_EQ
|| op
== RELOP_SET_NE
||
3431 op
== RELOP_SET_LT
|| op
== RELOP_SET_GT
||
3432 op
== RELOP_SET_LE
|| op
== RELOP_SET_GE
);
3436 evaluate_relop(const struct ovsdb_datum
*a
, const struct ovsdb_datum
*b
,
3437 const struct ovsdb_type
*type
, enum relop op
)
3442 return ovsdb_datum_compare_3way(a
, b
, type
) == 0;
3445 return ovsdb_datum_compare_3way(a
, b
, type
) != 0;
3447 return ovsdb_datum_compare_3way(a
, b
, type
) < 0;
3449 return ovsdb_datum_compare_3way(a
, b
, type
) > 0;
3451 return ovsdb_datum_compare_3way(a
, b
, type
) <= 0;
3453 return ovsdb_datum_compare_3way(a
, b
, type
) >= 0;
3456 return b
->n
> a
->n
&& ovsdb_datum_includes_all(a
, b
, type
);
3458 return a
->n
> b
->n
&& ovsdb_datum_includes_all(b
, a
, type
);
3460 return ovsdb_datum_includes_all(a
, b
, type
);
3462 return ovsdb_datum_includes_all(b
, a
, type
);
3470 is_condition_satisfied(const struct vsctl_table_class
*table
,
3471 const struct ovsdb_idl_row
*row
, const char *arg
,
3472 struct ovsdb_symbol_table
*symtab
)
3474 static const char *operators
[] = {
3475 #define RELOP(ENUM, STRING) STRING,
3480 const struct ovsdb_idl_column
*column
;
3481 const struct ovsdb_datum
*have_datum
;
3482 char *key_string
, *value_string
;
3483 struct ovsdb_type type
;
3488 error
= parse_column_key_value(arg
, table
, &column
, &key_string
,
3489 &operator, operators
, ARRAY_SIZE(operators
),
3491 die_if_error(error
);
3492 if (!value_string
) {
3493 vsctl_fatal("%s: missing value", arg
);
3496 type
= column
->type
;
3497 type
.n_max
= UINT_MAX
;
3499 have_datum
= ovsdb_idl_read(row
, column
);
3501 union ovsdb_atom want_key
;
3502 struct ovsdb_datum b
;
3505 if (column
->type
.value
.type
== OVSDB_TYPE_VOID
) {
3506 vsctl_fatal("cannot specify key to check for non-map column %s",
3510 die_if_error(ovsdb_atom_from_string(&want_key
, &column
->type
.key
,
3511 key_string
, symtab
));
3513 type
.key
= type
.value
;
3514 type
.value
.type
= OVSDB_TYPE_VOID
;
3515 die_if_error(ovsdb_datum_from_string(&b
, &type
, value_string
, symtab
));
3517 idx
= ovsdb_datum_find_key(have_datum
,
3518 &want_key
, column
->type
.key
.type
);
3519 if (idx
== UINT_MAX
&& !is_set_operator(operator)) {
3522 struct ovsdb_datum a
;
3524 if (idx
!= UINT_MAX
) {
3526 a
.keys
= &have_datum
->values
[idx
];
3534 retval
= evaluate_relop(&a
, &b
, &type
, operator);
3537 ovsdb_atom_destroy(&want_key
, column
->type
.key
.type
);
3539 struct ovsdb_datum want_datum
;
3541 die_if_error(ovsdb_datum_from_string(&want_datum
, &column
->type
,
3542 value_string
, symtab
));
3543 retval
= evaluate_relop(have_datum
, &want_datum
, &type
, operator);
3544 ovsdb_datum_destroy(&want_datum
, &column
->type
);
3554 pre_cmd_wait_until(struct vsctl_context
*ctx
)
3556 const char *table_name
= ctx
->argv
[1];
3557 const struct vsctl_table_class
*table
;
3560 table
= pre_get_table(ctx
, table_name
);
3562 for (i
= 3; i
< ctx
->argc
; i
++) {
3563 pre_parse_column_key_value(ctx
, ctx
->argv
[i
], table
);
3568 cmd_wait_until(struct vsctl_context
*ctx
)
3570 const char *table_name
= ctx
->argv
[1];
3571 const char *record_id
= ctx
->argv
[2];
3572 const struct vsctl_table_class
*table
;
3573 const struct ovsdb_idl_row
*row
;
3576 table
= get_table(table_name
);
3578 row
= get_row(ctx
, table
, record_id
);
3580 ctx
->try_again
= true;
3584 for (i
= 3; i
< ctx
->argc
; i
++) {
3585 if (!is_condition_satisfied(table
, row
, ctx
->argv
[i
], ctx
->symtab
)) {
3586 ctx
->try_again
= true;
3592 static struct json
*
3593 where_uuid_equals(const struct uuid
*uuid
)
3596 json_array_create_1(
3597 json_array_create_3(
3598 json_string_create("_uuid"),
3599 json_string_create("=="),
3600 json_array_create_2(
3601 json_string_create("uuid"),
3602 json_string_create_nocopy(
3603 xasprintf(UUID_FMT
, UUID_ARGS(uuid
))))));
3607 vsctl_context_init(struct vsctl_context
*ctx
, struct vsctl_command
*command
,
3608 struct ovsdb_idl
*idl
, struct ovsdb_idl_txn
*txn
,
3609 const struct ovsrec_open_vswitch
*ovs
,
3610 struct ovsdb_symbol_table
*symtab
)
3612 ctx
->argc
= command
->argc
;
3613 ctx
->argv
= command
->argv
;
3614 ctx
->options
= command
->options
;
3616 ds_swap(&ctx
->output
, &command
->output
);
3617 ctx
->table
= command
->table
;
3621 ctx
->symtab
= symtab
;
3622 ctx
->verified_ports
= false;
3624 ctx
->try_again
= false;
3628 vsctl_context_done(struct vsctl_context
*ctx
, struct vsctl_command
*command
)
3630 ds_swap(&ctx
->output
, &command
->output
);
3631 command
->table
= ctx
->table
;
3635 run_prerequisites(struct vsctl_command
*commands
, size_t n_commands
,
3636 struct ovsdb_idl
*idl
)
3638 struct vsctl_command
*c
;
3640 ovsdb_idl_add_table(idl
, &ovsrec_table_open_vswitch
);
3641 if (wait_for_reload
) {
3642 ovsdb_idl_add_column(idl
, &ovsrec_open_vswitch_col_cur_cfg
);
3644 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
3645 if (c
->syntax
->prerequisites
) {
3646 struct vsctl_context ctx
;
3648 ds_init(&c
->output
);
3651 vsctl_context_init(&ctx
, c
, idl
, NULL
, NULL
, NULL
);
3652 (c
->syntax
->prerequisites
)(&ctx
);
3653 vsctl_context_done(&ctx
, c
);
3655 assert(!c
->output
.string
);
3661 static enum ovsdb_idl_txn_status
3662 do_vsctl(const char *args
, struct vsctl_command
*commands
, size_t n_commands
,
3663 struct ovsdb_idl
*idl
)
3665 struct ovsdb_idl_txn
*txn
;
3666 const struct ovsrec_open_vswitch
*ovs
;
3667 enum ovsdb_idl_txn_status status
;
3668 struct ovsdb_symbol_table
*symtab
;
3669 struct vsctl_command
*c
;
3670 struct shash_node
*node
;
3671 int64_t next_cfg
= 0;
3674 txn
= the_idl_txn
= ovsdb_idl_txn_create(idl
);
3676 ovsdb_idl_txn_set_dry_run(txn
);
3679 ovsdb_idl_txn_add_comment(txn
, "ovs-vsctl: %s", args
);
3681 ovs
= ovsrec_open_vswitch_first(idl
);
3683 /* XXX add verification that table is empty */
3684 ovs
= ovsrec_open_vswitch_insert(txn
);
3687 if (wait_for_reload
) {
3688 struct json
*where
= where_uuid_equals(&ovs
->header_
.uuid
);
3689 ovsdb_idl_txn_increment(txn
, "Open_vSwitch", "next_cfg", where
);
3690 json_destroy(where
);
3693 symtab
= ovsdb_symbol_table_create();
3694 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
3695 ds_init(&c
->output
);
3698 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
3699 struct vsctl_context ctx
;
3701 vsctl_context_init(&ctx
, c
, idl
, txn
, ovs
, symtab
);
3702 if (c
->syntax
->run
) {
3703 (c
->syntax
->run
)(&ctx
);
3705 vsctl_context_done(&ctx
, c
);
3707 if (ctx
.try_again
) {
3708 status
= TXN_AGAIN_WAIT
;
3713 SHASH_FOR_EACH (node
, &symtab
->sh
) {
3714 struct ovsdb_symbol
*symbol
= node
->data
;
3715 if (!symbol
->created
) {
3716 vsctl_fatal("row id \"%s\" is referenced but never created (e.g. "
3717 "with \"-- --id=%s create ...\")",
3718 node
->name
, node
->name
);
3720 if (!symbol
->strong_ref
) {
3721 if (!symbol
->weak_ref
) {
3722 VLOG_WARN("row id \"%s\" was created but no reference to it "
3723 "was inserted, so it will not actually appear in "
3724 "the database", node
->name
);
3726 VLOG_WARN("row id \"%s\" was created but only a weak "
3727 "reference to it was inserted, so it will not "
3728 "actually appear in the database", node
->name
);
3733 status
= ovsdb_idl_txn_commit_block(txn
);
3734 if (wait_for_reload
&& status
== TXN_SUCCESS
) {
3735 next_cfg
= ovsdb_idl_txn_get_increment_new_value(txn
);
3737 if (status
== TXN_UNCHANGED
|| status
== TXN_SUCCESS
) {
3738 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
3739 if (c
->syntax
->postprocess
) {
3740 struct vsctl_context ctx
;
3742 vsctl_context_init(&ctx
, c
, idl
, txn
, ovs
, symtab
);
3743 (c
->syntax
->postprocess
)(&ctx
);
3744 vsctl_context_done(&ctx
, c
);
3748 error
= xstrdup(ovsdb_idl_txn_get_error(txn
));
3749 ovsdb_idl_txn_destroy(txn
);
3750 txn
= the_idl_txn
= NULL
;
3753 case TXN_UNCOMMITTED
:
3754 case TXN_INCOMPLETE
:
3758 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
3759 vsctl_fatal("transaction aborted");
3765 case TXN_AGAIN_WAIT
:
3770 vsctl_fatal("transaction error: %s", error
);
3772 case TXN_NOT_LOCKED
:
3773 /* Should not happen--we never call ovsdb_idl_set_lock(). */
3774 vsctl_fatal("database not locked");
3781 ovsdb_symbol_table_destroy(symtab
);
3783 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
3784 struct ds
*ds
= &c
->output
;
3787 table_print(c
->table
, &table_style
);
3788 } else if (oneline
) {
3792 for (j
= 0; j
< ds
->length
; j
++) {
3793 int ch
= ds
->string
[j
];
3796 fputs("\\n", stdout
);
3800 fputs("\\\\", stdout
);
3809 fputs(ds_cstr(ds
), stdout
);
3811 ds_destroy(&c
->output
);
3812 table_destroy(c
->table
);
3815 smap_destroy(&c
->options
);
3819 if (wait_for_reload
&& status
!= TXN_UNCHANGED
) {
3822 OVSREC_OPEN_VSWITCH_FOR_EACH (ovs
, idl
) {
3823 if (ovs
->cur_cfg
>= next_cfg
) {
3827 ovsdb_idl_wait(idl
);
3832 ovsdb_idl_destroy(idl
);
3837 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
3838 * resources and return so that the caller can try again. */
3840 ovsdb_idl_txn_abort(txn
);
3841 ovsdb_idl_txn_destroy(txn
);
3843 ovsdb_symbol_table_destroy(symtab
);
3844 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
3845 ds_destroy(&c
->output
);
3846 table_destroy(c
->table
);
3854 static const struct vsctl_command_syntax all_commands
[] = {
3855 /* Open vSwitch commands. */
3856 {"init", 0, 0, NULL
, cmd_init
, NULL
, "", RW
},
3857 {"show", 0, 0, pre_cmd_show
, cmd_show
, NULL
, "", RO
},
3859 /* Bridge commands. */
3860 {"add-br", 1, 3, pre_get_info
, cmd_add_br
, NULL
, "--may-exist", RW
},
3861 {"del-br", 1, 1, pre_get_info
, cmd_del_br
, NULL
, "--if-exists", RW
},
3862 {"list-br", 0, 0, pre_get_info
, cmd_list_br
, NULL
, "", RO
},
3863 {"br-exists", 1, 1, pre_get_info
, cmd_br_exists
, NULL
, "", RO
},
3864 {"br-to-vlan", 1, 1, pre_get_info
, cmd_br_to_vlan
, NULL
, "", RO
},
3865 {"br-to-parent", 1, 1, pre_get_info
, cmd_br_to_parent
, NULL
, "", RO
},
3866 {"br-set-external-id", 2, 3, pre_cmd_br_set_external_id
,
3867 cmd_br_set_external_id
, NULL
, "", RW
},
3868 {"br-get-external-id", 1, 2, pre_cmd_br_get_external_id
,
3869 cmd_br_get_external_id
, NULL
, "", RO
},
3871 /* Port commands. */
3872 {"list-ports", 1, 1, pre_get_info
, cmd_list_ports
, NULL
, "", RO
},
3873 {"add-port", 2, INT_MAX
, pre_get_info
, cmd_add_port
, NULL
, "--may-exist",
3875 {"add-bond", 4, INT_MAX
, pre_get_info
, cmd_add_bond
, NULL
,
3876 "--may-exist,--fake-iface", RW
},
3877 {"del-port", 1, 2, pre_get_info
, cmd_del_port
, NULL
,
3878 "--if-exists,--with-iface", RW
},
3879 {"port-to-br", 1, 1, pre_get_info
, cmd_port_to_br
, NULL
, "", RO
},
3881 /* Interface commands. */
3882 {"list-ifaces", 1, 1, pre_get_info
, cmd_list_ifaces
, NULL
, "", RO
},
3883 {"iface-to-br", 1, 1, pre_get_info
, cmd_iface_to_br
, NULL
, "", RO
},
3885 /* Controller commands. */
3886 {"get-controller", 1, 1, pre_controller
, cmd_get_controller
, NULL
, "", RO
},
3887 {"del-controller", 1, 1, pre_controller
, cmd_del_controller
, NULL
, "", RW
},
3888 {"set-controller", 1, INT_MAX
, pre_controller
, cmd_set_controller
, NULL
,
3890 {"get-fail-mode", 1, 1, pre_get_info
, cmd_get_fail_mode
, NULL
, "", RO
},
3891 {"del-fail-mode", 1, 1, pre_get_info
, cmd_del_fail_mode
, NULL
, "", RW
},
3892 {"set-fail-mode", 2, 2, pre_get_info
, cmd_set_fail_mode
, NULL
, "", RW
},
3894 /* Manager commands. */
3895 {"get-manager", 0, 0, pre_manager
, cmd_get_manager
, NULL
, "", RO
},
3896 {"del-manager", 0, INT_MAX
, pre_manager
, cmd_del_manager
, NULL
, "", RW
},
3897 {"set-manager", 1, INT_MAX
, pre_manager
, cmd_set_manager
, NULL
, "", RW
},
3900 {"get-ssl", 0, 0, pre_cmd_get_ssl
, cmd_get_ssl
, NULL
, "", RO
},
3901 {"del-ssl", 0, 0, pre_cmd_del_ssl
, cmd_del_ssl
, NULL
, "", RW
},
3902 {"set-ssl", 3, 3, pre_cmd_set_ssl
, cmd_set_ssl
, NULL
, "--bootstrap", RW
},
3904 /* Switch commands. */
3905 {"emer-reset", 0, 0, pre_cmd_emer_reset
, cmd_emer_reset
, NULL
, "", RW
},
3907 /* Database commands. */
3908 {"comment", 0, INT_MAX
, NULL
, NULL
, NULL
, "", RO
},
3909 {"get", 2, INT_MAX
, pre_cmd_get
, cmd_get
, NULL
, "--if-exists,--id=", RO
},
3910 {"list", 1, INT_MAX
, pre_cmd_list
, cmd_list
, NULL
, "--columns=", RO
},
3911 {"find", 1, INT_MAX
, pre_cmd_find
, cmd_find
, NULL
, "--columns=", RO
},
3912 {"set", 3, INT_MAX
, pre_cmd_set
, cmd_set
, NULL
, "", RW
},
3913 {"add", 4, INT_MAX
, pre_cmd_add
, cmd_add
, NULL
, "", RW
},
3914 {"remove", 4, INT_MAX
, pre_cmd_remove
, cmd_remove
, NULL
, "", RW
},
3915 {"clear", 3, INT_MAX
, pre_cmd_clear
, cmd_clear
, NULL
, "", RW
},
3916 {"create", 2, INT_MAX
, pre_create
, cmd_create
, post_create
, "--id=", RW
},
3917 {"destroy", 1, INT_MAX
, pre_cmd_destroy
, cmd_destroy
, NULL
, "--if-exists",
3919 {"wait-until", 2, INT_MAX
, pre_cmd_wait_until
, cmd_wait_until
, NULL
, "",
3922 {NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
, RO
},