2009-12-08 17:18:12 -08:00
|
|
|
|
/*
|
2017-01-04 14:29:21 -08:00
|
|
|
|
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
|
2009-12-08 17:18:12 -08:00
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
2010-01-25 10:13:52 -08:00
|
|
|
|
#include <ctype.h>
|
2009-12-08 17:18:12 -08:00
|
|
|
|
#include <errno.h>
|
2010-01-25 10:13:52 -08:00
|
|
|
|
#include <float.h>
|
2009-12-08 17:18:12 -08:00
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <inttypes.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2011-05-09 10:29:51 -07:00
|
|
|
|
#include <unistd.h>
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
#include "db-ctl-base.h"
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
#include "command-line.h"
|
|
|
|
|
#include "compiler.h"
|
2016-12-20 17:50:06 -08:00
|
|
|
|
#include "dirs.h"
|
2016-03-03 10:20:46 -08:00
|
|
|
|
#include "openvswitch/dynamic-string.h"
|
2014-02-26 10:44:46 -08:00
|
|
|
|
#include "fatal-signal.h"
|
2012-04-17 16:56:21 -07:00
|
|
|
|
#include "hash.h"
|
2016-07-12 16:37:34 -05:00
|
|
|
|
#include "openvswitch/json.h"
|
2010-01-25 10:13:52 -08:00
|
|
|
|
#include "ovsdb-data.h"
|
2009-12-08 17:18:12 -08:00
|
|
|
|
#include "ovsdb-idl.h"
|
2017-11-03 13:53:53 +08:00
|
|
|
|
#include "openvswitch/poll-loop.h"
|
2010-01-28 16:09:26 -08:00
|
|
|
|
#include "process.h"
|
2011-02-10 09:34:42 -08:00
|
|
|
|
#include "stream.h"
|
2010-03-23 15:29:10 -07:00
|
|
|
|
#include "stream-ssl.h"
|
2012-05-22 01:53:07 -07:00
|
|
|
|
#include "smap.h"
|
2011-03-25 15:26:30 -07:00
|
|
|
|
#include "sset.h"
|
2009-12-09 13:28:48 -08:00
|
|
|
|
#include "svec.h"
|
2012-03-27 15:57:52 -07:00
|
|
|
|
#include "lib/vswitch-idl.h"
|
2011-02-08 16:10:34 -08:00
|
|
|
|
#include "table.h"
|
2009-12-08 17:18:12 -08:00
|
|
|
|
#include "timeval.h"
|
|
|
|
|
#include "util.h"
|
2014-12-15 14:10:38 +01:00
|
|
|
|
#include "openvswitch/vconn.h"
|
2014-12-15 14:10:38 +01:00
|
|
|
|
#include "openvswitch/vlog.h"
|
2010-07-16 11:02:49 -07:00
|
|
|
|
|
2010-10-19 14:47:01 -07:00
|
|
|
|
VLOG_DEFINE_THIS_MODULE(vsctl);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
struct vsctl_context;
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
/* --db: The database server to contact. */
|
|
|
|
|
static const char *db;
|
|
|
|
|
|
|
|
|
|
/* --oneline: Write each command's output as a single line? */
|
|
|
|
|
static bool oneline;
|
|
|
|
|
|
2009-12-11 11:28:36 -08:00
|
|
|
|
/* --dry-run: Do not commit any changes. */
|
|
|
|
|
static bool dry_run;
|
|
|
|
|
|
2009-12-16 16:26:17 -08:00
|
|
|
|
/* --no-wait: Wait for ovs-vswitchd to reload its configuration? */
|
|
|
|
|
static bool wait_for_reload = true;
|
|
|
|
|
|
2009-12-14 13:59:58 -08:00
|
|
|
|
/* --timeout: Time to wait for a connection to 'db'. */
|
2010-09-17 14:37:51 -07:00
|
|
|
|
static int timeout;
|
2009-12-14 13:59:58 -08:00
|
|
|
|
|
2013-03-15 16:14:28 -07:00
|
|
|
|
/* --retry: If true, ovs-vsctl will retry connecting to the database forever.
|
|
|
|
|
* If false and --db says to use an active connection method (e.g. "unix:",
|
|
|
|
|
* "tcp:", "ssl:"), then ovs-vsctl will try to connect once and exit with an
|
|
|
|
|
* error if the database server cannot be contacted (e.g. ovsdb-server is not
|
|
|
|
|
* running).
|
|
|
|
|
*
|
|
|
|
|
* Regardless of this setting, --timeout always limits how long ovs-vsctl will
|
|
|
|
|
* wait. */
|
|
|
|
|
static bool retry;
|
|
|
|
|
|
2011-02-08 16:10:34 -08:00
|
|
|
|
/* Format for table output. */
|
|
|
|
|
static struct table_style table_style = TABLE_STYLE_DEFAULT;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void vsctl_cmd_init(void);
|
2015-07-13 23:24:11 -07:00
|
|
|
|
|
|
|
|
|
/* The IDL we're using and the current transaction, if any.
|
|
|
|
|
* This is for use by vsctl_exit() only, to allow it to clean up.
|
|
|
|
|
* Other code should use its context arguments. */
|
|
|
|
|
static struct ovsdb_idl *the_idl;
|
|
|
|
|
static struct ovsdb_idl_txn *the_idl_txn;
|
|
|
|
|
OVS_NO_RETURN static void vsctl_exit(int status);
|
|
|
|
|
|
2014-12-15 14:10:38 +01:00
|
|
|
|
OVS_NO_RETURN static void usage(void);
|
2012-12-10 14:24:36 -08:00
|
|
|
|
static void parse_options(int argc, char *argv[], struct shash *local_options);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void run_prerequisites(struct ctl_command[], size_t n_commands,
|
2010-11-16 09:15:40 -08:00
|
|
|
|
struct ovsdb_idl *);
|
2018-01-25 15:39:47 -08:00
|
|
|
|
static bool do_vsctl(const char *args, struct ctl_command *, size_t n,
|
2012-03-27 10:16:52 -07:00
|
|
|
|
struct ovsdb_idl *);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
/* post_db_reload_check frame work is to allow ovs-vsctl to do additional
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
* checks after OVSDB transactions are successfully recorded and reload by
|
|
|
|
|
* ovs-vswitchd.
|
|
|
|
|
*
|
|
|
|
|
* For example, When a new interface is added to OVSDB, ovs-vswitchd will
|
|
|
|
|
* either store a positive values on successful implementing the new
|
|
|
|
|
* interface, or -1 on failure.
|
|
|
|
|
*
|
2016-07-18 09:15:19 -07:00
|
|
|
|
* Unless --no-wait command line option is specified,
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
* post_db_reload_do_checks() is called right after any configuration
|
|
|
|
|
* changes is picked up (i.e. reload) by ovs-vswitchd. Any error detected
|
|
|
|
|
* post OVSDB reload is reported as ovs-vsctl errors. OVS-vswitchd logs
|
|
|
|
|
* more detailed messages about those errors.
|
|
|
|
|
*
|
|
|
|
|
* Current implementation only check for Post OVSDB reload failures on new
|
|
|
|
|
* interface additions with 'add-br' and 'add-port' commands.
|
|
|
|
|
*
|
|
|
|
|
* post_db_reload_expect_iface()
|
|
|
|
|
*
|
|
|
|
|
* keep track of interfaces to be checked post OVSDB reload. */
|
|
|
|
|
static void post_db_reload_check_init(void);
|
|
|
|
|
static void post_db_reload_do_checks(const struct vsctl_context *);
|
|
|
|
|
static void post_db_reload_expect_iface(const struct ovsrec_interface *);
|
|
|
|
|
|
|
|
|
|
static struct uuid *neoteric_ifaces;
|
|
|
|
|
static size_t n_neoteric_ifaces;
|
|
|
|
|
static size_t allocated_neoteric_ifaces;
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
int
|
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
struct ovsdb_idl *idl;
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct ctl_command *commands;
|
2012-12-10 14:24:36 -08:00
|
|
|
|
struct shash local_options;
|
2012-03-27 10:16:52 -07:00
|
|
|
|
unsigned int seqno;
|
2010-01-28 16:09:26 -08:00
|
|
|
|
size_t n_commands;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
set_program_name(argv[0]);
|
2014-02-26 10:44:46 -08:00
|
|
|
|
fatal_ignore_sigpipe();
|
2010-07-16 10:53:14 -07:00
|
|
|
|
vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
|
2016-02-03 13:15:48 -08:00
|
|
|
|
vlog_set_levels_from_string_assert("reconnect:warn");
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_cmd_init();
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
/* Parse command line. */
|
2018-05-17 14:04:25 -07:00
|
|
|
|
char *args = process_escape_args(argv);
|
2012-12-10 14:24:36 -08:00
|
|
|
|
shash_init(&local_options);
|
|
|
|
|
parse_options(argc, argv, &local_options);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
|
|
|
|
|
&n_commands);
|
2018-05-17 14:04:25 -07:00
|
|
|
|
VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG,
|
|
|
|
|
"Called as %s", args);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2009-12-14 13:59:58 -08:00
|
|
|
|
if (timeout) {
|
|
|
|
|
time_alarm(timeout);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
/* Initialize IDL. */
|
2013-03-15 16:14:28 -07:00
|
|
|
|
idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false, retry);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
run_prerequisites(commands, n_commands, idl);
|
|
|
|
|
|
2012-03-27 10:16:52 -07:00
|
|
|
|
/* Execute the commands.
|
|
|
|
|
*
|
|
|
|
|
* 'seqno' is the database sequence number for which we last tried to
|
|
|
|
|
* execute our transaction. There's no point in trying to commit more than
|
|
|
|
|
* once for any given sequence number, because if the transaction fails
|
|
|
|
|
* it's because the database changed and we need to obtain an up-to-date
|
|
|
|
|
* view of the database before we try the transaction again. */
|
|
|
|
|
seqno = ovsdb_idl_get_seqno(idl);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
for (;;) {
|
2012-03-27 10:16:52 -07:00
|
|
|
|
ovsdb_idl_run(idl);
|
2013-03-15 16:14:28 -07:00
|
|
|
|
if (!ovsdb_idl_is_alive(idl)) {
|
|
|
|
|
int retval = ovsdb_idl_get_last_error(idl);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("%s: database connection failed (%s)",
|
2013-03-15 16:14:28 -07:00
|
|
|
|
db, ovs_retval_to_string(retval));
|
|
|
|
|
}
|
2012-03-27 10:16:52 -07:00
|
|
|
|
|
|
|
|
|
if (seqno != ovsdb_idl_get_seqno(idl)) {
|
|
|
|
|
seqno = ovsdb_idl_get_seqno(idl);
|
2018-01-25 15:39:47 -08:00
|
|
|
|
if (do_vsctl(args, commands, n_commands, idl)) {
|
|
|
|
|
free(args);
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-27 10:16:52 -07:00
|
|
|
|
if (seqno == ovsdb_idl_get_seqno(idl)) {
|
2011-10-31 09:15:14 -07:00
|
|
|
|
ovsdb_idl_wait(idl);
|
|
|
|
|
poll_block();
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-12-10 14:24:36 -08:00
|
|
|
|
parse_options(int argc, char *argv[], struct shash *local_options)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
|
|
|
|
enum {
|
|
|
|
|
OPT_DB = UCHAR_MAX + 1,
|
|
|
|
|
OPT_ONELINE,
|
2009-12-10 15:32:50 -08:00
|
|
|
|
OPT_NO_SYSLOG,
|
2009-12-11 11:28:36 -08:00
|
|
|
|
OPT_NO_WAIT,
|
2010-01-04 19:15:22 -08:00
|
|
|
|
OPT_DRY_RUN,
|
2015-08-19 09:21:04 -07:00
|
|
|
|
OPT_BOOTSTRAP_CA_CERT,
|
2010-03-23 15:29:10 -07:00
|
|
|
|
OPT_PEER_CA_CERT,
|
2012-12-10 14:24:36 -08:00
|
|
|
|
OPT_LOCAL,
|
2013-03-15 16:14:28 -07:00
|
|
|
|
OPT_RETRY,
|
2015-02-04 09:52:12 -08:00
|
|
|
|
OPT_COMMANDS,
|
|
|
|
|
OPT_OPTIONS,
|
2011-02-08 16:10:34 -08:00
|
|
|
|
VLOG_OPTION_ENUMS,
|
2016-10-06 16:21:33 -07:00
|
|
|
|
TABLE_OPTION_ENUMS,
|
|
|
|
|
SSL_OPTION_ENUMS,
|
2009-12-08 17:18:12 -08:00
|
|
|
|
};
|
2012-12-10 14:24:36 -08:00
|
|
|
|
static const struct option global_long_options[] = {
|
2011-05-04 13:49:42 -07:00
|
|
|
|
{"db", required_argument, NULL, OPT_DB},
|
|
|
|
|
{"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
|
|
|
|
|
{"no-wait", no_argument, NULL, OPT_NO_WAIT},
|
|
|
|
|
{"dry-run", no_argument, NULL, OPT_DRY_RUN},
|
|
|
|
|
{"oneline", no_argument, NULL, OPT_ONELINE},
|
|
|
|
|
{"timeout", required_argument, NULL, 't'},
|
2013-03-15 16:14:28 -07:00
|
|
|
|
{"retry", no_argument, NULL, OPT_RETRY},
|
2011-05-04 13:49:42 -07:00
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"commands", no_argument, NULL, OPT_COMMANDS},
|
|
|
|
|
{"options", no_argument, NULL, OPT_OPTIONS},
|
2011-05-04 13:49:42 -07:00
|
|
|
|
{"version", no_argument, NULL, 'V'},
|
2010-01-04 19:15:22 -08:00
|
|
|
|
VLOG_LONG_OPTIONS,
|
2011-02-08 16:10:34 -08:00
|
|
|
|
TABLE_LONG_OPTIONS,
|
2011-05-10 09:17:37 -07:00
|
|
|
|
STREAM_SSL_LONG_OPTIONS,
|
2015-08-19 09:21:04 -07:00
|
|
|
|
{"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
|
2011-05-04 13:49:42 -07:00
|
|
|
|
{"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
|
|
|
|
|
{NULL, 0, NULL, 0},
|
2009-12-08 17:18:12 -08:00
|
|
|
|
};
|
2012-12-10 14:24:36 -08:00
|
|
|
|
const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
|
2010-08-16 15:54:47 -07:00
|
|
|
|
char *tmp, *short_options;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2015-06-11 08:19:15 -07:00
|
|
|
|
struct option *options;
|
2012-12-10 14:24:36 -08:00
|
|
|
|
size_t allocated_options;
|
|
|
|
|
size_t n_options;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
2015-03-16 12:01:55 -04:00
|
|
|
|
tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
|
2010-08-16 15:54:47 -07:00
|
|
|
|
short_options = xasprintf("+%s", tmp);
|
|
|
|
|
free(tmp);
|
2009-12-14 10:13:36 -08:00
|
|
|
|
|
2012-12-10 14:24:36 -08:00
|
|
|
|
/* We want to parse both global and command-specific options here, but
|
|
|
|
|
* getopt_long() isn't too convenient for the job. We copy our global
|
|
|
|
|
* options into a dynamic array, then append all of the command-specific
|
|
|
|
|
* options. */
|
|
|
|
|
options = xmemdup(global_long_options, sizeof global_long_options);
|
|
|
|
|
allocated_options = ARRAY_SIZE(global_long_options);
|
|
|
|
|
n_options = n_global_long_options;
|
2015-06-11 08:19:15 -07:00
|
|
|
|
ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
|
2011-02-08 16:10:34 -08:00
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
for (;;) {
|
2012-12-10 14:24:36 -08:00
|
|
|
|
int idx;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
int c;
|
|
|
|
|
|
2012-12-10 14:24:36 -08:00
|
|
|
|
c = getopt_long(argc, argv, short_options, options, &idx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
if (c == -1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
case OPT_DB:
|
|
|
|
|
db = optarg;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OPT_ONELINE:
|
|
|
|
|
oneline = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2009-12-09 13:28:48 -08:00
|
|
|
|
case OPT_NO_SYSLOG:
|
2016-02-03 13:21:10 -08:00
|
|
|
|
vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2009-12-10 15:32:50 -08:00
|
|
|
|
case OPT_NO_WAIT:
|
2009-12-16 16:26:17 -08:00
|
|
|
|
wait_for_reload = false;
|
2009-12-10 15:32:50 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2009-12-11 11:28:36 -08:00
|
|
|
|
case OPT_DRY_RUN:
|
|
|
|
|
dry_run = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-12-10 14:24:36 -08:00
|
|
|
|
case OPT_LOCAL:
|
|
|
|
|
if (shash_find(local_options, options[idx].name)) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("'%s' option specified multiple times",
|
2012-12-10 14:24:36 -08:00
|
|
|
|
options[idx].name);
|
|
|
|
|
}
|
|
|
|
|
shash_add_nocopy(local_options,
|
|
|
|
|
xasprintf("--%s", options[idx].name),
|
2016-06-24 21:23:16 -07:00
|
|
|
|
nullable_xstrdup(optarg));
|
2012-12-10 14:24:36 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
case 'h':
|
|
|
|
|
usage();
|
|
|
|
|
|
2015-02-04 09:52:12 -08:00
|
|
|
|
case OPT_COMMANDS:
|
2015-06-11 08:19:15 -07:00
|
|
|
|
ctl_print_commands();
|
2017-06-23 18:12:49 +02:00
|
|
|
|
/* fall through */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
|
|
|
|
|
case OPT_OPTIONS:
|
2015-06-11 08:19:15 -07:00
|
|
|
|
ctl_print_options(global_long_options);
|
2017-06-23 18:12:49 +02:00
|
|
|
|
/* fall through */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
case 'V':
|
2011-08-02 12:16:44 -07:00
|
|
|
|
ovs_print_version(0, 0);
|
2014-02-26 16:29:00 -08:00
|
|
|
|
printf("DB Schema %s\n", ovsrec_get_db_version());
|
2009-12-08 17:18:12 -08:00
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
|
2009-12-14 10:13:36 -08:00
|
|
|
|
case 't':
|
|
|
|
|
timeout = strtoul(optarg, NULL, 10);
|
2009-12-14 13:59:58 -08:00
|
|
|
|
if (timeout < 0) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("value %s on -t or --timeout is invalid",
|
2010-02-02 14:25:11 -08:00
|
|
|
|
optarg);
|
2009-12-14 10:13:36 -08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2013-03-15 16:14:28 -07:00
|
|
|
|
case OPT_RETRY:
|
|
|
|
|
retry = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2010-01-04 19:15:22 -08:00
|
|
|
|
VLOG_OPTION_HANDLERS
|
2011-02-08 16:10:34 -08:00
|
|
|
|
TABLE_OPTION_HANDLERS(&table_style)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2010-03-23 15:29:10 -07:00
|
|
|
|
STREAM_SSL_OPTION_HANDLERS
|
|
|
|
|
|
|
|
|
|
case OPT_PEER_CA_CERT:
|
|
|
|
|
stream_ssl_set_peer_ca_cert_file(optarg);
|
|
|
|
|
break;
|
|
|
|
|
|
2015-08-19 09:21:04 -07:00
|
|
|
|
case OPT_BOOTSTRAP_CA_CERT:
|
|
|
|
|
stream_ssl_set_ca_cert_file(optarg, true);
|
|
|
|
|
break;
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
case '?':
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-16 15:54:47 -07:00
|
|
|
|
free(short_options);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
if (!db) {
|
2015-06-11 08:19:15 -07:00
|
|
|
|
db = ctl_default_db();
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2012-12-10 14:24:36 -08:00
|
|
|
|
|
|
|
|
|
for (i = n_global_long_options; options[i].name; i++) {
|
|
|
|
|
free(CONST_CAST(char *, options[i].name));
|
|
|
|
|
}
|
|
|
|
|
free(options);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage(void)
|
|
|
|
|
{
|
2010-01-27 13:49:19 -08:00
|
|
|
|
printf("\
|
|
|
|
|
%s: ovs-vswitchd management utility\n\
|
|
|
|
|
usage: %s [OPTIONS] COMMAND [ARG...]\n\
|
|
|
|
|
\n\
|
2011-02-10 09:34:42 -08:00
|
|
|
|
Open vSwitch commands:\n\
|
|
|
|
|
init initialize database, if not yet initialized\n\
|
2011-05-24 13:03:58 -07:00
|
|
|
|
show print overview of database contents\n\
|
2011-02-10 09:34:42 -08:00
|
|
|
|
emer-reset reset configuration to clean state\n\
|
|
|
|
|
\n\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
Bridge commands:\n\
|
|
|
|
|
add-br BRIDGE create a new bridge named BRIDGE\n\
|
|
|
|
|
add-br BRIDGE PARENT VLAN create new fake BRIDGE in PARENT on VLAN\n\
|
|
|
|
|
del-br BRIDGE delete BRIDGE and all of its ports\n\
|
|
|
|
|
list-br print the names of all the bridges\n\
|
2012-03-12 15:49:17 -07:00
|
|
|
|
br-exists BRIDGE exit 2 if BRIDGE does not exist\n\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
br-to-vlan BRIDGE print the VLAN which BRIDGE is on\n\
|
|
|
|
|
br-to-parent BRIDGE print the parent of BRIDGE\n\
|
|
|
|
|
br-set-external-id BRIDGE KEY VALUE set KEY on BRIDGE to VALUE\n\
|
|
|
|
|
br-set-external-id BRIDGE KEY unset KEY on BRIDGE\n\
|
|
|
|
|
br-get-external-id BRIDGE KEY print value of KEY on BRIDGE\n\
|
|
|
|
|
br-get-external-id BRIDGE list key-value pairs on BRIDGE\n\
|
|
|
|
|
\n\
|
2011-02-10 09:34:42 -08:00
|
|
|
|
Port commands (a bond is considered to be a single port):\n\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
list-ports BRIDGE print the names of all the ports on BRIDGE\n\
|
|
|
|
|
add-port BRIDGE PORT add network device PORT to BRIDGE\n\
|
|
|
|
|
add-bond BRIDGE PORT IFACE... add bonded port PORT in BRIDGE from IFACES\n\
|
|
|
|
|
del-port [BRIDGE] PORT delete PORT (which may be bonded) from BRIDGE\n\
|
|
|
|
|
port-to-br PORT print name of bridge that contains PORT\n\
|
|
|
|
|
\n\
|
|
|
|
|
Interface commands (a bond consists of multiple interfaces):\n\
|
|
|
|
|
list-ifaces BRIDGE print the names of all interfaces on BRIDGE\n\
|
|
|
|
|
iface-to-br IFACE print name of bridge that contains IFACE\n\
|
|
|
|
|
\n\
|
|
|
|
|
Controller commands:\n\
|
2011-09-15 13:30:18 -07:00
|
|
|
|
get-controller BRIDGE print the controllers for BRIDGE\n\
|
|
|
|
|
del-controller BRIDGE delete the controllers for BRIDGE\n\
|
2018-03-12 19:23:44 +08:00
|
|
|
|
[--inactivity-probe=MSECS]\n\
|
2011-09-15 13:30:18 -07:00
|
|
|
|
set-controller BRIDGE TARGET... set the controllers for BRIDGE\n\
|
2010-07-15 14:53:36 -07:00
|
|
|
|
get-fail-mode BRIDGE print the fail-mode for BRIDGE\n\
|
|
|
|
|
del-fail-mode BRIDGE delete the fail-mode for BRIDGE\n\
|
|
|
|
|
set-fail-mode BRIDGE MODE set the fail-mode for BRIDGE to MODE\n\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
\n\
|
2011-02-04 13:30:02 -08:00
|
|
|
|
Manager commands:\n\
|
2011-09-15 13:30:18 -07:00
|
|
|
|
get-manager print the managers\n\
|
|
|
|
|
del-manager delete the managers\n\
|
2018-03-12 19:23:44 +08:00
|
|
|
|
[--inactivity-probe=MSECS]\n\
|
2011-09-15 13:30:18 -07:00
|
|
|
|
set-manager TARGET... set the list of managers to TARGET...\n\
|
2011-02-04 13:30:02 -08:00
|
|
|
|
\n\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
SSL commands:\n\
|
|
|
|
|
get-ssl print the SSL configuration\n\
|
|
|
|
|
del-ssl delete the SSL configuration\n\
|
|
|
|
|
set-ssl PRIV-KEY CERT CA-CERT set the SSL configuration\n\
|
|
|
|
|
\n\
|
2015-02-20 14:17:11 -05:00
|
|
|
|
Auto Attach commands:\n\
|
|
|
|
|
add-aa-mapping BRIDGE I-SID VLAN add Auto Attach mapping to BRIDGE\n\
|
|
|
|
|
del-aa-mapping BRIDGE I-SID VLAN delete Auto Attach mapping VLAN from BRIDGE\n\
|
|
|
|
|
get-aa-mapping BRIDGE get Auto Attach mappings from BRIDGE\n\
|
|
|
|
|
\n\
|
2010-04-30 15:06:51 -07:00
|
|
|
|
Switch commands:\n\
|
|
|
|
|
emer-reset reset switch to known good state\n\
|
|
|
|
|
\n\
|
2015-05-28 16:19:15 -07:00
|
|
|
|
%s\
|
2018-02-26 14:04:02 -06:00
|
|
|
|
%s\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
\n\
|
|
|
|
|
Options:\n\
|
|
|
|
|
--db=DATABASE connect to DATABASE\n\
|
|
|
|
|
(default: %s)\n\
|
2011-02-10 09:34:42 -08:00
|
|
|
|
--no-wait do not wait for ovs-vswitchd to reconfigure\n\
|
2013-03-15 16:14:28 -07:00
|
|
|
|
--retry keep trying to connect to server forever\n\
|
2011-02-10 09:34:42 -08:00
|
|
|
|
-t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
|
|
|
|
|
--dry-run do not commit changes to database\n\
|
2010-01-27 13:49:19 -08:00
|
|
|
|
--oneline print exactly one line of output per command\n",
|
2018-02-26 14:04:02 -06:00
|
|
|
|
program_name, program_name, ctl_get_db_cmd_usage(),
|
|
|
|
|
ctl_list_db_tables_usage(), ctl_default_db());
|
2017-03-31 13:21:03 -04:00
|
|
|
|
table_usage();
|
2009-12-08 17:18:12 -08:00
|
|
|
|
vlog_usage();
|
2011-02-10 09:34:42 -08:00
|
|
|
|
printf("\
|
|
|
|
|
--no-syslog equivalent to --verbose=vsctl:syslog:warn\n");
|
2018-04-23 13:04:28 -05:00
|
|
|
|
stream_usage("database", true, true, true);
|
2010-01-27 13:49:19 -08:00
|
|
|
|
printf("\n\
|
|
|
|
|
Other options:\n\
|
|
|
|
|
-h, --help display this help message\n\
|
|
|
|
|
-V, --version display version information\n");
|
2009-12-08 17:18:12 -08:00
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
/* ovs-vsctl specific context. Inherits the 'struct ctl_context' as base. */
|
2009-12-10 13:28:22 -08:00
|
|
|
|
struct vsctl_context {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct ctl_context base;
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
|
|
|
|
/* Modifiable state. */
|
2009-12-10 13:28:22 -08:00
|
|
|
|
const struct ovsrec_open_vswitch *ovs;
|
2010-10-22 14:46:30 -07:00
|
|
|
|
bool verified_ports;
|
2010-06-24 11:01:53 -07:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
/* A cache of the contents of the database.
|
|
|
|
|
*
|
|
|
|
|
* A command that needs to use any of this information must first call
|
|
|
|
|
* vsctl_context_populate_cache(). A command that changes anything that
|
|
|
|
|
* could invalidate the cache must either call
|
|
|
|
|
* vsctl_context_invalidate_cache() or manually update the cache to
|
|
|
|
|
* maintain its correctness. */
|
|
|
|
|
bool cache_valid;
|
|
|
|
|
struct shash bridges; /* Maps from bridge name to struct vsctl_bridge. */
|
|
|
|
|
struct shash ports; /* Maps from port name to struct vsctl_port. */
|
|
|
|
|
struct shash ifaces; /* Maps from port name to struct vsctl_iface. */
|
2009-12-10 13:28:22 -08:00
|
|
|
|
};
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge {
|
|
|
|
|
struct ovsrec_bridge *br_cfg;
|
|
|
|
|
char *name;
|
2014-12-15 14:10:38 +01:00
|
|
|
|
struct ovs_list ports; /* Contains "struct vsctl_port"s. */
|
2012-03-16 13:12:54 -07:00
|
|
|
|
|
|
|
|
|
/* VLAN ("fake") bridge support.
|
|
|
|
|
*
|
|
|
|
|
* Use 'parent != NULL' to detect a fake bridge, because 'vlan' can be 0
|
|
|
|
|
* in either case. */
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct hmap children; /* VLAN bridges indexed by 'vlan'. */
|
|
|
|
|
struct hmap_node children_node; /* Node in parent's 'children' hmap. */
|
2012-03-16 13:12:54 -07:00
|
|
|
|
struct vsctl_bridge *parent; /* Real bridge, or NULL. */
|
|
|
|
|
int vlan; /* VLAN VID (0...4095), or 0. */
|
2009-12-08 17:18:12 -08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct vsctl_port {
|
2014-12-15 14:10:38 +01:00
|
|
|
|
struct ovs_list ports_node; /* In struct vsctl_bridge's 'ports' list. */
|
|
|
|
|
struct ovs_list ifaces; /* Contains "struct vsctl_iface"s. */
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct ovsrec_port *port_cfg;
|
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct vsctl_iface {
|
2014-12-15 14:10:38 +01:00
|
|
|
|
struct ovs_list ifaces_node; /* In struct vsctl_port's 'ifaces' list. */
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct ovsrec_interface *iface_cfg;
|
|
|
|
|
struct vsctl_port *port;
|
|
|
|
|
};
|
|
|
|
|
|
2015-09-02 14:20:32 -07:00
|
|
|
|
/* Casts 'base' into 'struct vsctl_context'. */
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static struct vsctl_context *
|
|
|
|
|
vsctl_context_cast(struct ctl_context *base)
|
|
|
|
|
{
|
|
|
|
|
return CONTAINER_OF(base, struct vsctl_context, base);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-06 14:59:40 -08:00
|
|
|
|
static struct vsctl_bridge *find_vlan_bridge(struct vsctl_bridge *parent,
|
|
|
|
|
int vlan);
|
|
|
|
|
|
2010-02-09 12:13:46 -08:00
|
|
|
|
static char *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_to_string(const struct ctl_context *ctx)
|
2010-02-09 12:13:46 -08:00
|
|
|
|
{
|
|
|
|
|
const struct shash_node *node;
|
|
|
|
|
struct svec words;
|
|
|
|
|
char *s;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
svec_init(&words);
|
|
|
|
|
SHASH_FOR_EACH (node, &ctx->options) {
|
|
|
|
|
svec_add(&words, node->name);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < ctx->argc; i++) {
|
|
|
|
|
svec_add(&words, ctx->argv[i]);
|
|
|
|
|
}
|
|
|
|
|
svec_terminate(&words);
|
|
|
|
|
|
|
|
|
|
s = process_escape_args(words.names);
|
|
|
|
|
|
|
|
|
|
svec_destroy(&words);
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-22 14:46:30 -07:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
verify_ports(struct vsctl_context *vsctl_ctx)
|
2010-10-22 14:46:30 -07:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (!vsctl_ctx->verified_ports) {
|
2010-10-22 14:46:30 -07:00
|
|
|
|
const struct ovsrec_bridge *bridge;
|
|
|
|
|
const struct ovsrec_port *port;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_verify_bridges(vsctl_ctx->ovs);
|
|
|
|
|
OVSREC_BRIDGE_FOR_EACH (bridge, vsctl_ctx->base.idl) {
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_bridge_verify_ports(bridge);
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
OVSREC_PORT_FOR_EACH (port, vsctl_ctx->base.idl) {
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_port_verify_interfaces(port);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_ctx->verified_ports = true;
|
2010-10-22 14:46:30 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static struct vsctl_bridge *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_bridge_to_cache(struct vsctl_context *vsctl_ctx,
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct ovsrec_bridge *br_cfg, const char *name,
|
|
|
|
|
struct vsctl_bridge *parent, int vlan)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
|
|
|
|
struct vsctl_bridge *br = xmalloc(sizeof *br);
|
|
|
|
|
br->br_cfg = br_cfg;
|
|
|
|
|
br->name = xstrdup(name);
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_list_init(&br->ports);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
br->parent = parent;
|
|
|
|
|
br->vlan = vlan;
|
2012-04-17 16:56:21 -07:00
|
|
|
|
hmap_init(&br->children);
|
|
|
|
|
if (parent) {
|
2014-11-06 14:59:40 -08:00
|
|
|
|
struct vsctl_bridge *conflict = find_vlan_bridge(parent, vlan);
|
|
|
|
|
if (conflict) {
|
|
|
|
|
VLOG_WARN("%s: bridge has multiple VLAN bridges (%s and %s) "
|
|
|
|
|
"for VLAN %d, but only one is allowed",
|
|
|
|
|
parent->name, name, conflict->name, vlan);
|
|
|
|
|
} else {
|
|
|
|
|
hmap_insert(&parent->children, &br->children_node,
|
|
|
|
|
hash_int(vlan, 0));
|
|
|
|
|
}
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_add(&vsctl_ctx->bridges, br->name, br);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
return br;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-17 16:56:21 -07:00
|
|
|
|
static void
|
|
|
|
|
ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
|
|
|
|
|
struct ovsrec_bridge *bridge)
|
|
|
|
|
{
|
|
|
|
|
struct ovsrec_bridge **bridges;
|
|
|
|
|
size_t i, n;
|
|
|
|
|
|
|
|
|
|
bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
|
|
|
|
|
for (i = n = 0; i < ovs->n_bridges; i++) {
|
|
|
|
|
if (ovs->bridges[i] != bridge) {
|
|
|
|
|
bridges[n++] = ovs->bridges[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
|
|
|
|
|
free(bridges);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_cached_bridge(struct vsctl_context *vsctl_ctx, struct vsctl_bridge *br)
|
2012-04-17 16:56:21 -07:00
|
|
|
|
{
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_assert(ovs_list_is_empty(&br->ports));
|
2012-11-06 13:14:55 -08:00
|
|
|
|
ovs_assert(hmap_is_empty(&br->children));
|
2012-04-17 16:56:21 -07:00
|
|
|
|
if (br->parent) {
|
|
|
|
|
hmap_remove(&br->parent->children, &br->children_node);
|
|
|
|
|
}
|
|
|
|
|
if (br->br_cfg) {
|
|
|
|
|
ovsrec_bridge_delete(br->br_cfg);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs_delete_bridge(vsctl_ctx->ovs, br->br_cfg);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_find_and_delete(&vsctl_ctx->bridges, br->name);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
hmap_destroy(&br->children);
|
|
|
|
|
free(br->name);
|
|
|
|
|
free(br);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static bool
|
|
|
|
|
port_is_fake_bridge(const struct ovsrec_port *port_cfg)
|
|
|
|
|
{
|
|
|
|
|
return (port_cfg->fake_bridge
|
|
|
|
|
&& port_cfg->tag
|
2012-03-16 13:12:54 -07:00
|
|
|
|
&& *port_cfg->tag >= 0 && *port_cfg->tag <= 4095);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct vsctl_bridge *
|
2012-04-17 16:56:21 -07:00
|
|
|
|
find_vlan_bridge(struct vsctl_bridge *parent, int vlan)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct vsctl_bridge *child;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2012-04-17 16:56:21 -07:00
|
|
|
|
HMAP_FOR_EACH_IN_BUCKET (child, children_node, hash_int(vlan, 0),
|
|
|
|
|
&parent->children) {
|
|
|
|
|
if (child->vlan == vlan) {
|
|
|
|
|
return child;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-17 16:56:21 -07:00
|
|
|
|
static struct vsctl_port *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_port_to_cache(struct vsctl_context *vsctl_ctx, struct vsctl_bridge *parent,
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct ovsrec_port *port_cfg)
|
|
|
|
|
{
|
|
|
|
|
struct vsctl_port *port;
|
|
|
|
|
|
|
|
|
|
if (port_cfg->tag
|
|
|
|
|
&& *port_cfg->tag >= 0 && *port_cfg->tag <= 4095) {
|
|
|
|
|
struct vsctl_bridge *vlan_bridge;
|
|
|
|
|
|
|
|
|
|
vlan_bridge = find_vlan_bridge(parent, *port_cfg->tag);
|
|
|
|
|
if (vlan_bridge) {
|
|
|
|
|
parent = vlan_bridge;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
port = xmalloc(sizeof *port);
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_list_push_back(&parent->ports, &port->ports_node);
|
|
|
|
|
ovs_list_init(&port->ifaces);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
port->port_cfg = port_cfg;
|
|
|
|
|
port->bridge = parent;
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_add(&vsctl_ctx->ports, port_cfg->name, port);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
|
|
|
|
|
return port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_cached_port(struct vsctl_context *vsctl_ctx, struct vsctl_port *port)
|
2012-04-17 16:56:21 -07:00
|
|
|
|
{
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_assert(ovs_list_is_empty(&port->ifaces));
|
|
|
|
|
ovs_list_remove(&port->ports_node);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_find_and_delete(&vsctl_ctx->ports, port->port_cfg->name);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
ovsrec_port_delete(port->port_cfg);
|
|
|
|
|
free(port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct vsctl_iface *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_iface_to_cache(struct vsctl_context *vsctl_ctx, struct vsctl_port *parent,
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct ovsrec_interface *iface_cfg)
|
|
|
|
|
{
|
|
|
|
|
struct vsctl_iface *iface;
|
|
|
|
|
|
|
|
|
|
iface = xmalloc(sizeof *iface);
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_list_push_back(&parent->ifaces, &iface->ifaces_node);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
iface->iface_cfg = iface_cfg;
|
|
|
|
|
iface->port = parent;
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_add(&vsctl_ctx->ifaces, iface_cfg->name, iface);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
|
|
|
|
|
return iface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_cached_iface(struct vsctl_context *vsctl_ctx, struct vsctl_iface *iface)
|
2012-04-17 16:56:21 -07:00
|
|
|
|
{
|
2016-03-25 14:10:22 -07:00
|
|
|
|
ovs_list_remove(&iface->ifaces_node);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_find_and_delete(&vsctl_ctx->ifaces, iface->iface_cfg->name);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
ovsrec_interface_delete(iface->iface_cfg);
|
|
|
|
|
free(iface);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_invalidate_cache(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct shash_node *node;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (!vsctl_ctx->cache_valid) {
|
2012-04-17 17:07:00 -07:00
|
|
|
|
return;
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_ctx->cache_valid = false;
|
2012-04-17 17:07:00 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
SHASH_FOR_EACH (node, &vsctl_ctx->bridges) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *bridge = node->data;
|
2012-04-17 16:56:21 -07:00
|
|
|
|
hmap_destroy(&bridge->children);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
free(bridge->name);
|
|
|
|
|
free(bridge);
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_destroy(&vsctl_ctx->bridges);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
shash_destroy_free_data(&vsctl_ctx->ports);
|
|
|
|
|
shash_destroy_free_data(&vsctl_ctx->ifaces);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_get_info(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_bridges);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_name);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_controller);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_fail_mode);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_ports);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_name);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_fake_bridge);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_tag);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_interfaces);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_name);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_ofport);
|
2016-12-20 17:50:06 -08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_error);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_populate_cache(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
const struct ovsrec_open_vswitch *ovs = vsctl_ctx->ovs;
|
2011-03-25 15:26:30 -07:00
|
|
|
|
struct sset bridges, ports;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
size_t i;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (vsctl_ctx->cache_valid) {
|
2012-04-17 17:07:00 -07:00
|
|
|
|
/* Cache is already populated. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_ctx->cache_valid = true;
|
|
|
|
|
shash_init(&vsctl_ctx->bridges);
|
|
|
|
|
shash_init(&vsctl_ctx->ports);
|
|
|
|
|
shash_init(&vsctl_ctx->ifaces);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2011-03-25 15:26:30 -07:00
|
|
|
|
sset_init(&bridges);
|
|
|
|
|
sset_init(&ports);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
for (i = 0; i < ovs->n_bridges; i++) {
|
|
|
|
|
struct ovsrec_bridge *br_cfg = ovs->bridges[i];
|
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
size_t j;
|
|
|
|
|
|
2011-03-25 15:26:30 -07:00
|
|
|
|
if (!sset_add(&bridges, br_cfg->name)) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
VLOG_WARN("%s: database contains duplicate bridge name",
|
|
|
|
|
br_cfg->name);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = add_bridge_to_cache(vsctl_ctx, br_cfg, br_cfg->name, NULL, 0);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
for (j = 0; j < br_cfg->n_ports; j++) {
|
|
|
|
|
struct ovsrec_port *port_cfg = br_cfg->ports[j];
|
|
|
|
|
|
2011-03-25 15:26:30 -07:00
|
|
|
|
if (!sset_add(&ports, port_cfg->name)) {
|
2011-07-08 12:31:55 -07:00
|
|
|
|
/* Duplicate port name. (We will warn about that later.) */
|
2009-12-08 17:18:12 -08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (port_is_fake_bridge(port_cfg)
|
2011-03-25 15:26:30 -07:00
|
|
|
|
&& sset_add(&bridges, port_cfg->name)) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_bridge_to_cache(vsctl_ctx, NULL, port_cfg->name, br,
|
2012-04-17 16:56:21 -07:00
|
|
|
|
*port_cfg->tag);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-25 15:26:30 -07:00
|
|
|
|
sset_destroy(&bridges);
|
|
|
|
|
sset_destroy(&ports);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2011-03-25 15:26:30 -07:00
|
|
|
|
sset_init(&bridges);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
for (i = 0; i < ovs->n_bridges; i++) {
|
|
|
|
|
struct ovsrec_bridge *br_cfg = ovs->bridges[i];
|
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
size_t j;
|
|
|
|
|
|
2011-03-25 15:26:30 -07:00
|
|
|
|
if (!sset_add(&bridges, br_cfg->name)) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = shash_find_data(&vsctl_ctx->bridges, br_cfg->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
for (j = 0; j < br_cfg->n_ports; j++) {
|
|
|
|
|
struct ovsrec_port *port_cfg = br_cfg->ports[j];
|
|
|
|
|
struct vsctl_port *port;
|
|
|
|
|
size_t k;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = shash_find_data(&vsctl_ctx->ports, port_cfg->name);
|
2011-07-08 12:31:55 -07:00
|
|
|
|
if (port) {
|
|
|
|
|
if (port_cfg == port->port_cfg) {
|
|
|
|
|
VLOG_WARN("%s: port is in multiple bridges (%s and %s)",
|
|
|
|
|
port_cfg->name, br->name, port->bridge->name);
|
|
|
|
|
} else {
|
|
|
|
|
/* Log as an error because this violates the database's
|
|
|
|
|
* uniqueness constraints, so the database server shouldn't
|
|
|
|
|
* have allowed it. */
|
|
|
|
|
VLOG_ERR("%s: database contains duplicate port name",
|
|
|
|
|
port_cfg->name);
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (port_is_fake_bridge(port_cfg)
|
2011-03-25 15:26:30 -07:00
|
|
|
|
&& !sset_add(&bridges, port_cfg->name)) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = add_port_to_cache(vsctl_ctx, br, port_cfg);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
for (k = 0; k < port_cfg->n_interfaces; k++) {
|
|
|
|
|
struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
|
|
|
|
|
struct vsctl_iface *iface;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
iface = shash_find_data(&vsctl_ctx->ifaces, iface_cfg->name);
|
2011-07-08 12:31:55 -07:00
|
|
|
|
if (iface) {
|
|
|
|
|
if (iface_cfg == iface->iface_cfg) {
|
|
|
|
|
VLOG_WARN("%s: interface is in multiple ports "
|
|
|
|
|
"(%s and %s)",
|
|
|
|
|
iface_cfg->name,
|
|
|
|
|
iface->port->port_cfg->name,
|
|
|
|
|
port->port_cfg->name);
|
|
|
|
|
} else {
|
|
|
|
|
/* Log as an error because this violates the database's
|
|
|
|
|
* uniqueness constraints, so the database server
|
|
|
|
|
* shouldn't have allowed it. */
|
|
|
|
|
VLOG_ERR("%s: database contains duplicate interface "
|
|
|
|
|
"name", iface_cfg->name);
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_iface_to_cache(vsctl_ctx, port, iface_cfg);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-25 15:26:30 -07:00
|
|
|
|
sset_destroy(&bridges);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
check_conflicts(struct vsctl_context *vsctl_ctx, const char *name,
|
2009-12-08 17:18:12 -08:00
|
|
|
|
char *msg)
|
|
|
|
|
{
|
|
|
|
|
struct vsctl_iface *iface;
|
|
|
|
|
struct vsctl_port *port;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
verify_ports(vsctl_ctx);
|
2010-10-22 14:46:30 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (shash_find(&vsctl_ctx->bridges, name)) {
|
|
|
|
|
ctl_fatal("%s because a bridge named %s already exists",
|
2009-12-10 16:05:20 -08:00
|
|
|
|
msg, name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = shash_find_data(&vsctl_ctx->ports, name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
if (port) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("%s because a port named %s already exists on "
|
2009-12-10 16:05:20 -08:00
|
|
|
|
"bridge %s", msg, name, port->bridge->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
iface = shash_find_data(&vsctl_ctx->ifaces, name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
if (iface) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("%s because an interface named %s already exists "
|
2009-12-10 16:05:20 -08:00
|
|
|
|
"on bridge %s", msg, name, iface->port->bridge->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct vsctl_bridge *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
find_bridge(struct vsctl_context *vsctl_ctx, const char *name, bool must_exist)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2012-04-17 17:07:00 -07:00
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs_assert(vsctl_ctx->cache_valid);
|
2012-04-17 17:07:00 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = shash_find_data(&vsctl_ctx->bridges, name);
|
2009-12-10 13:42:12 -08:00
|
|
|
|
if (must_exist && !br) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("no bridge named %s", name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_verify_bridges(vsctl_ctx->ovs);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
return br;
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-17 16:05:55 -08:00
|
|
|
|
static struct vsctl_bridge *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
find_real_bridge(struct vsctl_context *vsctl_ctx,
|
|
|
|
|
const char *name, bool must_exist)
|
2009-12-17 16:05:55 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_bridge *br = find_bridge(vsctl_ctx, name, must_exist);
|
2009-12-17 16:05:55 -08:00
|
|
|
|
if (br && br->parent) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("%s is a fake bridge", name);
|
2009-12-17 16:05:55 -08:00
|
|
|
|
}
|
|
|
|
|
return br;
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static struct vsctl_port *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
find_port(struct vsctl_context *vsctl_ctx, const char *name, bool must_exist)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2012-04-17 17:07:00 -07:00
|
|
|
|
struct vsctl_port *port;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs_assert(vsctl_ctx->cache_valid);
|
2012-04-17 17:07:00 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = shash_find_data(&vsctl_ctx->ports, name);
|
2009-12-10 14:07:33 -08:00
|
|
|
|
if (port && !strcmp(name, port->bridge->name)) {
|
2009-12-10 13:42:12 -08:00
|
|
|
|
port = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (must_exist && !port) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("no port named %s", name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
verify_ports(vsctl_ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
return port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct vsctl_iface *
|
2015-05-28 16:19:15 -07:00
|
|
|
|
find_iface(struct vsctl_context *vsctl_ctx, const char *name, bool must_exist)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2012-04-17 17:07:00 -07:00
|
|
|
|
struct vsctl_iface *iface;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs_assert(vsctl_ctx->cache_valid);
|
2012-04-17 17:07:00 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
iface = shash_find_data(&vsctl_ctx->ifaces, name);
|
2009-12-10 14:07:33 -08:00
|
|
|
|
if (iface && !strcmp(name, iface->port->bridge->name)) {
|
2009-12-10 13:42:12 -08:00
|
|
|
|
iface = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (must_exist && !iface) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("no interface named %s", name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
verify_ports(vsctl_ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
return iface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
|
|
|
|
|
{
|
|
|
|
|
struct ovsrec_port **ports;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
|
|
|
|
|
for (i = 0; i < br->n_ports; i++) {
|
|
|
|
|
ports[i] = br->ports[i];
|
|
|
|
|
}
|
|
|
|
|
ports[br->n_ports] = port;
|
|
|
|
|
ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
|
|
|
|
|
free(ports);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
|
|
|
|
|
{
|
|
|
|
|
struct ovsrec_port **ports;
|
|
|
|
|
size_t i, n;
|
|
|
|
|
|
|
|
|
|
ports = xmalloc(sizeof *br->ports * br->n_ports);
|
|
|
|
|
for (i = n = 0; i < br->n_ports; i++) {
|
|
|
|
|
if (br->ports[i] != port) {
|
|
|
|
|
ports[n++] = br->ports[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ovsrec_bridge_set_ports(br, ports, n);
|
|
|
|
|
free(ports);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
|
|
|
|
|
struct ovsrec_bridge *bridge)
|
|
|
|
|
{
|
|
|
|
|
struct ovsrec_bridge **bridges;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
|
|
|
|
|
for (i = 0; i < ovs->n_bridges; i++) {
|
|
|
|
|
bridges[i] = ovs->bridges[i];
|
|
|
|
|
}
|
|
|
|
|
bridges[ovs->n_bridges] = bridge;
|
|
|
|
|
ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
|
|
|
|
|
free(bridges);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-11 10:40:55 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_init(struct ctl_context *ctx OVS_UNUSED)
|
2009-12-11 10:40:55 -08:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-17 16:56:02 -07:00
|
|
|
|
static struct cmd_show_table cmd_show_tables[] = {
|
2011-05-24 13:03:58 -07:00
|
|
|
|
{&ovsrec_table_open_vswitch,
|
|
|
|
|
NULL,
|
|
|
|
|
{&ovsrec_open_vswitch_col_manager_options,
|
|
|
|
|
&ovsrec_open_vswitch_col_bridges,
|
2015-08-12 21:29:06 -07:00
|
|
|
|
&ovsrec_open_vswitch_col_ovs_version},
|
|
|
|
|
{NULL, NULL, NULL}
|
2015-07-17 16:39:07 -07:00
|
|
|
|
},
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
|
|
|
|
{&ovsrec_table_bridge,
|
|
|
|
|
&ovsrec_bridge_col_name,
|
|
|
|
|
{&ovsrec_bridge_col_controller,
|
|
|
|
|
&ovsrec_bridge_col_fail_mode,
|
2015-08-12 21:29:06 -07:00
|
|
|
|
&ovsrec_bridge_col_ports},
|
|
|
|
|
{NULL, NULL, NULL}
|
2015-07-17 16:39:07 -07:00
|
|
|
|
},
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
|
|
|
|
{&ovsrec_table_port,
|
|
|
|
|
&ovsrec_port_col_name,
|
|
|
|
|
{&ovsrec_port_col_tag,
|
|
|
|
|
&ovsrec_port_col_trunks,
|
2015-08-12 21:29:06 -07:00
|
|
|
|
&ovsrec_port_col_interfaces},
|
|
|
|
|
{NULL, NULL, NULL}
|
2015-07-17 16:39:07 -07:00
|
|
|
|
},
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
|
|
|
|
{&ovsrec_table_interface,
|
|
|
|
|
&ovsrec_interface_col_name,
|
|
|
|
|
{&ovsrec_interface_col_type,
|
|
|
|
|
&ovsrec_interface_col_options,
|
2018-03-12 10:31:25 +00:00
|
|
|
|
&ovsrec_interface_col_error,
|
|
|
|
|
&ovsrec_interface_col_bfd_status},
|
2015-08-12 21:29:06 -07:00
|
|
|
|
{NULL, NULL, NULL}
|
2015-07-17 16:39:07 -07:00
|
|
|
|
},
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
|
|
|
|
{&ovsrec_table_controller,
|
|
|
|
|
&ovsrec_controller_col_target,
|
|
|
|
|
{&ovsrec_controller_col_is_connected,
|
|
|
|
|
NULL,
|
2015-08-12 21:29:06 -07:00
|
|
|
|
NULL},
|
|
|
|
|
{NULL, NULL, NULL}
|
2015-07-17 16:39:07 -07:00
|
|
|
|
},
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
|
|
|
|
{&ovsrec_table_manager,
|
|
|
|
|
&ovsrec_manager_col_target,
|
|
|
|
|
{&ovsrec_manager_col_is_connected,
|
|
|
|
|
NULL,
|
2015-08-12 21:29:06 -07:00
|
|
|
|
NULL},
|
|
|
|
|
{NULL, NULL, NULL}
|
2015-07-17 16:39:07 -07:00
|
|
|
|
},
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
2015-08-12 21:29:06 -07:00
|
|
|
|
{NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}}
|
2015-06-11 09:45:06 -07:00
|
|
|
|
};
|
2011-05-24 13:03:58 -07:00
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_cmd_emer_reset(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
2011-02-02 00:08:12 -08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_controller);
|
2011-01-17 16:52:16 -08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_fail_mode);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_mirrors);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_netflow);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_sflow);
|
2013-04-22 10:01:14 -07:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_ipfix);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_flood_vlans);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_other_config);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_other_config);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl,
|
|
|
|
|
&ovsrec_interface_col_ingress_policing_rate);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl,
|
|
|
|
|
&ovsrec_interface_col_ingress_policing_burst);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-30 15:06:51 -07:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_emer_reset(struct ctl_context *ctx)
|
2010-04-30 15:06:51 -07:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
const struct ovsdb_idl *idl = ctx->idl;
|
|
|
|
|
const struct ovsrec_bridge *br;
|
|
|
|
|
const struct ovsrec_port *port;
|
|
|
|
|
const struct ovsrec_interface *iface;
|
2011-03-16 15:06:37 -07:00
|
|
|
|
const struct ovsrec_mirror *mirror, *next_mirror;
|
|
|
|
|
const struct ovsrec_controller *ctrl, *next_ctrl;
|
|
|
|
|
const struct ovsrec_manager *mgr, *next_mgr;
|
|
|
|
|
const struct ovsrec_netflow *nf, *next_nf;
|
|
|
|
|
const struct ovsrec_ssl *ssl, *next_ssl;
|
|
|
|
|
const struct ovsrec_sflow *sflow, *next_sflow;
|
2013-04-22 10:01:14 -07:00
|
|
|
|
const struct ovsrec_ipfix *ipfix, *next_ipfix;
|
|
|
|
|
const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
|
2010-04-30 15:06:51 -07:00
|
|
|
|
|
|
|
|
|
/* Reset the Open_vSwitch table. */
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_set_manager_options(vsctl_ctx->ovs, NULL, 0);
|
|
|
|
|
ovsrec_open_vswitch_set_ssl(vsctl_ctx->ovs, NULL);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
|
|
|
|
|
OVSREC_BRIDGE_FOR_EACH (br, idl) {
|
2012-05-22 01:53:07 -07:00
|
|
|
|
const char *hwaddr;
|
2010-04-30 15:06:51 -07:00
|
|
|
|
|
|
|
|
|
ovsrec_bridge_set_controller(br, NULL, 0);
|
2011-01-17 16:52:16 -08:00
|
|
|
|
ovsrec_bridge_set_fail_mode(br, NULL);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
ovsrec_bridge_set_mirrors(br, NULL, 0);
|
|
|
|
|
ovsrec_bridge_set_netflow(br, NULL);
|
|
|
|
|
ovsrec_bridge_set_sflow(br, NULL);
|
2013-04-22 10:01:14 -07:00
|
|
|
|
ovsrec_bridge_set_ipfix(br, NULL);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
ovsrec_bridge_set_flood_vlans(br, NULL, 0);
|
|
|
|
|
|
|
|
|
|
/* We only want to save the "hwaddr" key from other_config. */
|
2012-05-22 01:53:07 -07:00
|
|
|
|
hwaddr = smap_get(&br->other_config, "hwaddr");
|
|
|
|
|
if (hwaddr) {
|
2015-09-08 18:39:25 -07:00
|
|
|
|
const struct smap smap = SMAP_CONST1(&smap, "hwaddr", hwaddr);
|
2012-05-22 01:53:07 -07:00
|
|
|
|
ovsrec_bridge_set_other_config(br, &smap);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
} else {
|
2012-05-22 01:53:07 -07:00
|
|
|
|
ovsrec_bridge_set_other_config(br, NULL);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_PORT_FOR_EACH (port, idl) {
|
2012-05-22 01:53:07 -07:00
|
|
|
|
ovsrec_port_set_other_config(port, NULL);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_INTERFACE_FOR_EACH (iface, idl) {
|
|
|
|
|
/* xxx What do we do about gre/patch devices created by mgr? */
|
|
|
|
|
|
|
|
|
|
ovsrec_interface_set_ingress_policing_rate(iface, 0);
|
|
|
|
|
ovsrec_interface_set_ingress_policing_burst(iface, 0);
|
|
|
|
|
}
|
2011-03-16 15:06:37 -07:00
|
|
|
|
|
|
|
|
|
OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
|
|
|
|
|
ovsrec_mirror_delete(mirror);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
|
|
|
|
|
ovsrec_controller_delete(ctrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
|
|
|
|
|
ovsrec_manager_delete(mgr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
|
|
|
|
|
ovsrec_netflow_delete(nf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
|
|
|
|
|
ovsrec_ssl_delete(ssl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_SFLOW_FOR_EACH_SAFE (sflow, next_sflow, idl) {
|
|
|
|
|
ovsrec_sflow_delete(sflow);
|
|
|
|
|
}
|
2012-04-17 17:07:00 -07:00
|
|
|
|
|
2013-04-22 10:01:14 -07:00
|
|
|
|
OVSREC_IPFIX_FOR_EACH_SAFE (ipfix, next_ipfix, idl) {
|
|
|
|
|
ovsrec_ipfix_delete(ipfix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset, idl) {
|
|
|
|
|
ovsrec_flow_sample_collector_set_delete(fscset);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_invalidate_cache(ctx);
|
2010-04-30 15:06:51 -07:00
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_add_br(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2011-05-04 13:49:42 -07:00
|
|
|
|
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
|
2010-02-10 11:21:56 -08:00
|
|
|
|
const char *br_name, *parent_name;
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
struct ovsrec_interface *iface;
|
2010-02-10 11:21:56 -08:00
|
|
|
|
int vlan;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2010-02-09 11:03:14 -08:00
|
|
|
|
br_name = ctx->argv[1];
|
2017-02-03 14:13:38 -08:00
|
|
|
|
if (!br_name[0]) {
|
|
|
|
|
ctl_fatal("bridge name must not be empty string");
|
|
|
|
|
}
|
2010-02-09 11:03:14 -08:00
|
|
|
|
if (ctx->argc == 2) {
|
|
|
|
|
parent_name = NULL;
|
|
|
|
|
vlan = 0;
|
|
|
|
|
} else if (ctx->argc == 4) {
|
|
|
|
|
parent_name = ctx->argv[2];
|
|
|
|
|
vlan = atoi(ctx->argv[3]);
|
2012-03-16 13:12:54 -07:00
|
|
|
|
if (vlan < 0 || vlan > 4095) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("%s: vlan must be between 0 and 4095", ctx->argv[0]);
|
2010-02-09 11:03:14 -08:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("'%s' command takes exactly 1 or 3 arguments",
|
2010-02-09 11:03:14 -08:00
|
|
|
|
ctx->argv[0]);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2010-02-09 11:03:14 -08:00
|
|
|
|
if (may_exist) {
|
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, br_name, false);
|
2010-02-09 11:03:14 -08:00
|
|
|
|
if (br) {
|
|
|
|
|
if (!parent_name) {
|
|
|
|
|
if (br->parent) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("\"--may-exist add-br %s\" but %s is "
|
2010-02-09 11:03:14 -08:00
|
|
|
|
"a VLAN bridge for VLAN %d",
|
|
|
|
|
br_name, br_name, br->vlan);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!br->parent) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
|
2010-02-09 11:03:14 -08:00
|
|
|
|
"is not a VLAN bridge",
|
|
|
|
|
br_name, parent_name, vlan, br_name);
|
|
|
|
|
} else if (strcmp(br->parent->name, parent_name)) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
|
2010-02-09 11:03:14 -08:00
|
|
|
|
"has the wrong parent %s",
|
|
|
|
|
br_name, parent_name, vlan,
|
|
|
|
|
br_name, br->parent->name);
|
|
|
|
|
} else if (br->vlan != vlan) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
|
2010-02-09 11:03:14 -08:00
|
|
|
|
"is a VLAN bridge for the wrong VLAN %d",
|
|
|
|
|
br_name, parent_name, vlan, br_name, br->vlan);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
check_conflicts(vsctl_ctx, br_name,
|
2009-12-08 17:18:12 -08:00
|
|
|
|
xasprintf("cannot create a bridge named %s", br_name));
|
|
|
|
|
|
2010-02-09 11:03:14 -08:00
|
|
|
|
if (!parent_name) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct ovsrec_port *port;
|
2010-02-09 11:03:14 -08:00
|
|
|
|
struct ovsrec_bridge *br;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
iface = ovsrec_interface_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_interface_set_name(iface, br_name);
|
2010-11-04 10:53:57 -07:00
|
|
|
|
ovsrec_interface_set_type(iface, "internal");
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
port = ovsrec_port_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_port_set_name(port, br_name);
|
|
|
|
|
ovsrec_port_set_interfaces(port, &iface, 1);
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
br = ovsrec_bridge_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_bridge_set_name(br, br_name);
|
|
|
|
|
ovsrec_bridge_set_ports(br, &port, 1);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs_insert_bridge(vsctl_ctx->ovs, br);
|
2010-02-09 11:03:14 -08:00
|
|
|
|
} else {
|
2014-11-06 14:59:40 -08:00
|
|
|
|
struct vsctl_bridge *conflict;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *parent;
|
|
|
|
|
struct ovsrec_port *port;
|
2010-02-09 11:03:14 -08:00
|
|
|
|
struct ovsrec_bridge *br;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
int64_t tag = vlan;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
parent = find_bridge(vsctl_ctx, parent_name, false);
|
2012-03-16 13:12:54 -07:00
|
|
|
|
if (parent && parent->parent) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("cannot create bridge with fake bridge as parent");
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
if (!parent) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("parent bridge %s does not exist", parent_name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2014-11-06 14:59:40 -08:00
|
|
|
|
conflict = find_vlan_bridge(parent, vlan);
|
|
|
|
|
if (conflict) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("bridge %s already has a child VLAN bridge %s "
|
2014-11-06 14:59:40 -08:00
|
|
|
|
"on VLAN %d", parent_name, conflict->name, vlan);
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
br = parent->br_cfg;
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
iface = ovsrec_interface_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_interface_set_name(iface, br_name);
|
|
|
|
|
ovsrec_interface_set_type(iface, "internal");
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
port = ovsrec_port_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_port_set_name(port, br_name);
|
|
|
|
|
ovsrec_port_set_interfaces(port, &iface, 1);
|
|
|
|
|
ovsrec_port_set_fake_bridge(port, true);
|
|
|
|
|
ovsrec_port_set_tag(port, &tag, 1);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
|
|
|
|
|
bridge_insert_port(br, port);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
post_db_reload_expect_iface(iface);
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_invalidate_cache(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_port(struct vsctl_context *vsctl_ctx, struct vsctl_port *port)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct vsctl_iface *iface, *next_iface;
|
2011-03-16 15:06:37 -07:00
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
bridge_delete_port((port->bridge->parent
|
|
|
|
|
? port->bridge->parent->br_cfg
|
|
|
|
|
: port->bridge->br_cfg), port->port_cfg);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
|
|
|
|
|
LIST_FOR_EACH_SAFE (iface, next_iface, ifaces_node, &port->ifaces) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_cached_iface(vsctl_ctx, iface);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_cached_port(vsctl_ctx, port);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_bridge(struct vsctl_context *vsctl_ctx, struct vsctl_bridge *br)
|
2012-04-17 16:56:21 -07:00
|
|
|
|
{
|
|
|
|
|
struct vsctl_bridge *child, *next_child;
|
|
|
|
|
struct vsctl_port *port, *next_port;
|
2013-04-22 10:01:14 -07:00
|
|
|
|
const struct ovsrec_flow_sample_collector_set *fscset, *next_fscset;
|
2012-04-17 16:56:21 -07:00
|
|
|
|
|
|
|
|
|
HMAP_FOR_EACH_SAFE (child, next_child, children_node, &br->children) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_bridge(vsctl_ctx, child);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIST_FOR_EACH_SAFE (port, next_port, ports_node, &br->ports) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_port(vsctl_ctx, port);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
2013-04-22 10:01:14 -07:00
|
|
|
|
OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH_SAFE (fscset, next_fscset,
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_ctx->base.idl) {
|
2013-04-22 10:01:14 -07:00
|
|
|
|
if (fscset->bridge == br->br_cfg) {
|
|
|
|
|
ovsrec_flow_sample_collector_set_delete(fscset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_cached_bridge(vsctl_ctx, br);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_br(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-10 14:07:33 -08:00
|
|
|
|
bool must_exist = !shash_find(&ctx->options, "--if-exists");
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, ctx->argv[1], must_exist);
|
2009-12-10 14:07:33 -08:00
|
|
|
|
if (bridge) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_bridge(vsctl_ctx, bridge);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-09 13:28:48 -08:00
|
|
|
|
static void
|
|
|
|
|
output_sorted(struct svec *svec, struct ds *output)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
svec_sort(svec);
|
|
|
|
|
SVEC_FOR_EACH (i, name, svec) {
|
|
|
|
|
ds_put_format(output, "%s\n", name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_list_br(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct shash_node *node;
|
2009-12-09 13:28:48 -08:00
|
|
|
|
struct svec bridges;
|
2012-11-30 18:50:18 -08:00
|
|
|
|
bool real = shash_find(&ctx->options, "--real");
|
|
|
|
|
bool fake = shash_find(&ctx->options, "--fake");
|
|
|
|
|
|
|
|
|
|
/* If neither fake nor real were requested, return both. */
|
|
|
|
|
if (!real && !fake) {
|
|
|
|
|
real = fake = true;
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
|
|
|
|
|
svec_init(&bridges);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
SHASH_FOR_EACH (node, &vsctl_ctx->bridges) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *br = node->data;
|
2012-11-30 18:50:18 -08:00
|
|
|
|
|
|
|
|
|
if (br->parent ? fake : real) {
|
|
|
|
|
svec_add(&bridges, br->name);
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2009-12-10 13:28:22 -08:00
|
|
|
|
output_sorted(&bridges, &ctx->output);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
svec_destroy(&bridges);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_br_exists(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (!find_bridge(vsctl_ctx, ctx->argv[1], false)) {
|
2015-07-13 23:24:11 -07:00
|
|
|
|
vsctl_exit(2);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-09 17:04:08 -08:00
|
|
|
|
static void
|
2012-05-22 01:53:07 -07:00
|
|
|
|
set_external_id(struct smap *old, struct smap *new,
|
|
|
|
|
char *key, char *value)
|
2009-12-09 17:04:08 -08:00
|
|
|
|
{
|
2012-05-22 01:53:07 -07:00
|
|
|
|
smap_clone(new, old);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
|
|
|
|
|
if (value) {
|
2012-05-22 01:53:07 -07:00
|
|
|
|
smap_replace(new, key, value);
|
|
|
|
|
} else {
|
|
|
|
|
smap_remove(new, key);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_cmd_br_set_external_id(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
|
|
|
|
pre_get_info(ctx);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_external_ids);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_external_ids);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-09 17:04:08 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_br_set_external_id(struct ctl_context *ctx)
|
2009-12-09 17:04:08 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
struct vsctl_bridge *bridge;
|
2012-05-22 01:53:07 -07:00
|
|
|
|
struct smap new;
|
2009-12-09 17:04:08 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
if (bridge->br_cfg) {
|
2012-05-22 01:53:07 -07:00
|
|
|
|
|
|
|
|
|
set_external_id(&bridge->br_cfg->external_ids, &new, ctx->argv[2],
|
|
|
|
|
ctx->argc >= 4 ? ctx->argv[3] : NULL);
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_bridge_verify_external_ids(bridge->br_cfg);
|
2012-05-22 01:53:07 -07:00
|
|
|
|
ovsrec_bridge_set_external_ids(bridge->br_cfg, &new);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
} else {
|
2009-12-10 13:28:22 -08:00
|
|
|
|
char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_port *port = shash_find_data(&vsctl_ctx->ports,
|
|
|
|
|
ctx->argv[1]);
|
2012-05-22 01:53:07 -07:00
|
|
|
|
set_external_id(&port->port_cfg->external_ids, &new,
|
|
|
|
|
key, ctx->argc >= 4 ? ctx->argv[3] : NULL);
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_port_verify_external_ids(port->port_cfg);
|
2012-05-22 01:53:07 -07:00
|
|
|
|
ovsrec_port_set_external_ids(port->port_cfg, &new);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
free(key);
|
|
|
|
|
}
|
2012-05-22 01:53:07 -07:00
|
|
|
|
smap_destroy(&new);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-05-22 01:53:07 -07:00
|
|
|
|
get_external_id(struct smap *smap, const char *prefix, const char *key,
|
2009-12-09 17:04:08 -08:00
|
|
|
|
struct ds *output)
|
|
|
|
|
{
|
2012-05-22 01:53:07 -07:00
|
|
|
|
if (key) {
|
|
|
|
|
char *prefix_key = xasprintf("%s%s", prefix, key);
|
|
|
|
|
const char *value = smap_get(smap, prefix_key);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
|
2012-05-22 01:53:07 -07:00
|
|
|
|
if (value) {
|
|
|
|
|
ds_put_format(output, "%s\n", value);
|
|
|
|
|
}
|
|
|
|
|
free(prefix_key);
|
|
|
|
|
} else {
|
|
|
|
|
const struct smap_node **sorted = smap_sort(smap);
|
|
|
|
|
size_t prefix_len = strlen(prefix);
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < smap_count(smap); i++) {
|
|
|
|
|
const struct smap_node *node = sorted[i];
|
|
|
|
|
if (!strncmp(node->key, prefix, prefix_len)) {
|
|
|
|
|
ds_put_format(output, "%s=%s\n", node->key + prefix_len,
|
|
|
|
|
node->value);
|
|
|
|
|
}
|
2009-12-09 17:04:08 -08:00
|
|
|
|
}
|
2012-05-22 01:53:07 -07:00
|
|
|
|
free(sorted);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_cmd_br_get_external_id(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
|
|
|
|
pre_cmd_br_set_external_id(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-09 17:04:08 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_br_get_external_id(struct ctl_context *ctx)
|
2009-12-09 17:04:08 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
if (bridge->br_cfg) {
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_bridge_verify_external_ids(bridge->br_cfg);
|
2012-05-22 01:53:07 -07:00
|
|
|
|
get_external_id(&bridge->br_cfg->external_ids, "",
|
|
|
|
|
ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
} else {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_port *port = shash_find_data(&vsctl_ctx->ports,
|
|
|
|
|
ctx->argv[1]);
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_port_verify_external_ids(port->port_cfg);
|
2012-05-22 01:53:07 -07:00
|
|
|
|
get_external_id(&port->port_cfg->external_ids, "fake-bridge-",
|
|
|
|
|
ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
|
2009-12-09 17:04:08 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_list_ports(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *br;
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct vsctl_port *port;
|
2009-12-09 13:28:48 -08:00
|
|
|
|
struct svec ports;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_bridge_verify_ports(br->br_cfg ? br->br_cfg : br->parent->br_cfg);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
|
|
|
|
|
svec_init(&ports);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
LIST_FOR_EACH (port, ports_node, &br->ports) {
|
|
|
|
|
if (strcmp(port->port_cfg->name, br->name)) {
|
2009-12-09 13:28:48 -08:00
|
|
|
|
svec_add(&ports, port->port_cfg->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-12-10 13:28:22 -08:00
|
|
|
|
output_sorted(&ports, &ctx->output);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
svec_destroy(&ports);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_port(struct ctl_context *ctx,
|
2010-02-09 12:13:46 -08:00
|
|
|
|
const char *br_name, const char *port_name,
|
|
|
|
|
bool may_exist, bool fake_iface,
|
2010-04-05 12:58:21 -07:00
|
|
|
|
char *iface_names[], int n_ifaces,
|
|
|
|
|
char *settings[], int n_settings)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
struct ovsrec_interface **ifaces;
|
|
|
|
|
struct ovsrec_port *port;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
2017-02-03 14:13:38 -08:00
|
|
|
|
if (!port_name[0]) {
|
|
|
|
|
ctl_fatal("port name must not be empty string");
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < n_ifaces; i++) {
|
|
|
|
|
if (!iface_names[i][0]) {
|
|
|
|
|
ctl_fatal("interface name must not be empty string");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2010-02-09 12:13:46 -08:00
|
|
|
|
if (may_exist) {
|
2010-09-02 10:09:09 -07:00
|
|
|
|
struct vsctl_port *vsctl_port;
|
2010-02-09 12:13:46 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_port = find_port(vsctl_ctx, port_name, false);
|
2010-09-02 10:09:09 -07:00
|
|
|
|
if (vsctl_port) {
|
2010-02-09 12:13:46 -08:00
|
|
|
|
struct svec want_names, have_names;
|
|
|
|
|
|
|
|
|
|
svec_init(&want_names);
|
|
|
|
|
for (i = 0; i < n_ifaces; i++) {
|
|
|
|
|
svec_add(&want_names, iface_names[i]);
|
|
|
|
|
}
|
|
|
|
|
svec_sort(&want_names);
|
|
|
|
|
|
|
|
|
|
svec_init(&have_names);
|
2010-09-02 10:09:09 -07:00
|
|
|
|
for (i = 0; i < vsctl_port->port_cfg->n_interfaces; i++) {
|
|
|
|
|
svec_add(&have_names,
|
|
|
|
|
vsctl_port->port_cfg->interfaces[i]->name);
|
2010-02-09 12:13:46 -08:00
|
|
|
|
}
|
|
|
|
|
svec_sort(&have_names);
|
|
|
|
|
|
2010-09-02 10:09:09 -07:00
|
|
|
|
if (strcmp(vsctl_port->bridge->name, br_name)) {
|
2010-02-09 12:13:46 -08:00
|
|
|
|
char *command = vsctl_context_to_string(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("\"%s\" but %s is actually attached to bridge %s",
|
2010-09-02 10:09:09 -07:00
|
|
|
|
command, port_name, vsctl_port->bridge->name);
|
2010-02-09 12:13:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!svec_equal(&want_names, &have_names)) {
|
|
|
|
|
char *have_names_string = svec_join(&have_names, ", ", "");
|
|
|
|
|
char *command = vsctl_context_to_string(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("\"%s\" but %s actually has interface(s) %s",
|
2010-02-09 12:13:46 -08:00
|
|
|
|
command, port_name, have_names_string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
svec_destroy(&want_names);
|
|
|
|
|
svec_destroy(&have_names);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
check_conflicts(vsctl_ctx, port_name,
|
2009-12-08 17:18:12 -08:00
|
|
|
|
xasprintf("cannot create a port named %s", port_name));
|
2010-02-09 12:13:46 -08:00
|
|
|
|
for (i = 0; i < n_ifaces; i++) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
check_conflicts(vsctl_ctx, iface_names[i],
|
2010-02-09 12:13:46 -08:00
|
|
|
|
xasprintf("cannot create an interface named %s",
|
|
|
|
|
iface_names[i]));
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, br_name, true);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
ifaces = xmalloc(n_ifaces * sizeof *ifaces);
|
|
|
|
|
for (i = 0; i < n_ifaces; i++) {
|
2010-01-28 16:09:26 -08:00
|
|
|
|
ifaces[i] = ovsrec_interface_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_interface_set_name(ifaces[i], iface_names[i]);
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
post_db_reload_expect_iface(ifaces[i]);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
port = ovsrec_port_insert(ctx->txn);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
ovsrec_port_set_name(port, port_name);
|
|
|
|
|
ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
|
2010-01-14 21:53:43 -08:00
|
|
|
|
ovsrec_port_set_bond_fake_iface(port, fake_iface);
|
2009-12-09 22:14:54 -08:00
|
|
|
|
|
2012-03-16 13:12:54 -07:00
|
|
|
|
if (bridge->parent) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
int64_t tag = bridge->vlan;
|
|
|
|
|
ovsrec_port_set_tag(port, &tag, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-05 12:58:21 -07:00
|
|
|
|
for (i = 0; i < n_settings; i++) {
|
2018-07-02 12:50:09 +02:00
|
|
|
|
char *error = ctl_set_column("Port", &port->header_, settings[i],
|
|
|
|
|
ctx->symtab);
|
|
|
|
|
if (error) {
|
|
|
|
|
ctl_fatal("%s", error);
|
|
|
|
|
}
|
2010-04-05 12:58:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
|
|
|
|
|
: bridge->br_cfg), port);
|
|
|
|
|
|
2017-08-02 15:03:06 -07:00
|
|
|
|
struct vsctl_port *vsctl_port = add_port_to_cache(vsctl_ctx, bridge, port);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
for (i = 0; i < n_ifaces; i++) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
add_iface_to_cache(vsctl_ctx, vsctl_port, ifaces[i]);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
}
|
|
|
|
|
free(ifaces);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_add_port(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2011-05-04 13:49:42 -07:00
|
|
|
|
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
|
2010-02-09 12:13:46 -08:00
|
|
|
|
|
|
|
|
|
add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, false,
|
2010-04-05 12:58:21 -07:00
|
|
|
|
&ctx->argv[2], 1, &ctx->argv[3], ctx->argc - 3);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_add_bond(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2011-05-04 13:49:42 -07:00
|
|
|
|
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
|
2010-01-14 21:53:43 -08:00
|
|
|
|
bool fake_iface = shash_find(&ctx->options, "--fake-iface");
|
2010-04-05 12:58:21 -07:00
|
|
|
|
int n_ifaces;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
n_ifaces = ctx->argc - 3;
|
|
|
|
|
for (i = 3; i < ctx->argc; i++) {
|
|
|
|
|
if (strchr(ctx->argv[i], '=')) {
|
|
|
|
|
n_ifaces = i - 3;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (n_ifaces < 2) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("add-bond requires at least 2 interfaces, but only "
|
2010-04-05 12:58:21 -07:00
|
|
|
|
"%d were specified", n_ifaces);
|
|
|
|
|
}
|
2010-01-14 21:53:43 -08:00
|
|
|
|
|
2010-02-09 12:13:46 -08:00
|
|
|
|
add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, fake_iface,
|
2010-04-05 12:58:21 -07:00
|
|
|
|
&ctx->argv[3], n_ifaces,
|
|
|
|
|
&ctx->argv[n_ifaces + 3], ctx->argc - 3 - n_ifaces);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 13:49:37 -08:00
|
|
|
|
static void
|
|
|
|
|
cmd_add_bond_iface(struct ctl_context *ctx)
|
|
|
|
|
{
|
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
|
|
|
|
|
struct vsctl_port *port = find_port(vsctl_ctx, ctx->argv[1], true);
|
|
|
|
|
|
|
|
|
|
const char *iface_name = ctx->argv[2];
|
|
|
|
|
if (may_exist) {
|
|
|
|
|
struct vsctl_iface *iface = find_iface(vsctl_ctx, iface_name, false);
|
|
|
|
|
if (iface) {
|
|
|
|
|
if (iface->port == port) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
char *command = vsctl_context_to_string(ctx);
|
|
|
|
|
ctl_fatal("\"%s\" but %s is actually attached to port %s",
|
|
|
|
|
command, iface_name, iface->port->port_cfg->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
check_conflicts(vsctl_ctx, iface_name,
|
|
|
|
|
xasprintf("cannot create an interface named %s",
|
|
|
|
|
iface_name));
|
|
|
|
|
|
|
|
|
|
struct ovsrec_interface *iface = ovsrec_interface_insert(ctx->txn);
|
|
|
|
|
ovsrec_interface_set_name(iface, iface_name);
|
|
|
|
|
ovsrec_port_update_interfaces_addvalue(port->port_cfg, iface);
|
|
|
|
|
post_db_reload_expect_iface(iface);
|
|
|
|
|
add_iface_to_cache(vsctl_ctx, port, iface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
cmd_del_bond_iface(struct ctl_context *ctx)
|
|
|
|
|
{
|
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
const char *iface_name = ctx->argv[ctx->argc - 1];
|
|
|
|
|
bool must_exist = !shash_find(&ctx->options, "--if-exists");
|
|
|
|
|
struct vsctl_iface *iface = find_iface(vsctl_ctx, iface_name, must_exist);
|
|
|
|
|
if (!iface) {
|
|
|
|
|
ovs_assert(!must_exist);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *port_name = ctx->argc > 2 ? ctx->argv[1] : NULL;
|
|
|
|
|
if (port_name) {
|
|
|
|
|
struct vsctl_port *port = find_port(vsctl_ctx, port_name, true);
|
|
|
|
|
if (iface->port != port) {
|
|
|
|
|
ctl_fatal("port %s does not have an interface %s",
|
|
|
|
|
port_name, iface_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ovs_list_is_short(&iface->port->ifaces)) {
|
|
|
|
|
ctl_fatal("cannot delete last interface from port %s",
|
|
|
|
|
iface->port->port_cfg->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ovsrec_port_update_interfaces_delvalue(iface->port->port_cfg,
|
|
|
|
|
iface->iface_cfg);
|
|
|
|
|
del_cached_iface(vsctl_ctx, iface);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_port(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-10 14:07:33 -08:00
|
|
|
|
bool must_exist = !shash_find(&ctx->options, "--if-exists");
|
2010-02-22 16:36:30 -08:00
|
|
|
|
bool with_iface = shash_find(&ctx->options, "--with-iface") != NULL;
|
2013-06-18 21:01:33 -07:00
|
|
|
|
const char *target = ctx->argv[ctx->argc - 1];
|
2010-02-22 16:36:30 -08:00
|
|
|
|
struct vsctl_port *port;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (find_bridge(vsctl_ctx, target, false)) {
|
2013-07-08 10:47:37 -07:00
|
|
|
|
if (must_exist) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("cannot delete port %s because it is the local port "
|
2013-07-08 10:47:37 -07:00
|
|
|
|
"for bridge %s (deleting this port requires deleting "
|
|
|
|
|
"the entire bridge)", target, target);
|
|
|
|
|
}
|
|
|
|
|
port = NULL;
|
2013-06-18 21:01:33 -07:00
|
|
|
|
} else if (!with_iface) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = find_port(vsctl_ctx, target, must_exist);
|
2010-02-22 16:36:30 -08:00
|
|
|
|
} else {
|
|
|
|
|
struct vsctl_iface *iface;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = find_port(vsctl_ctx, target, false);
|
2010-02-22 16:36:30 -08:00
|
|
|
|
if (!port) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
iface = find_iface(vsctl_ctx, target, false);
|
2010-02-22 16:36:30 -08:00
|
|
|
|
if (iface) {
|
|
|
|
|
port = iface->port;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (must_exist && !port) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("no port or interface named %s", target);
|
2009-12-10 14:07:33 -08:00
|
|
|
|
}
|
2010-02-22 16:36:30 -08:00
|
|
|
|
}
|
2009-12-10 14:07:33 -08:00
|
|
|
|
|
2010-02-22 16:36:30 -08:00
|
|
|
|
if (port) {
|
|
|
|
|
if (ctx->argc == 3) {
|
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2010-02-22 16:36:30 -08:00
|
|
|
|
if (port->bridge != bridge) {
|
|
|
|
|
if (port->bridge->parent == bridge) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("bridge %s does not have a port %s (although "
|
2018-05-01 19:07:36 -04:00
|
|
|
|
"its child bridge %s does)",
|
2010-02-22 16:36:30 -08:00
|
|
|
|
ctx->argv[1], ctx->argv[2],
|
2018-05-01 19:07:36 -04:00
|
|
|
|
port->bridge->name);
|
2010-02-22 16:36:30 -08:00
|
|
|
|
} else {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("bridge %s does not have a port %s",
|
2010-02-22 16:36:30 -08:00
|
|
|
|
ctx->argv[1], ctx->argv[2]);
|
|
|
|
|
}
|
2009-12-10 14:07:33 -08:00
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2010-02-22 16:36:30 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
del_port(vsctl_ctx, port);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_port_to_br(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_port *port;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
port = find_port(vsctl_ctx, ctx->argv[1], true);
|
2009-12-10 13:28:22 -08:00
|
|
|
|
ds_put_format(&ctx->output, "%s\n", port->bridge->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_br_to_vlan(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-10 13:28:22 -08:00
|
|
|
|
ds_put_format(&ctx->output, "%d\n", bridge->vlan);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_br_to_parent(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *bridge;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
bridge = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
if (bridge->parent) {
|
|
|
|
|
bridge = bridge->parent;
|
|
|
|
|
}
|
2009-12-10 13:28:22 -08:00
|
|
|
|
ds_put_format(&ctx->output, "%s\n", bridge->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_list_ifaces(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_bridge *br;
|
2012-04-17 16:56:21 -07:00
|
|
|
|
struct vsctl_port *port;
|
2009-12-09 13:28:48 -08:00
|
|
|
|
struct svec ifaces;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
|
|
|
|
verify_ports(vsctl_ctx);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
|
|
|
|
|
svec_init(&ifaces);
|
2012-04-17 16:56:21 -07:00
|
|
|
|
LIST_FOR_EACH (port, ports_node, &br->ports) {
|
|
|
|
|
struct vsctl_iface *iface;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2012-04-17 16:56:21 -07:00
|
|
|
|
LIST_FOR_EACH (iface, ifaces_node, &port->ifaces) {
|
|
|
|
|
if (strcmp(iface->iface_cfg->name, br->name)) {
|
|
|
|
|
svec_add(&ifaces, iface->iface_cfg->name);
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-12-10 13:28:22 -08:00
|
|
|
|
output_sorted(&ifaces, &ctx->output);
|
2009-12-09 13:28:48 -08:00
|
|
|
|
svec_destroy(&ifaces);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_iface_to_br(struct ctl_context *ctx)
|
2009-12-08 17:18:12 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
struct vsctl_iface *iface;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
iface = find_iface(vsctl_ctx, ctx->argv[1], true);
|
2009-12-10 13:28:22 -08:00
|
|
|
|
ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2009-12-09 17:04:08 -08:00
|
|
|
|
|
2010-10-22 14:46:30 -07:00
|
|
|
|
static void
|
|
|
|
|
verify_controllers(struct ovsrec_bridge *bridge)
|
|
|
|
|
{
|
2012-04-17 13:50:53 -07:00
|
|
|
|
size_t i;
|
2010-10-22 14:46:30 -07:00
|
|
|
|
|
2012-04-17 13:50:53 -07:00
|
|
|
|
ovsrec_bridge_verify_controller(bridge);
|
|
|
|
|
for (i = 0; i < bridge->n_controller; i++) {
|
|
|
|
|
ovsrec_controller_verify_target(bridge->controller[i]);
|
2010-10-22 14:46:30 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-08 14:24:59 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_controller(struct ctl_context *ctx)
|
2010-12-08 14:24:59 -08:00
|
|
|
|
{
|
|
|
|
|
pre_get_info(ctx);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_controller_col_target);
|
2018-03-12 19:23:44 +08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_controller_col_inactivity_probe);
|
2010-12-08 14:24:59 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 10:43:42 -07:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_get_controller(struct ctl_context *ctx)
|
2010-04-20 10:43:42 -07:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
struct vsctl_bridge *br;
|
2010-04-20 10:43:42 -07:00
|
|
|
|
struct svec targets;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2012-04-17 13:50:53 -07:00
|
|
|
|
if (br->parent) {
|
|
|
|
|
br = br->parent;
|
|
|
|
|
}
|
2010-10-22 14:46:30 -07:00
|
|
|
|
verify_controllers(br->br_cfg);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
|
|
|
|
|
/* Print the targets in sorted order for reproducibility. */
|
2010-04-20 10:43:42 -07:00
|
|
|
|
svec_init(&targets);
|
2012-04-17 13:56:38 -07:00
|
|
|
|
for (i = 0; i < br->br_cfg->n_controller; i++) {
|
|
|
|
|
svec_add(&targets, br->br_cfg->controller[i]->target);
|
2010-04-20 10:43:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
svec_sort(&targets);
|
|
|
|
|
for (i = 0; i < targets.n; i++) {
|
|
|
|
|
ds_put_format(&ctx->output, "%s\n", targets.names[i]);
|
|
|
|
|
}
|
|
|
|
|
svec_destroy(&targets);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-16 15:06:37 -07:00
|
|
|
|
static void
|
|
|
|
|
delete_controllers(struct ovsrec_controller **controllers,
|
|
|
|
|
size_t n_controllers)
|
|
|
|
|
{
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_controllers; i++) {
|
|
|
|
|
ovsrec_controller_delete(controllers[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-16 15:10:35 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_controller(struct ctl_context *ctx)
|
2009-12-16 15:10:35 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2012-04-17 13:56:38 -07:00
|
|
|
|
struct ovsrec_bridge *br;
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_real_bridge(vsctl_ctx, ctx->argv[1], true)->br_cfg;
|
2012-04-17 13:56:38 -07:00
|
|
|
|
verify_controllers(br);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 13:56:38 -07:00
|
|
|
|
if (br->controller) {
|
|
|
|
|
delete_controllers(br->controller, br->n_controller);
|
|
|
|
|
ovsrec_bridge_set_controller(br, NULL, 0);
|
2012-04-17 17:07:00 -07:00
|
|
|
|
}
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 10:43:42 -07:00
|
|
|
|
static struct ovsrec_controller **
|
2018-03-12 19:23:44 +08:00
|
|
|
|
insert_controllers(struct ctl_context *ctx, char *targets[], size_t n)
|
2010-04-20 10:43:42 -07:00
|
|
|
|
{
|
|
|
|
|
struct ovsrec_controller **controllers;
|
|
|
|
|
size_t i;
|
2018-03-12 19:23:44 +08:00
|
|
|
|
const char *inactivity_probe = shash_find_data(&ctx->options,
|
|
|
|
|
"--inactivity-probe");
|
2010-04-20 10:43:42 -07:00
|
|
|
|
|
|
|
|
|
controllers = xmalloc(n * sizeof *controllers);
|
|
|
|
|
for (i = 0; i < n; i++) {
|
2011-10-12 00:03:10 -07:00
|
|
|
|
if (vconn_verify_name(targets[i]) && pvconn_verify_name(targets[i])) {
|
|
|
|
|
VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
|
|
|
|
|
}
|
2018-03-12 19:23:44 +08:00
|
|
|
|
controllers[i] = ovsrec_controller_insert(ctx->txn);
|
2010-04-20 10:43:42 -07:00
|
|
|
|
ovsrec_controller_set_target(controllers[i], targets[i]);
|
2018-03-12 19:23:44 +08:00
|
|
|
|
if (inactivity_probe) {
|
|
|
|
|
int64_t msecs = atoll(inactivity_probe);
|
|
|
|
|
ovsrec_controller_set_inactivity_probe(controllers[i], &msecs, 1);
|
|
|
|
|
}
|
2010-04-20 10:43:42 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return controllers;
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-16 15:10:35 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_set_controller(struct ctl_context *ctx)
|
2009-12-16 15:10:35 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
struct ovsrec_controller **controllers;
|
2012-04-17 13:56:38 -07:00
|
|
|
|
struct ovsrec_bridge *br;
|
2010-07-15 14:53:36 -07:00
|
|
|
|
size_t n;
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_real_bridge(vsctl_ctx, ctx->argv[1], true)->br_cfg;
|
2012-04-17 13:56:38 -07:00
|
|
|
|
verify_controllers(br);
|
2011-03-16 15:06:37 -07:00
|
|
|
|
|
2012-04-17 13:56:38 -07:00
|
|
|
|
delete_controllers(br->controller, br->n_controller);
|
2010-04-20 10:43:42 -07:00
|
|
|
|
|
2010-07-15 14:53:36 -07:00
|
|
|
|
n = ctx->argc - 2;
|
2018-03-12 19:23:44 +08:00
|
|
|
|
controllers = insert_controllers(ctx, &ctx->argv[2], n);
|
2012-04-17 13:56:38 -07:00
|
|
|
|
ovsrec_bridge_set_controller(br, controllers, n);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
free(controllers);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_get_fail_mode(struct ctl_context *ctx)
|
2009-12-16 15:10:35 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
struct vsctl_bridge *br;
|
2012-04-19 14:27:40 -07:00
|
|
|
|
const char *fail_mode;
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-19 14:27:40 -07:00
|
|
|
|
if (br->parent) {
|
|
|
|
|
br = br->parent;
|
|
|
|
|
}
|
|
|
|
|
ovsrec_bridge_verify_fail_mode(br->br_cfg);
|
|
|
|
|
|
|
|
|
|
fail_mode = br->br_cfg->fail_mode;
|
|
|
|
|
if (fail_mode && strlen(fail_mode)) {
|
|
|
|
|
ds_put_format(&ctx->output, "%s\n", fail_mode);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_fail_mode(struct ctl_context *ctx)
|
2009-12-16 15:10:35 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
struct vsctl_bridge *br;
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_real_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
ovsrec_bridge_set_fail_mode(br->br_cfg, NULL);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_set_fail_mode(struct ctl_context *ctx)
|
2009-12-16 15:10:35 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2010-07-15 14:53:36 -07:00
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
const char *fail_mode = ctx->argv[2];
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
2012-04-17 17:07:00 -07:00
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_real_bridge(vsctl_ctx, ctx->argv[1], true);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
|
|
|
|
|
if (strcmp(fail_mode, "standalone") && strcmp(fail_mode, "secure")) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-15 20:56:43 -07:00
|
|
|
|
ovsrec_bridge_set_fail_mode(br->br_cfg, fail_mode);
|
2009-12-16 15:10:35 -08:00
|
|
|
|
}
|
2009-12-18 13:43:28 -08:00
|
|
|
|
|
2011-02-04 13:30:02 -08:00
|
|
|
|
static void
|
|
|
|
|
verify_managers(const struct ovsrec_open_vswitch *ovs)
|
|
|
|
|
{
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
ovsrec_open_vswitch_verify_manager_options(ovs);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ovs->n_manager_options; ++i) {
|
|
|
|
|
const struct ovsrec_manager *mgr = ovs->manager_options[i];
|
|
|
|
|
|
|
|
|
|
ovsrec_manager_verify_target(mgr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_manager(struct ctl_context *ctx)
|
2011-02-04 13:30:02 -08:00
|
|
|
|
{
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_manager_col_target);
|
2018-03-12 19:23:44 +08:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_manager_col_inactivity_probe);
|
2011-02-04 13:30:02 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_get_manager(struct ctl_context *ctx)
|
2011-02-04 13:30:02 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
const struct ovsrec_open_vswitch *ovs = vsctl_ctx->ovs;
|
2011-02-04 13:30:02 -08:00
|
|
|
|
struct svec targets;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
verify_managers(ovs);
|
|
|
|
|
|
|
|
|
|
/* Print the targets in sorted order for reproducibility. */
|
|
|
|
|
svec_init(&targets);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ovs->n_manager_options; i++) {
|
|
|
|
|
svec_add(&targets, ovs->manager_options[i]->target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
svec_sort_unique(&targets);
|
|
|
|
|
for (i = 0; i < targets.n; i++) {
|
|
|
|
|
ds_put_format(&ctx->output, "%s\n", targets.names[i]);
|
|
|
|
|
}
|
|
|
|
|
svec_destroy(&targets);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-06-10 15:31:51 -07:00
|
|
|
|
delete_managers(const struct ovsrec_open_vswitch *ovs)
|
2011-02-04 13:30:02 -08:00
|
|
|
|
{
|
2011-03-16 15:06:37 -07:00
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
/* Delete Manager rows pointed to by 'manager_options' column. */
|
|
|
|
|
for (i = 0; i < ovs->n_manager_options; i++) {
|
|
|
|
|
ovsrec_manager_delete(ovs->manager_options[i]);
|
|
|
|
|
}
|
2011-02-04 13:30:02 -08:00
|
|
|
|
|
2011-03-16 15:06:37 -07:00
|
|
|
|
/* Delete 'Manager' row refs in 'manager_options' column. */
|
2011-03-10 11:15:01 -08:00
|
|
|
|
ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
|
2011-02-04 13:30:02 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-03-16 15:06:37 -07:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_manager(struct ctl_context *ctx)
|
2011-03-16 15:06:37 -07:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
const struct ovsrec_open_vswitch *ovs = vsctl_ctx->ovs;
|
2011-03-16 15:06:37 -07:00
|
|
|
|
|
|
|
|
|
verify_managers(ovs);
|
2015-06-10 15:31:51 -07:00
|
|
|
|
delete_managers(ovs);
|
2011-03-16 15:06:37 -07:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-04 13:30:02 -08:00
|
|
|
|
static void
|
2018-03-12 19:23:44 +08:00
|
|
|
|
insert_managers(struct vsctl_context *vsctl_ctx, char *targets[], size_t n,
|
|
|
|
|
struct shash *options)
|
2011-02-04 13:30:02 -08:00
|
|
|
|
{
|
|
|
|
|
struct ovsrec_manager **managers;
|
|
|
|
|
size_t i;
|
2018-03-12 19:23:44 +08:00
|
|
|
|
const char *inactivity_probe = shash_find_data(options,
|
|
|
|
|
"--inactivity-probe");
|
2011-02-04 13:30:02 -08:00
|
|
|
|
|
|
|
|
|
/* Insert each manager in a new row in Manager table. */
|
|
|
|
|
managers = xmalloc(n * sizeof *managers);
|
|
|
|
|
for (i = 0; i < n; i++) {
|
2011-10-12 00:03:10 -07:00
|
|
|
|
if (stream_verify_name(targets[i]) && pstream_verify_name(targets[i])) {
|
|
|
|
|
VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
managers[i] = ovsrec_manager_insert(vsctl_ctx->base.txn);
|
2011-02-04 13:30:02 -08:00
|
|
|
|
ovsrec_manager_set_target(managers[i], targets[i]);
|
2018-03-12 19:23:44 +08:00
|
|
|
|
if (inactivity_probe) {
|
|
|
|
|
int64_t msecs = atoll(inactivity_probe);
|
|
|
|
|
ovsrec_manager_set_inactivity_probe(managers[i], &msecs, 1);
|
|
|
|
|
}
|
2011-02-04 13:30:02 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Store uuids of new Manager rows in 'manager_options' column. */
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_set_manager_options(vsctl_ctx->ovs, managers, n);
|
2011-02-04 13:30:02 -08:00
|
|
|
|
free(managers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_set_manager(struct ctl_context *ctx)
|
2011-02-04 13:30:02 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2011-02-04 13:30:02 -08:00
|
|
|
|
const size_t n = ctx->argc - 1;
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
verify_managers(vsctl_ctx->ovs);
|
|
|
|
|
delete_managers(vsctl_ctx->ovs);
|
2018-03-12 19:23:44 +08:00
|
|
|
|
insert_managers(vsctl_ctx, &ctx->argv[1], n, &ctx->options);
|
2011-02-04 13:30:02 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_cmd_get_ssl(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
|
|
|
|
|
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_private_key);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_certificate);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_ca_cert);
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_bootstrap_ca_cert);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-18 13:43:28 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_get_ssl(struct ctl_context *ctx)
|
2009-12-18 13:43:28 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
struct ovsrec_ssl *ssl = vsctl_ctx->ovs->ssl;
|
2009-12-18 13:43:28 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_verify_ssl(vsctl_ctx->ovs);
|
2009-12-18 13:43:28 -08:00
|
|
|
|
if (ssl) {
|
2010-10-22 14:46:30 -07:00
|
|
|
|
ovsrec_ssl_verify_private_key(ssl);
|
|
|
|
|
ovsrec_ssl_verify_certificate(ssl);
|
|
|
|
|
ovsrec_ssl_verify_ca_cert(ssl);
|
|
|
|
|
ovsrec_ssl_verify_bootstrap_ca_cert(ssl);
|
|
|
|
|
|
2009-12-18 13:43:28 -08:00
|
|
|
|
ds_put_format(&ctx->output, "Private key: %s\n", ssl->private_key);
|
|
|
|
|
ds_put_format(&ctx->output, "Certificate: %s\n", ssl->certificate);
|
|
|
|
|
ds_put_format(&ctx->output, "CA Certificate: %s\n", ssl->ca_cert);
|
|
|
|
|
ds_put_format(&ctx->output, "Bootstrap: %s\n",
|
|
|
|
|
ssl->bootstrap_ca_cert ? "true" : "false");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_cmd_del_ssl(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-18 13:43:28 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_ssl(struct ctl_context *ctx)
|
2009-12-18 13:43:28 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
|
|
|
|
struct ovsrec_ssl *ssl = vsctl_ctx->ovs->ssl;
|
2011-03-16 15:06:37 -07:00
|
|
|
|
|
|
|
|
|
if (ssl) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_verify_ssl(vsctl_ctx->ovs);
|
2011-03-16 15:06:37 -07:00
|
|
|
|
ovsrec_ssl_delete(ssl);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_set_ssl(vsctl_ctx->ovs, NULL);
|
2011-03-16 15:06:37 -07:00
|
|
|
|
}
|
2009-12-18 13:43:28 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_cmd_set_ssl(struct ctl_context *ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-18 13:43:28 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_set_ssl(struct ctl_context *ctx)
|
2009-12-18 13:43:28 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2009-12-18 13:43:28 -08:00
|
|
|
|
bool bootstrap = shash_find(&ctx->options, "--bootstrap");
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct ovsrec_ssl *ssl = vsctl_ctx->ovs->ssl;
|
2009-12-18 13:43:28 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_verify_ssl(vsctl_ctx->ovs);
|
2011-03-16 15:06:37 -07:00
|
|
|
|
if (ssl) {
|
|
|
|
|
ovsrec_ssl_delete(ssl);
|
|
|
|
|
}
|
2010-01-28 16:09:26 -08:00
|
|
|
|
ssl = ovsrec_ssl_insert(ctx->txn);
|
2009-12-18 13:43:28 -08:00
|
|
|
|
|
|
|
|
|
ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
|
|
|
|
|
ovsrec_ssl_set_certificate(ssl, ctx->argv[2]);
|
|
|
|
|
ovsrec_ssl_set_ca_cert(ssl, ctx->argv[3]);
|
|
|
|
|
|
|
|
|
|
ovsrec_ssl_set_bootstrap_ca_cert(ssl, bootstrap);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsrec_open_vswitch_set_ssl(vsctl_ctx->ovs, ssl);
|
2009-12-18 13:43:28 -08:00
|
|
|
|
}
|
2015-02-20 14:17:11 -05:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
autoattach_insert_mapping(struct ovsrec_autoattach *aa,
|
|
|
|
|
int64_t isid,
|
|
|
|
|
int64_t vlan)
|
|
|
|
|
{
|
|
|
|
|
int64_t *key_mappings, *value_mappings;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
key_mappings = xmalloc(sizeof *aa->key_mappings * (aa->n_mappings + 1));
|
|
|
|
|
value_mappings = xmalloc(sizeof *aa->value_mappings * (aa->n_mappings + 1));
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < aa->n_mappings; i++) {
|
|
|
|
|
key_mappings[i] = aa->key_mappings[i];
|
|
|
|
|
value_mappings[i] = aa->value_mappings[i];
|
|
|
|
|
}
|
|
|
|
|
key_mappings[aa->n_mappings] = isid;
|
|
|
|
|
value_mappings[aa->n_mappings] = vlan;
|
|
|
|
|
|
|
|
|
|
ovsrec_autoattach_set_mappings(aa, key_mappings, value_mappings,
|
|
|
|
|
aa->n_mappings + 1);
|
|
|
|
|
|
|
|
|
|
free(key_mappings);
|
|
|
|
|
free(value_mappings);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_add_aa_mapping(struct ctl_context *ctx)
|
2015-02-20 14:17:11 -05:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
int64_t isid, vlan;
|
|
|
|
|
char *nptr = NULL;
|
|
|
|
|
|
|
|
|
|
isid = strtoull(ctx->argv[2], &nptr, 10);
|
|
|
|
|
if (nptr == ctx->argv[2] || nptr == NULL) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("Invalid argument %s", ctx->argv[2]);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vlan = strtoull(ctx->argv[3], &nptr, 10);
|
|
|
|
|
if (nptr == ctx->argv[3] || nptr == NULL) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("Invalid argument %s", ctx->argv[3]);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
if (br->parent) {
|
|
|
|
|
br = br->parent;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 17:33:22 -07:00
|
|
|
|
if (br->br_cfg) {
|
2015-03-19 23:22:05 -07:00
|
|
|
|
if (!br->br_cfg->auto_attach) {
|
|
|
|
|
struct ovsrec_autoattach *aa = ovsrec_autoattach_insert(ctx->txn);
|
|
|
|
|
ovsrec_bridge_set_auto_attach(br->br_cfg, aa);
|
|
|
|
|
}
|
2015-02-20 14:17:11 -05:00
|
|
|
|
autoattach_insert_mapping(br->br_cfg->auto_attach, isid, vlan);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
del_aa_mapping(struct ovsrec_autoattach *aa,
|
|
|
|
|
int64_t isid,
|
|
|
|
|
int64_t vlan)
|
|
|
|
|
{
|
|
|
|
|
int64_t *key_mappings, *value_mappings;
|
|
|
|
|
size_t i, n;
|
|
|
|
|
|
|
|
|
|
key_mappings = xmalloc(sizeof *aa->key_mappings * (aa->n_mappings));
|
|
|
|
|
value_mappings = xmalloc(sizeof *value_mappings * (aa->n_mappings));
|
|
|
|
|
|
|
|
|
|
for (i = n = 0; i < aa->n_mappings; i++) {
|
|
|
|
|
if (aa->key_mappings[i] != isid && aa->value_mappings[i] != vlan) {
|
|
|
|
|
key_mappings[n] = aa->key_mappings[i];
|
|
|
|
|
value_mappings[n++] = aa->value_mappings[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ovsrec_autoattach_set_mappings(aa, key_mappings, value_mappings, n);
|
|
|
|
|
|
|
|
|
|
free(key_mappings);
|
|
|
|
|
free(value_mappings);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_del_aa_mapping(struct ctl_context *ctx)
|
2015-02-20 14:17:11 -05:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
int64_t isid, vlan;
|
|
|
|
|
char *nptr = NULL;
|
|
|
|
|
|
|
|
|
|
isid = strtoull(ctx->argv[2], &nptr, 10);
|
|
|
|
|
if (nptr == ctx->argv[2] || nptr == NULL) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("Invalid argument %s", ctx->argv[2]);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vlan = strtoull(ctx->argv[3], &nptr, 10);
|
|
|
|
|
if (nptr == ctx->argv[3] || nptr == NULL) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("Invalid argument %s", ctx->argv[3]);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
if (br->parent) {
|
|
|
|
|
br = br->parent;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 17:33:22 -07:00
|
|
|
|
if (br->br_cfg && br->br_cfg->auto_attach &&
|
2015-02-20 14:17:11 -05:00
|
|
|
|
br->br_cfg->auto_attach->key_mappings &&
|
|
|
|
|
br->br_cfg->auto_attach->value_mappings) {
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < br->br_cfg->auto_attach->n_mappings; i++) {
|
|
|
|
|
if (br->br_cfg->auto_attach->key_mappings[i] == isid &&
|
|
|
|
|
br->br_cfg->auto_attach->value_mappings[i] == vlan) {
|
|
|
|
|
del_aa_mapping(br->br_cfg->auto_attach, isid, vlan);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
pre_aa_mapping(struct ctl_context *ctx)
|
2015-02-20 14:17:11 -05:00
|
|
|
|
{
|
|
|
|
|
pre_get_info(ctx);
|
|
|
|
|
|
2015-03-19 23:39:30 -07:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_auto_attach);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
ovsdb_idl_add_column(ctx->idl, &ovsrec_autoattach_col_mappings);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
verify_auto_attach(struct ovsrec_bridge *bridge)
|
|
|
|
|
{
|
|
|
|
|
if (bridge) {
|
|
|
|
|
ovsrec_bridge_verify_auto_attach(bridge);
|
|
|
|
|
|
|
|
|
|
if (bridge->auto_attach) {
|
|
|
|
|
ovsrec_autoattach_verify_mappings(bridge->auto_attach);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
cmd_get_aa_mapping(struct ctl_context *ctx)
|
2015-02-20 14:17:11 -05:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
struct vsctl_bridge *br;
|
|
|
|
|
|
|
|
|
|
vsctl_context_populate_cache(ctx);
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
br = find_bridge(vsctl_ctx, ctx->argv[1], true);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
if (br->parent) {
|
|
|
|
|
br = br->parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
verify_auto_attach(br->br_cfg);
|
|
|
|
|
|
2015-07-13 17:33:22 -07:00
|
|
|
|
if (br->br_cfg && br->br_cfg->auto_attach &&
|
2015-02-20 14:17:11 -05:00
|
|
|
|
br->br_cfg->auto_attach->key_mappings &&
|
|
|
|
|
br->br_cfg->auto_attach->value_mappings) {
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < br->br_cfg->auto_attach->n_mappings; i++) {
|
|
|
|
|
ds_put_format(&ctx->output, "%"PRId64" %"PRId64"\n",
|
2015-02-22 15:59:59 -08:00
|
|
|
|
br->br_cfg->auto_attach->key_mappings[i],
|
|
|
|
|
br->br_cfg->auto_attach->value_mappings[i]);
|
2015-02-20 14:17:11 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
static const struct ctl_table_class tables[OVSREC_N_TABLES] = {
|
2017-04-27 15:47:59 -07:00
|
|
|
|
[OVSREC_TABLE_BRIDGE].row_ids[0] = {&ovsrec_bridge_col_name, NULL, NULL},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
[OVSREC_TABLE_CONTROLLER].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_controller},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-04-27 15:47:59 -07:00
|
|
|
|
[OVSREC_TABLE_INTERFACE].row_ids[0]
|
|
|
|
|
= {&ovsrec_interface_col_name, NULL, NULL},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-04-27 15:47:59 -07:00
|
|
|
|
[OVSREC_TABLE_MIRROR].row_ids[0] = {&ovsrec_mirror_col_name, NULL, NULL},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-04-27 15:47:59 -07:00
|
|
|
|
[OVSREC_TABLE_MANAGER].row_ids[0]
|
|
|
|
|
= {&ovsrec_manager_col_target, NULL, NULL},
|
2010-11-05 10:22:18 -07:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
[OVSREC_TABLE_NETFLOW].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_netflow},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-04-27 15:47:59 -07:00
|
|
|
|
[OVSREC_TABLE_PORT].row_ids[0] = {&ovsrec_port_col_name, NULL, NULL},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
[OVSREC_TABLE_QOS].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_port_col_name, NULL, &ovsrec_port_col_qos},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
[OVSREC_TABLE_SFLOW].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_sflow},
|
2010-06-17 15:04:12 -07:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
[OVSREC_TABLE_FLOW_TABLE].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_flow_table_col_name, NULL, NULL},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2017-04-27 13:54:53 -07:00
|
|
|
|
[OVSREC_TABLE_IPFIX].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_ipfix},
|
2017-01-04 14:29:21 -08:00
|
|
|
|
|
|
|
|
|
[OVSREC_TABLE_AUTOATTACH].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_auto_attach},
|
2015-02-20 14:17:11 -05:00
|
|
|
|
|
2017-01-04 14:29:21 -08:00
|
|
|
|
[OVSREC_TABLE_FLOW_SAMPLE_COLLECTOR_SET].row_ids[0]
|
2017-04-27 15:47:59 -07:00
|
|
|
|
= {&ovsrec_flow_sample_collector_set_col_id, NULL, NULL},
|
2010-01-25 10:13:52 -08:00
|
|
|
|
};
|
|
|
|
|
|
2010-01-27 11:25:20 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
post_db_reload_check_init(void)
|
2010-01-25 10:13:52 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
n_neoteric_ifaces = 0;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void
|
|
|
|
|
post_db_reload_expect_iface(const struct ovsrec_interface *iface)
|
2010-01-25 10:13:52 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (n_neoteric_ifaces >= allocated_neoteric_ifaces) {
|
|
|
|
|
neoteric_ifaces = x2nrealloc(neoteric_ifaces,
|
|
|
|
|
&allocated_neoteric_ifaces,
|
|
|
|
|
sizeof *neoteric_ifaces);
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
neoteric_ifaces[n_neoteric_ifaces++] = iface->header_.uuid;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void
|
|
|
|
|
post_db_reload_do_checks(const struct vsctl_context *vsctl_ctx)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
2016-12-20 17:50:06 -08:00
|
|
|
|
bool print_error = false;
|
2015-05-28 16:19:15 -07:00
|
|
|
|
size_t i;
|
2010-11-16 09:15:40 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
for (i = 0; i < n_neoteric_ifaces; i++) {
|
|
|
|
|
const struct uuid *uuid;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
uuid = ovsdb_idl_txn_get_insert_uuid(vsctl_ctx->base.txn,
|
|
|
|
|
&neoteric_ifaces[i]);
|
|
|
|
|
if (uuid) {
|
|
|
|
|
const struct ovsrec_interface *iface;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
iface = ovsrec_interface_get_for_uuid(vsctl_ctx->base.idl, uuid);
|
|
|
|
|
if (iface && (!iface->ofport || *iface->ofport == -1)) {
|
2016-12-20 17:50:06 -08:00
|
|
|
|
if (iface->error && *iface->error) {
|
|
|
|
|
ovs_error(0, "Error detected while setting up '%s': %s. "
|
|
|
|
|
"See ovs-vswitchd log for details.",
|
|
|
|
|
iface->name, iface->error);
|
|
|
|
|
} else {
|
|
|
|
|
ovs_error(0, "Error detected while setting up '%s'. "
|
|
|
|
|
"See ovs-vswitchd log for details.",
|
|
|
|
|
iface->name);
|
|
|
|
|
}
|
|
|
|
|
print_error = true;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-20 17:50:06 -08:00
|
|
|
|
if (print_error) {
|
|
|
|
|
ovs_error(0, "The default log directory is \"%s\".", ovs_logdir());
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
vsctl_context_init_command(struct vsctl_context *vsctl_ctx,
|
|
|
|
|
struct ctl_command *command)
|
2010-01-25 10:13:52 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_context_init_command(&vsctl_ctx->base, command);
|
|
|
|
|
vsctl_ctx->verified_ports = false;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void
|
|
|
|
|
vsctl_context_init(struct vsctl_context *vsctl_ctx,
|
|
|
|
|
struct ctl_command *command, struct ovsdb_idl *idl,
|
|
|
|
|
struct ovsdb_idl_txn *txn,
|
|
|
|
|
const struct ovsrec_open_vswitch *ovs,
|
|
|
|
|
struct ovsdb_symbol_table *symtab)
|
2010-01-25 10:13:52 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_context_init(&vsctl_ctx->base, command, idl, txn, symtab,
|
|
|
|
|
vsctl_context_invalidate_cache);
|
|
|
|
|
if (command) {
|
|
|
|
|
vsctl_ctx->verified_ports = false;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_ctx->ovs = ovs;
|
|
|
|
|
vsctl_ctx->cache_valid = false;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void
|
|
|
|
|
vsctl_context_done_command(struct vsctl_context *vsctl_ctx,
|
|
|
|
|
struct ctl_command *command)
|
2010-09-20 10:56:15 -07:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_context_done_command(&vsctl_ctx->base, command);
|
2010-09-20 10:56:15 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-16 09:15:40 -08:00
|
|
|
|
static void
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_done(struct vsctl_context *vsctl_ctx,
|
|
|
|
|
struct ctl_command *command)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_context_done(&vsctl_ctx->base, command);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static void
|
|
|
|
|
run_prerequisites(struct ctl_command *commands, size_t n_commands,
|
|
|
|
|
struct ovsdb_idl *idl)
|
2010-06-28 17:20:15 -07:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct ctl_command *c;
|
2010-06-28 17:20:15 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovsdb_idl_add_table(idl, &ovsrec_table_open_vswitch);
|
|
|
|
|
if (wait_for_reload) {
|
|
|
|
|
ovsdb_idl_add_column(idl, &ovsrec_open_vswitch_col_cur_cfg);
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
for (c = commands; c < &commands[n_commands]; c++) {
|
|
|
|
|
if (c->syntax->prerequisites) {
|
|
|
|
|
struct vsctl_context vsctl_ctx;
|
2010-01-25 10:13:52 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ds_init(&c->output);
|
|
|
|
|
c->table = NULL;
|
2010-06-28 17:20:15 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_init(&vsctl_ctx, c, idl, NULL, NULL, NULL);
|
|
|
|
|
(c->syntax->prerequisites)(&vsctl_ctx.base);
|
2018-07-02 12:50:10 +02:00
|
|
|
|
if (vsctl_ctx.base.error) {
|
|
|
|
|
ctl_fatal("%s", vsctl_ctx.base.error);
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_done(&vsctl_ctx, c);
|
2010-01-27 11:25:20 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs_assert(!c->output.string);
|
|
|
|
|
ovs_assert(!c->table);
|
2010-06-28 17:20:15 -07:00
|
|
|
|
}
|
2010-01-25 10:13:52 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-12 14:24:53 -08:00
|
|
|
|
static char *
|
|
|
|
|
vsctl_parent_process_info(void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef __linux__
|
|
|
|
|
pid_t parent_pid;
|
|
|
|
|
struct ds s;
|
|
|
|
|
|
|
|
|
|
parent_pid = getppid();
|
ovs-vsctl: Change log level of vsctl_parent_process_info
While running the ovn-scale-test [1] port-binding tests [2], I notice a
continual stream of messages such as this:
2016-08-04 13:05:28.705 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_cikzNO to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04 13:05:28.712 547 INFO paramiko.transport [-] Connected (version 2.0, client OpenSSH_6.6.1p1)
2016-08-04 13:05:28.805 547 INFO paramiko.transport [-] Authentication (publickey) successful!
2016-08-04T13:05:28Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.042 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_tvovcK to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.285 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_HwG7AK to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.505 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_Lqbv92 to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.724 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_6f8uQW to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.944 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_nKl2XF to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
Tracing these down, this is due to the check in vsctl_parent_process_info(),
which is verifying if the parent process can be opened. Since ovn-scale-test
runs sandboxes in containers, and these are run as root, there is no /proc/0
in the container. Thus, the check fails, and the error message is printed out.
It's unclear what value this log message provides, so removing it clears up
this problem and is probably the best option.
For the init process with pid of zero, this patch returns "init",
instead of trying to read from /proc/0/cmdline, which does not exist.
[1] https://github.com/openvswitch/ovn-scale-test
[2] https://github.com/openvswitch/ovn-scale-test/blob/master/rally_ovs/plugins/ovs/scenarios/ovn.py#L255
Signed-off-by: Kyle Mestery <mestery@mestery.com>
Acked-by: Andy Zhou <azhou@ovn.org>
2016-08-08 06:48:40 -07:00
|
|
|
|
ds_init(&s);
|
|
|
|
|
|
|
|
|
|
/* Retrive the command line of the parent process, except the init
|
|
|
|
|
* process since /proc/0 does not exist. */
|
|
|
|
|
if (parent_pid) {
|
|
|
|
|
char *procfile;
|
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
|
|
procfile = xasprintf("/proc/%d/cmdline", parent_pid);
|
2016-01-12 14:24:53 -08:00
|
|
|
|
|
ovs-vsctl: Change log level of vsctl_parent_process_info
While running the ovn-scale-test [1] port-binding tests [2], I notice a
continual stream of messages such as this:
2016-08-04 13:05:28.705 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_cikzNO to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04 13:05:28.712 547 INFO paramiko.transport [-] Connected (version 2.0, client OpenSSH_6.6.1p1)
2016-08-04 13:05:28.805 547 INFO paramiko.transport [-] Authentication (publickey) successful!
2016-08-04T13:05:28Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.042 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_tvovcK to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.285 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_HwG7AK to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.505 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_Lqbv92 to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.724 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_6f8uQW to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.944 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_nKl2XF to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
Tracing these down, this is due to the check in vsctl_parent_process_info(),
which is verifying if the parent process can be opened. Since ovn-scale-test
runs sandboxes in containers, and these are run as root, there is no /proc/0
in the container. Thus, the check fails, and the error message is printed out.
It's unclear what value this log message provides, so removing it clears up
this problem and is probably the best option.
For the init process with pid of zero, this patch returns "init",
instead of trying to read from /proc/0/cmdline, which does not exist.
[1] https://github.com/openvswitch/ovn-scale-test
[2] https://github.com/openvswitch/ovn-scale-test/blob/master/rally_ovs/plugins/ovs/scenarios/ovn.py#L255
Signed-off-by: Kyle Mestery <mestery@mestery.com>
Acked-by: Andy Zhou <azhou@ovn.org>
2016-08-08 06:48:40 -07:00
|
|
|
|
f = fopen(procfile, "r");
|
2016-01-12 14:24:53 -08:00
|
|
|
|
free(procfile);
|
2016-08-04 11:12:49 -07:00
|
|
|
|
if (f) {
|
|
|
|
|
ds_get_line(&s, f);
|
|
|
|
|
fclose(f);
|
2016-01-12 14:24:53 -08:00
|
|
|
|
}
|
ovs-vsctl: Change log level of vsctl_parent_process_info
While running the ovn-scale-test [1] port-binding tests [2], I notice a
continual stream of messages such as this:
2016-08-04 13:05:28.705 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_cikzNO to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04 13:05:28.712 547 INFO paramiko.transport [-] Connected (version 2.0, client OpenSSH_6.6.1p1)
2016-08-04 13:05:28.805 547 INFO paramiko.transport [-] Authentication (publickey) successful!
2016-08-04T13:05:28Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.042 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_tvovcK to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.285 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_HwG7AK to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.505 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_Lqbv92 to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.724 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_6f8uQW to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04T13:05:29Z|00002|vsctl|WARN|/proc/0/cmdline: open failed (No such file or directory)
2016-08-04 13:05:29.944 547 INFO rally_ovs.plugins.ovs.scenarios.ovn [-] bind lport_0996bf_nKl2XF to sandbox-172.16.200.24 on ovn-farm-node-uat-dal09-compute-325
Tracing these down, this is due to the check in vsctl_parent_process_info(),
which is verifying if the parent process can be opened. Since ovn-scale-test
runs sandboxes in containers, and these are run as root, there is no /proc/0
in the container. Thus, the check fails, and the error message is printed out.
It's unclear what value this log message provides, so removing it clears up
this problem and is probably the best option.
For the init process with pid of zero, this patch returns "init",
instead of trying to read from /proc/0/cmdline, which does not exist.
[1] https://github.com/openvswitch/ovn-scale-test
[2] https://github.com/openvswitch/ovn-scale-test/blob/master/rally_ovs/plugins/ovs/scenarios/ovn.py#L255
Signed-off-by: Kyle Mestery <mestery@mestery.com>
Acked-by: Andy Zhou <azhou@ovn.org>
2016-08-08 06:48:40 -07:00
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(&s, "init");
|
2016-01-12 14:24:53 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_format(&s, " (pid %d)", parent_pid);
|
|
|
|
|
return ds_steal_cstr(&s);
|
|
|
|
|
#else
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-25 15:39:47 -08:00
|
|
|
|
static bool
|
2015-05-28 16:19:15 -07:00
|
|
|
|
do_vsctl(const char *args, struct ctl_command *commands, size_t n_commands,
|
|
|
|
|
struct ovsdb_idl *idl)
|
2010-11-16 09:15:40 -08:00
|
|
|
|
{
|
2015-05-28 16:19:15 -07:00
|
|
|
|
struct ovsdb_idl_txn *txn;
|
|
|
|
|
const struct ovsrec_open_vswitch *ovs;
|
|
|
|
|
enum ovsdb_idl_txn_status status;
|
|
|
|
|
struct ovsdb_symbol_table *symtab;
|
|
|
|
|
struct vsctl_context vsctl_ctx;
|
|
|
|
|
struct ctl_command *c;
|
|
|
|
|
struct shash_node *node;
|
|
|
|
|
int64_t next_cfg = 0;
|
|
|
|
|
char *error = NULL;
|
2016-01-12 14:24:53 -08:00
|
|
|
|
char *ppid_info = NULL;
|
2010-11-16 09:15:40 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
txn = the_idl_txn = ovsdb_idl_txn_create(idl);
|
|
|
|
|
if (dry_run) {
|
|
|
|
|
ovsdb_idl_txn_set_dry_run(txn);
|
2010-11-16 09:15:40 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-12 14:24:53 -08:00
|
|
|
|
ppid_info = vsctl_parent_process_info();
|
|
|
|
|
if (ppid_info) {
|
|
|
|
|
ovsdb_idl_txn_add_comment(txn, "ovs-vsctl (invoked by %s): %s",
|
|
|
|
|
ppid_info, args);
|
|
|
|
|
free(ppid_info);
|
|
|
|
|
} else {
|
|
|
|
|
ovsdb_idl_txn_add_comment(txn, "ovs-vsctl: %s", args);
|
|
|
|
|
}
|
2012-09-05 10:35:20 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ovs = ovsrec_open_vswitch_first(idl);
|
|
|
|
|
if (!ovs) {
|
|
|
|
|
/* XXX add verification that table is empty */
|
|
|
|
|
ovs = ovsrec_open_vswitch_insert(txn);
|
2012-09-05 10:35:20 -07:00
|
|
|
|
}
|
2010-11-16 09:15:40 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (wait_for_reload) {
|
|
|
|
|
ovsdb_idl_txn_increment(txn, &ovs->header_,
|
2016-08-07 20:44:51 -07:00
|
|
|
|
&ovsrec_open_vswitch_col_next_cfg, false);
|
2009-12-16 16:26:17 -08:00
|
|
|
|
}
|
|
|
|
|
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
post_db_reload_check_init();
|
2010-06-02 11:08:03 -07:00
|
|
|
|
symtab = ovsdb_symbol_table_create();
|
2010-06-24 11:01:53 -07:00
|
|
|
|
for (c = commands; c < &commands[n_commands]; c++) {
|
|
|
|
|
ds_init(&c->output);
|
2011-02-08 16:10:34 -08:00
|
|
|
|
c->table = NULL;
|
2010-06-24 11:01:53 -07:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_init(&vsctl_ctx, NULL, idl, txn, ovs, symtab);
|
2010-01-28 16:09:26 -08:00
|
|
|
|
for (c = commands; c < &commands[n_commands]; c++) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_init_command(&vsctl_ctx, c);
|
2011-06-06 11:40:10 -07:00
|
|
|
|
if (c->syntax->run) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
(c->syntax->run)(&vsctl_ctx.base);
|
2011-06-06 11:40:10 -07:00
|
|
|
|
}
|
2018-07-02 12:50:10 +02:00
|
|
|
|
if (vsctl_ctx.base.error) {
|
|
|
|
|
ctl_fatal("%s", vsctl_ctx.base.error);
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_done_command(&vsctl_ctx, c);
|
2010-06-24 11:01:53 -07:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
if (vsctl_ctx.base.try_again) {
|
|
|
|
|
vsctl_context_done(&vsctl_ctx, NULL);
|
2010-06-24 11:01:53 -07:00
|
|
|
|
goto try_again;
|
|
|
|
|
}
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_done(&vsctl_ctx, NULL);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2011-03-01 13:11:56 -08:00
|
|
|
|
SHASH_FOR_EACH (node, &symtab->sh) {
|
|
|
|
|
struct ovsdb_symbol *symbol = node->data;
|
|
|
|
|
if (!symbol->created) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
|
2011-03-01 13:11:56 -08:00
|
|
|
|
"with \"-- --id=%s create ...\")",
|
|
|
|
|
node->name, node->name);
|
|
|
|
|
}
|
2011-03-10 11:15:01 -08:00
|
|
|
|
if (!symbol->strong_ref) {
|
|
|
|
|
if (!symbol->weak_ref) {
|
|
|
|
|
VLOG_WARN("row id \"%s\" was created but no reference to it "
|
|
|
|
|
"was inserted, so it will not actually appear in "
|
|
|
|
|
"the database", node->name);
|
|
|
|
|
} else {
|
|
|
|
|
VLOG_WARN("row id \"%s\" was created but only a weak "
|
|
|
|
|
"reference to it was inserted, so it will not "
|
|
|
|
|
"actually appear in the database", node->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-28 12:45:16 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-03 12:55:39 -08:00
|
|
|
|
status = ovsdb_idl_txn_commit_block(txn);
|
2009-12-16 16:26:17 -08:00
|
|
|
|
if (wait_for_reload && status == TXN_SUCCESS) {
|
|
|
|
|
next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
|
|
|
|
|
}
|
2010-05-18 14:16:43 -07:00
|
|
|
|
if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
|
|
|
|
|
for (c = commands; c < &commands[n_commands]; c++) {
|
|
|
|
|
if (c->syntax->postprocess) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_init(&vsctl_ctx, c, idl, txn, ovs, symtab);
|
|
|
|
|
(c->syntax->postprocess)(&vsctl_ctx.base);
|
2018-07-02 12:50:10 +02:00
|
|
|
|
if (vsctl_ctx.base.error) {
|
|
|
|
|
ctl_fatal("%s", vsctl_ctx.base.error);
|
|
|
|
|
}
|
2015-05-28 16:19:15 -07:00
|
|
|
|
vsctl_context_done(&vsctl_ctx, c);
|
2010-05-18 14:16:43 -07:00
|
|
|
|
}
|
2010-01-28 13:33:24 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-05 14:11:12 -08:00
|
|
|
|
error = xstrdup(ovsdb_idl_txn_get_error(txn));
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
switch (status) {
|
2011-06-20 16:17:44 -07:00
|
|
|
|
case TXN_UNCOMMITTED:
|
2009-12-08 17:18:12 -08:00
|
|
|
|
case TXN_INCOMPLETE:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
case TXN_ABORTED:
|
|
|
|
|
/* Should not happen--we never call ovsdb_idl_txn_abort(). */
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("transaction aborted");
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2009-12-16 16:26:17 -08:00
|
|
|
|
case TXN_UNCHANGED:
|
2009-12-08 17:18:12 -08:00
|
|
|
|
case TXN_SUCCESS:
|
|
|
|
|
break;
|
|
|
|
|
|
2012-03-27 10:16:52 -07:00
|
|
|
|
case TXN_TRY_AGAIN:
|
2010-06-24 11:01:53 -07:00
|
|
|
|
goto try_again;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
|
|
|
|
case TXN_ERROR:
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("transaction error: %s", error);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2011-07-26 16:49:03 -07:00
|
|
|
|
case TXN_NOT_LOCKED:
|
|
|
|
|
/* Should not happen--we never call ovsdb_idl_set_lock(). */
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_fatal("database not locked");
|
2011-07-26 16:49:03 -07:00
|
|
|
|
|
2009-12-08 17:18:12 -08:00
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2010-02-05 14:11:12 -08:00
|
|
|
|
free(error);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
|
2010-06-24 11:01:53 -07:00
|
|
|
|
ovsdb_symbol_table_destroy(symtab);
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
for (c = commands; c < &commands[n_commands]; c++) {
|
|
|
|
|
struct ds *ds = &c->output;
|
2010-06-02 11:08:03 -07:00
|
|
|
|
|
2011-02-08 16:10:34 -08:00
|
|
|
|
if (c->table) {
|
|
|
|
|
table_print(c->table, &table_style);
|
|
|
|
|
} else if (oneline) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
|
|
ds_chomp(ds, '\n');
|
|
|
|
|
for (j = 0; j < ds->length; j++) {
|
2010-09-02 10:09:09 -07:00
|
|
|
|
int ch = ds->string[j];
|
|
|
|
|
switch (ch) {
|
2009-12-08 17:18:12 -08:00
|
|
|
|
case '\n':
|
|
|
|
|
fputs("\\n", stdout);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '\\':
|
|
|
|
|
fputs("\\\\", stdout);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2010-09-02 10:09:09 -07:00
|
|
|
|
putchar(ch);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
putchar('\n');
|
|
|
|
|
} else {
|
|
|
|
|
fputs(ds_cstr(ds), stdout);
|
|
|
|
|
}
|
2010-02-02 14:27:22 -08:00
|
|
|
|
ds_destroy(&c->output);
|
2011-02-08 16:10:34 -08:00
|
|
|
|
table_destroy(c->table);
|
|
|
|
|
free(c->table);
|
2010-06-02 11:08:03 -07:00
|
|
|
|
|
2012-05-22 03:47:36 -07:00
|
|
|
|
shash_destroy_free_data(&c->options);
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
2010-02-02 14:27:22 -08:00
|
|
|
|
free(commands);
|
2009-12-16 16:26:17 -08:00
|
|
|
|
|
|
|
|
|
if (wait_for_reload && status != TXN_UNCHANGED) {
|
2014-02-18 13:19:36 -08:00
|
|
|
|
/* Even, if --retry flag was not specified, ovs-vsctl still
|
|
|
|
|
* has to retry to establish OVSDB connection, if wait_for_reload
|
|
|
|
|
* was set. Otherwise, ovs-vsctl would end up waiting forever
|
|
|
|
|
* until cur_cfg would be updated. */
|
|
|
|
|
ovsdb_idl_enable_reconnect(idl);
|
2009-12-16 16:26:17 -08:00
|
|
|
|
for (;;) {
|
|
|
|
|
ovsdb_idl_run(idl);
|
|
|
|
|
OVSREC_OPEN_VSWITCH_FOR_EACH (ovs, idl) {
|
|
|
|
|
if (ovs->cur_cfg >= next_cfg) {
|
2015-05-28 16:19:15 -07:00
|
|
|
|
post_db_reload_do_checks(&vsctl_ctx);
|
2009-12-16 16:26:17 -08:00
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ovsdb_idl_wait(idl);
|
|
|
|
|
poll_block();
|
|
|
|
|
}
|
|
|
|
|
done: ;
|
|
|
|
|
}
|
ovs-vsctl: Improve error reporting
ovs-vsctl is a command-line interface to the Open vSwitch database,
and as such it just modifies the desired Open vSwitch configuration in
the database. ovs-vswitchd, on the other hand, monitors the database
and implements the actual configuration specified in the database.
This can lead to surprises when the user makes a change to the
database, with ovs-vsctl, that ovs-vswitchd cannot actually
implement. In such a case, the ovs-vsctl command silently succeeds
(because the database was successfully updated) but its desired
effects don't actually take place. One good example of such a change
is attempting to add a port with a misspelled name (e.g. ``ovs-vsctl
add-port br0 fth0'', where fth0 should be eth0); another is creating
a bridge or a port whose name is longer than supported
(e.g. ``ovs-vsctl add-br'' with a 16-character bridge name on
Linux). It can take users a long time to realize the error, because it
requires looking through the ovs-vswitchd log.
The patch improves the situation by checking whether operations that
ovs executes succeed and report an error when
they do not. This patch only report add-br and add-port
operation errors by examining the `ofport' value that
ovs-vswitchd stores into the database record for the newly created
interface. Until ovs-vswitchd finishes implementing the new
configuration, this column is empty, and after it finishes it is
either -1 (on failure) or a positive number (on success).
Signed-off-by: Andy Zhou <azhou@nicira.com>
Co-authored-by: Thomas Graf <tgraf@redhat.com>
Signed-off-by: Thomas Graf <tgraf@redhat.com>
Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2014-03-27 17:10:31 +01:00
|
|
|
|
ovsdb_idl_txn_destroy(txn);
|
2010-02-02 14:27:22 -08:00
|
|
|
|
ovsdb_idl_destroy(idl);
|
2009-12-16 16:26:17 -08:00
|
|
|
|
|
2018-01-25 15:39:47 -08:00
|
|
|
|
return true;
|
2010-06-24 11:01:53 -07:00
|
|
|
|
|
|
|
|
|
try_again:
|
|
|
|
|
/* Our transaction needs to be rerun, or a prerequisite was not met. Free
|
|
|
|
|
* resources and return so that the caller can try again. */
|
2017-05-26 20:44:19 -07:00
|
|
|
|
ovsdb_idl_txn_abort(txn);
|
|
|
|
|
ovsdb_idl_txn_destroy(txn);
|
|
|
|
|
the_idl_txn = NULL;
|
|
|
|
|
|
2010-06-24 11:01:53 -07:00
|
|
|
|
ovsdb_symbol_table_destroy(symtab);
|
|
|
|
|
for (c = commands; c < &commands[n_commands]; c++) {
|
|
|
|
|
ds_destroy(&c->output);
|
2011-02-08 16:10:34 -08:00
|
|
|
|
table_destroy(c->table);
|
|
|
|
|
free(c->table);
|
2010-06-24 11:01:53 -07:00
|
|
|
|
}
|
|
|
|
|
free(error);
|
2018-01-25 15:39:47 -08:00
|
|
|
|
return false;
|
2009-12-08 17:18:12 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-13 23:24:11 -07:00
|
|
|
|
/* Frees the current transaction and the underlying IDL and then calls
|
|
|
|
|
* exit(status).
|
|
|
|
|
*
|
|
|
|
|
* Freeing the transaction and the IDL is not strictly necessary, but it makes
|
|
|
|
|
* for a clean memory leak report from valgrind in the normal case. That makes
|
|
|
|
|
* it easier to notice real memory leaks. */
|
|
|
|
|
static void
|
|
|
|
|
vsctl_exit(int status)
|
|
|
|
|
{
|
|
|
|
|
if (the_idl_txn) {
|
|
|
|
|
ovsdb_idl_txn_abort(the_idl_txn);
|
|
|
|
|
ovsdb_idl_txn_destroy(the_idl_txn);
|
|
|
|
|
}
|
|
|
|
|
ovsdb_idl_destroy(the_idl);
|
|
|
|
|
exit(status);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-04 09:52:12 -08:00
|
|
|
|
/*
|
2015-05-28 16:19:15 -07:00
|
|
|
|
* Developers who add new commands to the 'struct ctl_command_syntax' must
|
2015-02-04 09:52:12 -08:00
|
|
|
|
* define the 'arguments' member of the struct. The following keywords are
|
|
|
|
|
* available for composing the argument format:
|
|
|
|
|
*
|
|
|
|
|
* TABLE RECORD BRIDGE PARENT PORT
|
|
|
|
|
* KEY VALUE ARG KEY=VALUE ?KEY=VALUE
|
|
|
|
|
* IFACE SYSIFACE COLUMN COLUMN?:KEY COLUMN?:KEY=VALUE
|
|
|
|
|
* MODE CA-CERT CERTIFICATE PRIVATE-KEY
|
|
|
|
|
* TARGET NEW-* (e.g. NEW-PORT)
|
|
|
|
|
*
|
|
|
|
|
* For argument types not listed above, just uses 'ARG' as place holder.
|
|
|
|
|
*
|
|
|
|
|
* Encloses the keyword with '[]' if it is optional. Appends '...' to
|
|
|
|
|
* keyword or enclosed keyword to indicate that the argument can be specified
|
|
|
|
|
* multiple times.
|
|
|
|
|
*
|
|
|
|
|
* */
|
2015-05-28 16:19:15 -07:00
|
|
|
|
static const struct ctl_command_syntax vsctl_commands[] = {
|
2010-01-28 16:09:26 -08:00
|
|
|
|
/* Open vSwitch commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"init", 0, 0, "", NULL, cmd_init, NULL, "", RW},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
|
|
|
|
/* Bridge commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"add-br", 1, 3, "NEW-BRIDGE [PARENT] [NEW-VLAN]", pre_get_info,
|
|
|
|
|
cmd_add_br, NULL, "--may-exist", RW},
|
|
|
|
|
{"del-br", 1, 1, "BRIDGE", pre_get_info, cmd_del_br,
|
|
|
|
|
NULL, "--if-exists", RW},
|
|
|
|
|
{"list-br", 0, 0, "", pre_get_info, cmd_list_br, NULL, "--real,--fake",
|
|
|
|
|
RO},
|
|
|
|
|
{"br-exists", 1, 1, "BRIDGE", pre_get_info, cmd_br_exists, NULL, "", RO},
|
|
|
|
|
{"br-to-vlan", 1, 1, "BRIDGE", pre_get_info, cmd_br_to_vlan, NULL, "",
|
|
|
|
|
RO},
|
|
|
|
|
{"br-to-parent", 1, 1, "BRIDGE", pre_get_info, cmd_br_to_parent, NULL,
|
|
|
|
|
"", RO},
|
|
|
|
|
{"br-set-external-id", 2, 3, "BRIDGE KEY [VALUE]",
|
|
|
|
|
pre_cmd_br_set_external_id, cmd_br_set_external_id, NULL, "", RW},
|
|
|
|
|
{"br-get-external-id", 1, 2, "BRIDGE [KEY]", pre_cmd_br_get_external_id,
|
2010-11-16 09:15:40 -08:00
|
|
|
|
cmd_br_get_external_id, NULL, "", RO},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
|
|
|
|
/* Port commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"list-ports", 1, 1, "BRIDGE", pre_get_info, cmd_list_ports, NULL, "",
|
|
|
|
|
RO},
|
|
|
|
|
{"add-port", 2, INT_MAX, "BRIDGE NEW-PORT [COLUMN[:KEY]=VALUE]...",
|
|
|
|
|
pre_get_info, cmd_add_port, NULL, "--may-exist", RW},
|
|
|
|
|
{"del-port", 1, 2, "[BRIDGE] PORT|IFACE", pre_get_info, cmd_del_port, NULL,
|
2010-11-16 09:15:40 -08:00
|
|
|
|
"--if-exists,--with-iface", RW},
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"port-to-br", 1, 1, "PORT", pre_get_info, cmd_port_to_br, NULL, "", RO},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
2018-02-02 13:49:37 -08:00
|
|
|
|
/* Bond commands. */
|
|
|
|
|
{"add-bond", 4, INT_MAX,
|
|
|
|
|
"BRIDGE BOND IFACE... [COLUMN[:KEY]=VALUE]...", pre_get_info,
|
|
|
|
|
cmd_add_bond, NULL, "--may-exist,--fake-iface", RW},
|
|
|
|
|
{"add-bond-iface", 2, 2, "BOND IFACE", pre_get_info, cmd_add_bond_iface,
|
|
|
|
|
NULL, "--may-exist", RW},
|
|
|
|
|
{"del-bond-iface", 1, 2, "[BOND] IFACE", pre_get_info, cmd_del_bond_iface,
|
|
|
|
|
NULL, "--if-exists", RW},
|
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
/* Interface commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"list-ifaces", 1, 1, "BRIDGE", pre_get_info, cmd_list_ifaces, NULL, "",
|
|
|
|
|
RO},
|
|
|
|
|
{"iface-to-br", 1, 1, "IFACE", pre_get_info, cmd_iface_to_br, NULL, "",
|
|
|
|
|
RO},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
|
|
|
|
/* Controller commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"get-controller", 1, 1, "BRIDGE", pre_controller, cmd_get_controller,
|
|
|
|
|
NULL, "", RO},
|
|
|
|
|
{"del-controller", 1, 1, "BRIDGE", pre_controller, cmd_del_controller,
|
|
|
|
|
NULL, "", RW},
|
|
|
|
|
{"set-controller", 1, INT_MAX, "BRIDGE TARGET...", pre_controller,
|
2018-03-12 19:23:44 +08:00
|
|
|
|
cmd_set_controller, NULL, "--inactivity-probe=", RW},
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"get-fail-mode", 1, 1, "BRIDGE", pre_get_info, cmd_get_fail_mode, NULL,
|
|
|
|
|
"", RO},
|
|
|
|
|
{"del-fail-mode", 1, 1, "BRIDGE", pre_get_info, cmd_del_fail_mode, NULL,
|
2010-12-08 14:24:59 -08:00
|
|
|
|
"", RW},
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"set-fail-mode", 2, 2, "BRIDGE MODE", pre_get_info, cmd_set_fail_mode,
|
|
|
|
|
NULL, "", RW},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
2011-02-04 13:30:02 -08:00
|
|
|
|
/* Manager commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"get-manager", 0, 0, "", pre_manager, cmd_get_manager, NULL, "", RO},
|
|
|
|
|
{"del-manager", 0, 0, "", pre_manager, cmd_del_manager, NULL, "", RW},
|
|
|
|
|
{"set-manager", 1, INT_MAX, "TARGET...", pre_manager, cmd_set_manager,
|
2018-03-12 19:23:44 +08:00
|
|
|
|
NULL, "--inactivity-probe=", RW},
|
2011-02-04 13:30:02 -08:00
|
|
|
|
|
2010-01-28 16:09:26 -08:00
|
|
|
|
/* SSL commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"get-ssl", 0, 0, "", pre_cmd_get_ssl, cmd_get_ssl, NULL, "", RO},
|
|
|
|
|
{"del-ssl", 0, 0, "", pre_cmd_del_ssl, cmd_del_ssl, NULL, "", RW},
|
|
|
|
|
{"set-ssl", 3, 3, "PRIVATE-KEY CERTIFICATE CA-CERT", pre_cmd_set_ssl,
|
|
|
|
|
cmd_set_ssl, NULL, "--bootstrap", RW},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
|
2015-02-20 14:17:11 -05:00
|
|
|
|
/* Auto Attach commands. */
|
2015-03-19 23:39:30 -07:00
|
|
|
|
{"add-aa-mapping", 3, 3, "BRIDGE ARG ARG", pre_aa_mapping, cmd_add_aa_mapping,
|
2015-02-04 09:52:12 -08:00
|
|
|
|
NULL, "", RW},
|
|
|
|
|
{"del-aa-mapping", 3, 3, "BRIDGE ARG ARG", pre_aa_mapping, cmd_del_aa_mapping,
|
|
|
|
|
NULL, "", RW},
|
|
|
|
|
{"get-aa-mapping", 1, 1, "BRIDGE", pre_aa_mapping, cmd_get_aa_mapping,
|
|
|
|
|
NULL, "", RO},
|
2015-02-20 14:17:11 -05:00
|
|
|
|
|
2010-04-30 15:06:51 -07:00
|
|
|
|
/* Switch commands. */
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{"emer-reset", 0, 0, "", pre_cmd_emer_reset, cmd_emer_reset, NULL, "", RW},
|
2010-04-30 15:06:51 -07:00
|
|
|
|
|
2015-02-04 09:52:12 -08:00
|
|
|
|
{NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
|
2010-01-28 16:09:26 -08:00
|
|
|
|
};
|
2009-12-10 13:28:22 -08:00
|
|
|
|
|
2015-05-28 16:19:15 -07:00
|
|
|
|
/* Registers vsctl and common db commands. */
|
|
|
|
|
static void
|
|
|
|
|
vsctl_cmd_init(void)
|
2013-07-19 10:04:47 -07:00
|
|
|
|
{
|
2018-02-26 14:04:02 -06:00
|
|
|
|
ctl_init(&ovsrec_idl_class, ovsrec_table_classes, tables, cmd_show_tables,
|
|
|
|
|
vsctl_exit);
|
2015-05-28 16:19:15 -07:00
|
|
|
|
ctl_register_commands(vsctl_commands);
|
2013-07-19 10:04:47 -07:00
|
|
|
|
}
|