summaryrefslogtreecommitdiff
path: root/ovn/utilities/ovn-nbctl.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2016-07-24 13:14:59 -0700
committerBen Pfaff <blp@ovn.org>2016-07-26 23:59:53 -0700
commitfa183acc654f7e5da17cd70fc91d6b5b02782183 (patch)
tree9dc2236c8f5cd5e66e74914a56b091befa069d0f /ovn/utilities/ovn-nbctl.c
parent763f638b7f34953ccae8b494c63d0dab7f326b41 (diff)
downloadopenvswitch-fa183acc654f7e5da17cd70fc91d6b5b02782183.tar.gz
ovn: Make it possible for CMS to detect when the OVN system is up-to-date.
Until now, there has been no reliable for the CMS (or ovn-nbctl, or anything else) to detect when changes made to the northbound configuration have been passed through to the southbound database or to the hypervisors. This commit adds this feature to the system, by adding sequence numbers to the northbound and southbound databases and adding code in ovn-nbctl, ovn-northd, and ovn-controller to keep those sequence numbers up-to-date. The biggest user-visible change from this commit is new a new option --wait to ovn-nbctl. With --wait=sb, ovn-nbctl now waits for ovn-northd to update the southbound database; with --wait=hv, it waits for the changes to make their way to Open vSwitch on every hypervisor. Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Russell Bryant <russell@ovn.org>
Diffstat (limited to 'ovn/utilities/ovn-nbctl.c')
-rw-r--r--ovn/utilities/ovn-nbctl.c86
1 files changed, 84 insertions, 2 deletions
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index d34a92ced..e594a3238 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -49,6 +49,14 @@ static bool oneline;
/* --dry-run: Do not commit any changes. */
static bool dry_run;
+/* --wait=TYPE: Wait for configuration change to take effect? */
+enum nbctl_wait_type {
+ NBCTL_WAIT_NONE, /* Do not wait. */
+ NBCTL_WAIT_SB, /* Wait for southbound database updates. */
+ NBCTL_WAIT_HV /* Wait for hypervisors to catch up. */
+};
+static enum nbctl_wait_type wait_type = NBCTL_WAIT_NONE;
+
/* --timeout: Time to wait for a connection to 'db'. */
static int timeout;
@@ -160,6 +168,8 @@ parse_options(int argc, char *argv[], struct shash *local_options)
enum {
OPT_DB = UCHAR_MAX + 1,
OPT_NO_SYSLOG,
+ OPT_NO_WAIT,
+ OPT_WAIT,
OPT_DRY_RUN,
OPT_ONELINE,
OPT_LOCAL,
@@ -171,6 +181,8 @@ parse_options(int argc, char *argv[], struct shash *local_options)
static const struct option global_long_options[] = {
{"db", required_argument, NULL, OPT_DB},
{"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
+ {"no-wait", no_argument, NULL, OPT_NO_WAIT},
+ {"wait", required_argument, NULL, OPT_WAIT},
{"dry-run", no_argument, NULL, OPT_DRY_RUN},
{"oneline", no_argument, NULL, OPT_ONELINE},
{"timeout", required_argument, NULL, 't'},
@@ -227,6 +239,23 @@ parse_options(int argc, char *argv[], struct shash *local_options)
vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
break;
+ case OPT_NO_WAIT:
+ wait_type = NBCTL_WAIT_NONE;
+ break;
+
+ case OPT_WAIT:
+ if (!strcmp(optarg, "none")) {
+ wait_type = NBCTL_WAIT_NONE;
+ } else if (!strcmp(optarg, "sb")) {
+ wait_type = NBCTL_WAIT_SB;
+ } else if (!strcmp(optarg, "hv")) {
+ wait_type = NBCTL_WAIT_HV;
+ } else {
+ ctl_fatal("argument to --wait must be "
+ "\"none\", \"sb\", or \"hv\"");
+ }
+ break;
+
case OPT_DRY_RUN:
dry_run = true;
break;
@@ -294,6 +323,7 @@ usage(void)
usage: %s [OPTIONS] COMMAND [ARG...]\n\
\n\
General commands:\n\
+ init initialize the database\n\
show print overview of database contents\n\
show SWITCH print overview of database contents for SWITCH\n\
show ROUTER print overview of database contents for ROUTER\n\
@@ -381,6 +411,9 @@ DHCP Options commands:\n\
Options:\n\
--db=DATABASE connect to DATABASE\n\
(default: %s)\n\
+ --no-wait, --wait=none do not wait for OVN reconfiguration (default)\n\
+ --wait=sb wait for southbound database update\n\
+ --wait=hv wait for all chassis to catch up\n\
-t, --timeout=SECS wait at most SECS seconds\n\
--dry-run do not commit changes to database\n\
--oneline print exactly one line of output per command\n",
@@ -521,6 +554,11 @@ print_ls(const struct nbrec_logical_switch *ls, struct ds *s)
}
static void
+nbctl_init(struct ctl_context *ctx OVS_UNUSED)
+{
+}
+
+static void
nbctl_show(struct ctl_context *ctx)
{
const struct nbrec_logical_switch *ls;
@@ -2064,6 +2102,10 @@ nbctl_lr_route_list(struct ctl_context *ctx)
}
static const struct ctl_table_class tables[] = {
+ {&nbrec_table_nb_global,
+ {{&nbrec_table_nb_global, NULL, NULL},
+ {NULL, NULL, NULL}}},
+
{&nbrec_table_logical_switch,
{{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL},
{NULL, NULL, NULL}}},
@@ -2116,9 +2158,14 @@ static void
run_prerequisites(struct ctl_command *commands, size_t n_commands,
struct ovsdb_idl *idl)
{
- struct ctl_command *c;
+ ovsdb_idl_add_table(idl, &nbrec_table_nb_global);
+ if (wait_type == NBCTL_WAIT_SB) {
+ ovsdb_idl_add_column(idl, &nbrec_nb_global_col_sb_cfg);
+ } else if (wait_type == NBCTL_WAIT_HV) {
+ ovsdb_idl_add_column(idl, &nbrec_nb_global_col_hv_cfg);
+ }
- for (c = commands; c < &commands[n_commands]; c++) {
+ for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) {
if (c->syntax->prerequisites) {
struct ctl_context ctx;
@@ -2145,6 +2192,7 @@ do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
struct ctl_context ctx;
struct ctl_command *c;
struct shash_node *node;
+ int64_t next_cfg = 0;
char *error = NULL;
txn = the_idl_txn = ovsdb_idl_txn_create(idl);
@@ -2154,6 +2202,17 @@ do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args);
+ const struct nbrec_nb_global *nb = nbrec_nb_global_first(idl);
+ if (!nb) {
+ /* XXX add verification that table is empty */
+ nb = nbrec_nb_global_insert(txn);
+ }
+
+ if (wait_type != NBCTL_WAIT_NONE) {
+ ovsdb_idl_txn_increment(txn, &nb->header_,
+ &nbrec_nb_global_col_nb_cfg);
+ }
+
symtab = ovsdb_symbol_table_create();
for (c = commands; c < &commands[n_commands]; c++) {
ds_init(&c->output);
@@ -2195,6 +2254,9 @@ do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
}
status = ovsdb_idl_txn_commit_block(txn);
+ if (wait_type != NBCTL_WAIT_NONE && status == TXN_SUCCESS) {
+ next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
+ }
if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
for (c = commands; c < &commands[n_commands]; c++) {
if (c->syntax->postprocess) {
@@ -2271,6 +2333,25 @@ do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
shash_destroy_free_data(&c->options);
}
free(commands);
+
+ if (wait_type != NBCTL_WAIT_NONE && status != TXN_UNCHANGED) {
+ ovsdb_idl_enable_reconnect(idl);
+ for (;;) {
+ ovsdb_idl_run(idl);
+ NBREC_NB_GLOBAL_FOR_EACH (nb, idl) {
+ int64_t cur_cfg = (wait_type == NBCTL_WAIT_SB
+ ? nb->sb_cfg
+ : nb->hv_cfg);
+ if (cur_cfg >= next_cfg) {
+ goto done;
+ }
+ }
+ ovsdb_idl_wait(idl);
+ poll_block();
+ }
+ done: ;
+ }
+
ovsdb_idl_txn_destroy(txn);
ovsdb_idl_destroy(idl);
@@ -2312,6 +2393,7 @@ nbctl_exit(int status)
}
static const struct ctl_command_syntax nbctl_commands[] = {
+ { "init", 0, 0, "", NULL, nbctl_init, NULL, "", RW },
{ "show", 0, 1, "[SWITCH]", NULL, nbctl_show, NULL, "", RO },
/* logical switch commands. */