ovsdb-server: Add commands for adding and removing remotes at runtime.
authorBen Pfaff <blp@nicira.com>
Wed, 10 Apr 2013 16:34:49 +0000 (09:34 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 11 Apr 2013 01:15:01 +0000 (18:15 -0700)
This will make it possible, in later commits, to make ovsdb-server connect
to OVS managers only after ovs-vswitchd has completed its initial
configuration.

Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Ansis Atteka <aatteka@nicira.com>
ovsdb/ovsdb-server.1.in
ovsdb/ovsdb-server.c
tests/ovsdb-server.at

index 9d42471..82dd9c6 100644 (file)
@@ -1,4 +1,9 @@
 .\" -*- nroff -*-
+.de IQ
+.  br
+.  ns
+.  IP "\\$1"
+..
 .TH ovsdb\-server 1 "@VERSION@" "Open vSwitch" "Open vSwitch Manual"
 .\" This program's name:
 .ds PN ovsdb\-server
@@ -124,6 +129,29 @@ connections to database clients and reconnect.
 This command might be useful for debugging issues with database
 clients.
 .
+.IP "\fBovsdb\-server/add\-remote \fIremote\fR"
+Adds a remote, as if \fB\-\-remote=\fIremote\fR had been specified on
+the \fBovsdb\-server\fR command line.  (If \fIremote\fR is already a
+remote, this command succeeds without changing the configuration.)
+.
+.IP "\fBovsdb\-server/remove\-remote \fIremote\fR"
+Removes the specified \fIremote\fR from the configuration, failing
+with an error if \fIremote\fR is not configured as a remote.  This
+command only works with remotes that were named on \fB\-\-remote\fR or
+\fBovsdb\-server/add\-remote\fR, that is, it will not remove remotes
+added indirectly because they were read from the database by
+configuring a \fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR remote.
+(You can remove a database source with \fBovsdb\-server/remove\-remote
+\fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR, but not individual
+remotes found indirectly through the database.)
+.
+.IP "\fBovsdb\-server/list\-remotes"
+Outputs a list of the currently configured remotes named on
+\fB\-\-remote\fR or \fBovsdb\-server/add\-remote\fR, that is, it does
+not list remotes added indirectly because they were read from the
+database by configuring a
+\fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR remote.
+.
 .so lib/vlog-unixctl.man
 .so lib/memory-unixctl.man
 .so lib/coverage-unixctl.man
index 40fc36c..61095e2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -76,6 +76,15 @@ static unixctl_cb_func ovsdb_server_exit;
 static unixctl_cb_func ovsdb_server_compact;
 static unixctl_cb_func ovsdb_server_reconnect;
 
+struct add_remote_aux {
+    struct sset *remotes;
+    struct db *dbs;
+    size_t n_dbs;
+};
+static unixctl_cb_func ovsdb_server_add_remote;
+static unixctl_cb_func ovsdb_server_remove_remote;
+static unixctl_cb_func ovsdb_server_list_remotes;
+
 static void parse_options(int *argc, char **argvp[],
                           struct sset *remotes, char **unixctl_pathp,
                           char **run_command);
@@ -101,6 +110,7 @@ main(int argc, char *argv[])
     bool exiting;
     int retval;
     long long int status_timer = LLONG_MIN;
+    struct add_remote_aux add_remote_aux;
 
     struct db *dbs;
     int n_dbs;
@@ -181,6 +191,16 @@ main(int argc, char *argv[])
     unixctl_command_register("ovsdb-server/reconnect", "", 0, 0,
                              ovsdb_server_reconnect, jsonrpc);
 
+    add_remote_aux.remotes = &remotes;
+    add_remote_aux.dbs = dbs;
+    add_remote_aux.n_dbs = n_dbs;
+    unixctl_command_register("ovsdb-server/add-remote", "REMOTE", 1, 1,
+                             ovsdb_server_add_remote, &add_remote_aux);
+    unixctl_command_register("ovsdb-server/remove-remote", "REMOTE", 1, 1,
+                             ovsdb_server_remove_remote, &remotes);
+    unixctl_command_register("ovsdb-server/list-remotes", "", 0, 0,
+                             ovsdb_server_list_remotes, &remotes);
+
     exiting = false;
     while (!exiting) {
         int i;
@@ -198,9 +218,13 @@ main(int argc, char *argv[])
             simap_destroy(&usage);
         }
 
+        /* Run unixctl_server_run() before reconfigure_from_db() because
+         * ovsdb-server/add-remote and ovsdb-server/remove-remote can change
+         * the set of remotes that reconfigure_from_db() uses. */
+        unixctl_server_run(unixctl);
+
         reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes);
         ovsdb_jsonrpc_server_run(jsonrpc);
-        unixctl_server_run(unixctl);
 
         for (i = 0; i < n_dbs; i++) {
             ovsdb_trigger_run(dbs[i].db, time_msec());
@@ -871,6 +895,72 @@ ovsdb_server_reconnect(struct unixctl_conn *conn, int argc OVS_UNUSED,
     unixctl_command_reply(conn, NULL);
 }
 
+/* "ovsdb-server/add-remote REMOTE": adds REMOTE to the set of remotes that
+ * ovsdb-server services. */
+static void
+ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                        const char *argv[], void *aux_)
+{
+    struct add_remote_aux *aux = aux_;
+    const char *remote = argv[1];
+
+    const struct ovsdb_column *column;
+    const struct ovsdb_table *table;
+    const struct db *db;
+    char *retval;
+
+    retval = (strncmp("db:", remote, 3)
+              ? NULL
+              : parse_db_column(aux->dbs, aux->n_dbs, remote,
+                                &db, &table, &column));
+    if (!retval) {
+        sset_add(aux->remotes, remote);
+        unixctl_command_reply(conn, NULL);
+    } else {
+        unixctl_command_reply_error(conn, retval);
+        free(retval);
+    }
+}
+
+/* "ovsdb-server/remove-remote REMOTE": removes REMOTE frmo the set of remotes
+ * that ovsdb-server services. */
+static void
+ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                           const char *argv[], void *remotes_)
+{
+    struct sset *remotes = remotes_;
+    struct sset_node *node;
+
+    node = sset_find(remotes, argv[1]);
+    if (node) {
+        sset_delete(remotes, node);
+        unixctl_command_reply(conn, NULL);
+    } else {
+        unixctl_command_reply_error(conn, "no such remote");
+    }
+}
+
+/* "ovsdb-server/list-remotes": outputs a list of configured rmeotes. */
+static void
+ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                          const char *argv[] OVS_UNUSED, void *remotes_)
+{
+    struct sset *remotes = remotes_;
+    const char **list, **p;
+    struct ds s;
+
+    ds_init(&s);
+
+    list = sset_sort(remotes);
+    for (p = list; *p; p++) {
+        ds_put_format(&s, "%s\n", *p);
+    }
+    free(list);
+
+    unixctl_command_reply(conn, ds_cstr(&s));
+    ds_destroy(&s);
+}
+
 static void
 parse_options(int *argcp, char **argvp[],
               struct sset *remotes, char **unixctl_pathp, char **run_command)
index 62eae38..50f95bd 100644 (file)
@@ -229,6 +229,48 @@ AT_CHECK(
   [ignore])
 AT_CLEANUP
 
+AT_SETUP([ovsdb-server/add-remote and remove-remote])
+AT_KEYWORDS([ovsdb server positive])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile db])
+
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket1])
+OVS_WAIT_UNTIL([test -S socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+  [0], [punix:socket1
+])
+
+AT_CHECK([test ! -e socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote punix:socket2])
+OVS_WAIT_UNTIL([test -S socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+  [0], [punix:socket1
+punix:socket2
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote db:x,y,z], [2],
+  [], ["db:x,y,z": no database named x
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-remote punix:socket1])
+OVS_WAIT_UNTIL([test ! -e socket1])
+AT_CHECK([test -S socket2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+  [0], [punix:socket2
+])
+
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-remote punix:socket2])
+OVS_WAIT_UNTIL([test ! -e socket2])
+AT_CHECK([test ! -e socket1])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes])
+AT_CLEANUP
+
 AT_SETUP([SSL db: implementation])
 AT_KEYWORDS([ovsdb server positive ssl $5])
 AT_SKIP_IF([test "$HAVE_OPENSSL" = no])