[ovs-dev] [PATCH 2/2] ovsdb-server: Add and remove databases during run time.
Gurucharan Shetty
shettyg at nicira.com
Thu Jun 20 14:38:48 UTC 2013
The commit allows a user to add a database file to a
ovsdb-server during run time. One can also remove a
database file from ovsdb-server's control.
Feature #14595.
Signed-off-by: Gurucharan Shetty <gshetty at nicira.com>
---
ovsdb/jsonrpc-server.c | 10 ++
ovsdb/jsonrpc-server.h | 2 +
ovsdb/ovsdb-server.1.in | 18 +++
ovsdb/ovsdb-server.c | 348 +++++++++++++++++++++++++++++++++++++++--------
ovsdb/ovsdb.c | 3 +
ovsdb/server.c | 9 ++
ovsdb/server.h | 1 +
tests/ovsdb-server.at | 136 ++++++++++++++++++
8 files changed, 470 insertions(+), 57 deletions(-)
diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
index 9f99d64..0745ae6 100644
--- a/ovsdb/jsonrpc-server.c
+++ b/ovsdb/jsonrpc-server.c
@@ -132,6 +132,16 @@ ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *svr, struct ovsdb *db)
return ovsdb_server_add_db(&svr->up, db);
}
+/* Removes 'db' from the set of databases served out by 'svr'. Returns
+ * 'db' if successful, NULL if there is no database associated with 'db'. */
+void *
+ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *svr,
+ struct ovsdb *db)
+{
+ return ovsdb_server_remove_db(&svr->up, db);
+}
+
+
void
ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *svr)
{
diff --git a/ovsdb/jsonrpc-server.h b/ovsdb/jsonrpc-server.h
index f2395fc..707aa18 100644
--- a/ovsdb/jsonrpc-server.h
+++ b/ovsdb/jsonrpc-server.h
@@ -26,6 +26,8 @@ struct simap;
struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(void);
bool ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *,
struct ovsdb *);
+void *ovsdb_jsonrpc_server_remove_db(struct ovsdb_jsonrpc_server *,
+ struct ovsdb *);
void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *);
/* Options for a remote. */
diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in
index 82dd9c6..2e62ec9 100644
--- a/ovsdb/ovsdb-server.1.in
+++ b/ovsdb/ovsdb-server.1.in
@@ -152,6 +152,24 @@ 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.
.
+.IP "\fBovsdb\-server/add\-db \fIdatabase\fR"
+Adds the \fIdatabase\fR to the running \fBovsdb\-server\fR. The database
+file must already have been created and initialized using, for example,
+\fBovsdb\-tool create\fR.
+.
+.IP "\fBovsdb\-server/remove\-db \fIdatabase\fR"
+Removes the specified \fIdatabase\fR from the running \fBovsdb\-server\fR.
+If a \fIremote\fR has been configured such that it points to the specified
+\fIdatabase\fR, then it is automatically removed. Any public key
+infrastructure options specified through this database is no longer checked
+for new changes, but the linked files are still used. (Adding the
+\fIdatabase\fR back will recheck for the public key infrastructure options
+specified through it.)
+.
+.IP "\fBovsdb\-server/list\-dbs"
+Outputs a list of the currently configured databases added either through
+the command line or through the \fBovsdb\-server/add\-db\fR command.
+.
.so lib/vlog-unixctl.man
.so lib/memory-unixctl.man
.so lib/coverage-unixctl.man
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index ea8fe0f..a9c910b 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -73,26 +73,28 @@ static char *private_key_file;
static char *certificate_file;
static char *ca_cert_file;
static bool bootstrap_ca_cert;
+static bool ssl_reconfigure = true;
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 load_config_aux {
struct sset *remotes;
+ struct sset *dbnames;
struct shash *all_dbs;
FILE *config_tmpfile;
+ struct ovsdb_jsonrpc_server *jsonrpc;
};
static unixctl_cb_func ovsdb_server_add_remote;
-
-struct remove_remote_aux {
- struct sset *remotes;
- FILE *config_tmpfile;
-};
static unixctl_cb_func ovsdb_server_remove_remote;
static unixctl_cb_func ovsdb_server_list_remotes;
-static void open_db(const struct ovsdb_jsonrpc_server *jsonrpc,
+static unixctl_cb_func ovsdb_server_add_database;
+static unixctl_cb_func ovsdb_server_remove_database;
+static unixctl_cb_func ovsdb_server_list_databases;
+
+static void open_db(struct ovsdb_jsonrpc_server *jsonrpc,
struct db *db, struct shash *all_dbs);
static void parse_options(int *argc, char **argvp[],
@@ -108,8 +110,8 @@ static void update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc,
const struct sset *remotes,
struct shash *all_dbs);
-static void save_config(FILE *config_file, const struct sset *);
-static void load_config(FILE *config_file, struct sset *);
+static void save_config(FILE *config_file, const struct load_config_aux *);
+static void load_config(FILE *config_file, struct load_config_aux *);
int
main(int argc, char *argv[])
@@ -118,15 +120,14 @@ main(int argc, char *argv[])
char *run_command = NULL;
struct unixctl_server *unixctl;
struct ovsdb_jsonrpc_server *jsonrpc;
- struct sset remotes;
+ struct sset remotes, dbnames;
+ const char *dbname;
struct process *run_process;
bool exiting;
int retval;
long long int status_timer = LLONG_MIN;
- struct add_remote_aux add_remote_aux;
- struct remove_remote_aux remove_remote_aux;
FILE *config_tmpfile;
-
+ struct load_config_aux load_config_aux;
struct db *db;
struct shash all_dbs;
struct shash_node *node;
@@ -149,25 +150,36 @@ main(int argc, char *argv[])
if (!config_tmpfile) {
ovs_fatal(errno, "failed to create temporary file");
}
- save_config(config_tmpfile, &remotes);
+
+ sset_init(&dbnames);
+ if (argc > 0) {
+ for (i = 0; i < argc; i++) {
+ sset_add(&dbnames, argv[i]);
+ }
+ } else {
+ char *default_db = xasprintf("%s/conf.db", ovs_dbdir());
+ sset_add(&dbnames, default_db);
+ free(default_db);
+ }
+
+ load_config_aux.remotes = &remotes;
+ load_config_aux.dbnames = &dbnames;
+ load_config_aux.config_tmpfile = config_tmpfile;
+
+ save_config(config_tmpfile, &load_config_aux);
daemonize_start();
/* Load the saved config. */
- load_config(config_tmpfile, &remotes);
-
- shash_init(&all_dbs);
+ load_config(config_tmpfile, &load_config_aux);
jsonrpc = ovsdb_jsonrpc_server_create();
- if (argc > 0) {
- for (i = 0; i < argc; i++) {
- db = xzalloc(sizeof *db);
- db->filename = argv[i];
- open_db(jsonrpc, db, &all_dbs);
- }
- } else {
+ shash_init(&all_dbs);
+ load_config_aux.all_dbs = &all_dbs;
+ load_config_aux.jsonrpc = jsonrpc;
+ SSET_FOR_EACH(dbname, &dbnames) {
db = xzalloc(sizeof *db);
- db->filename = xasprintf("%s/conf.db", ovs_dbdir());
+ db->filename = strdup(dbname);
open_db(jsonrpc, db, &all_dbs);
}
@@ -209,20 +221,20 @@ 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.all_dbs = &all_dbs;
- add_remote_aux.config_tmpfile = config_tmpfile;
unixctl_command_register("ovsdb-server/add-remote", "REMOTE", 1, 1,
- ovsdb_server_add_remote, &add_remote_aux);
-
- remove_remote_aux.remotes = &remotes;
- remove_remote_aux.config_tmpfile = config_tmpfile;
+ ovsdb_server_add_remote, &load_config_aux);
unixctl_command_register("ovsdb-server/remove-remote", "REMOTE", 1, 1,
- ovsdb_server_remove_remote, &remove_remote_aux);
-
+ ovsdb_server_remove_remote, &load_config_aux);
unixctl_command_register("ovsdb-server/list-remotes", "", 0, 0,
ovsdb_server_list_remotes, &remotes);
+ unixctl_command_register("ovsdb-server/add-db", "DB", 1, 1,
+ ovsdb_server_add_database, &load_config_aux);
+ unixctl_command_register("ovsdb-server/remove-db", "DB", 1, 1,
+ ovsdb_server_remove_database, &load_config_aux);
+ unixctl_command_register("ovsdb-server/list-dbs", "", 0, 0,
+ ovsdb_server_list_databases, &all_dbs);
+
exiting = false;
while (!exiting) {
memory_run();
@@ -300,7 +312,7 @@ main(int argc, char *argv[])
}
static void
-open_db(const struct ovsdb_jsonrpc_server *jsonrpc, struct db *db,
+open_db(struct ovsdb_jsonrpc_server *jsonrpc, struct db *db,
struct shash *all_dbs)
{
struct ovsdb_error *error;
@@ -887,6 +899,9 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc,
shash_destroy_free_data(&resolved_remotes);
/* Configure SSL. */
+ if (!ssl_reconfigure) {
+ return;
+ }
stream_ssl_set_key_and_cert(query_db_string(all_dbs, private_key_file),
query_db_string(all_dbs, certificate_file));
stream_ssl_set_ca_cert_file(query_db_string(all_dbs, ca_cert_file),
@@ -967,7 +982,7 @@ 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_;
+ struct load_config_aux *aux = aux_;
const char *remote = argv[1];
const struct ovsdb_column *column;
@@ -981,7 +996,7 @@ ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
&db, &table, &column));
if (!retval) {
if (sset_add(aux->remotes, remote)) {
- save_config(aux->config_tmpfile, aux->remotes);
+ save_config(aux->config_tmpfile, aux);
}
unixctl_command_reply(conn, NULL);
} else {
@@ -996,13 +1011,13 @@ static void
ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,
const char *argv[], void *aux_)
{
- struct remove_remote_aux *aux = aux_;
+ struct load_config_aux *aux = aux_;
struct sset_node *node;
node = sset_find(aux->remotes, argv[1]);
if (node) {
sset_delete(aux->remotes, node);
- save_config(aux->config_tmpfile, aux->remotes);
+ save_config(aux->config_tmpfile, aux);
unixctl_command_reply(conn, NULL);
} else {
unixctl_command_reply_error(conn, "no such remote");
@@ -1030,6 +1045,204 @@ ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED,
ds_destroy(&s);
}
+static bool
+ssl_path_valid(struct shash *all_dbs, const char *config)
+{
+ const struct ovsdb_column *column;
+ const struct ovsdb_table *table;
+ char *retval;
+ const struct db *db;
+
+ if (!config) {
+ return false;
+ }
+
+ retval = (strncmp("db:", config, 3)
+ ? NULL
+ : parse_db_column(all_dbs, config,
+ &db, &table, &column));
+ if (retval) {
+ free(retval);
+ return false;
+ }
+ return true;
+}
+
+/* "ovsdb-server/add-db DB": adds the DB to ovsdb-server. */
+static void
+ovsdb_server_add_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *aux_)
+{
+ struct load_config_aux *aux = aux_;
+ const char *filename = argv[1];
+ struct db *db;
+ struct ovsdb_error *error;
+ char *err;
+
+ if (shash_count(aux->all_dbs)) {
+ /* If there are any DB paths specified without a schema,
+ * we cannot add a new database. */
+ struct sset db_paths;
+ const char *db_path;
+ const char *remote;
+
+ sset_init(&db_paths);
+
+ SSET_FOR_EACH(remote, aux->remotes) {
+ sset_add(&db_paths, remote);
+ }
+ if (private_key_file) {
+ sset_add(&db_paths, private_key_file);
+ }
+ if (certificate_file) {
+ sset_add(&db_paths, certificate_file);
+ }
+ if (ca_cert_file) {
+ sset_add(&db_paths, ca_cert_file);
+ }
+
+ SSET_FOR_EACH(db_path, &db_paths) {
+ if (!strncmp(db_path, "db:", 3)) {
+ const char *tokens[3];
+ char *save_ptr = NULL;
+ char *db_path_ = strdup(db_path);
+ strtok_r(db_path_, ":", &save_ptr); /* "db:" */
+ tokens[0] = strtok_r(NULL, ",", &save_ptr);
+ tokens[1] = strtok_r(NULL, ",", &save_ptr);
+ tokens[2] = strtok_r(NULL, ",", &save_ptr);
+ if (!tokens[0] || !tokens[1] || !tokens[2]) {
+ err = xasprintf("Failed to add the database as"
+ " there exists a %s with invalid"
+ " db path.", db_path);
+ unixctl_command_reply_error(conn, err);
+ free(err);
+ sset_destroy(&db_paths);
+ free(db_path_);
+ return;
+ }
+ free(db_path_);
+ }
+ }
+ sset_destroy(&db_paths);
+ }
+
+ db = xzalloc(sizeof *db);
+ db->filename = strdup(filename);
+
+ error = ovsdb_file_open(db->filename, false,
+ &db->db, &db->file);
+ if (error) {
+ VLOG_ERR("%s", ovsdb_error_to_string(error));
+ free(db->filename);
+ free(db);
+ free(error);
+ unixctl_command_reply_error(conn, "Failed to open the database file.");
+ return;
+ }
+
+ if (!ovsdb_jsonrpc_server_add_db(aux->jsonrpc, db->db)) {
+ VLOG_ERR("%s: duplicate database name", db->db->schema->name);
+ ovsdb_destroy(db->db);
+ free(db->filename);
+ free(db);
+ unixctl_command_reply_error(conn, "Failed to open the database file.");
+ return;
+ }
+
+ shash_add_once(aux->all_dbs, db->filename, db);
+ sset_add(aux->dbnames, filename);
+ save_config(aux->config_tmpfile, aux);
+
+ /* Unflag SSL paths if it becomes valid with this db. */
+ if (!ssl_reconfigure && ssl_path_valid(aux->all_dbs, private_key_file) && \
+ ssl_path_valid(aux->all_dbs, certificate_file) && \
+ ssl_path_valid(aux->all_dbs, ca_cert_file)) {
+ ssl_reconfigure = true;
+ }
+
+ unixctl_command_reply(conn, NULL);
+}
+
+static void
+ovsdb_server_remove_database(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[], void *aux_)
+{
+ struct load_config_aux *aux = aux_;
+ struct shash *all_dbs = aux->all_dbs;
+ struct sset *remotes = aux->remotes;
+ struct db *db;
+ const struct db *dbp;
+ struct shash_node *node;
+ const char *remote, *next;
+ const struct ovsdb_column *column;
+ const struct ovsdb_table *table;
+ char *retval;
+
+ node = shash_find(all_dbs, argv[1]);
+ if (node) {
+ if (!ovsdb_jsonrpc_server_remove_db(aux->jsonrpc,
+ ((struct db *)node->data)->db)) {
+ unixctl_command_reply_error(conn,
+ "Database not in jsonrpc server.");
+ return;
+ }
+
+ /* Remove any remotes associated with the database. */
+ SSET_FOR_EACH_SAFE(remote, next, remotes) {
+ if (!strncmp("db:", remote, 3)) {
+ retval = parse_db_column(all_dbs, remote, &dbp, &table,
+ &column);
+ if (!retval && !strcmp(dbp->filename, argv[1])) {
+ sset_find_and_delete(remotes, remote);
+ } else if (retval) {
+ free(retval);
+ }
+ }
+ }
+
+ db = node->data;
+ ovsdb_destroy(db->db);
+ shash_delete(all_dbs, node);
+ free(db->filename);
+ free(db);
+
+ /* Flag any SSL paths provided by this database. */
+ if (ssl_reconfigure) {
+ if (!ssl_path_valid(all_dbs, private_key_file) || \
+ !ssl_path_valid(all_dbs, certificate_file) || \
+ !ssl_path_valid(all_dbs, ca_cert_file)) {
+ ssl_reconfigure = false;
+ VLOG_ERR("SSL paths no longer valid.");
+ }
+ }
+ } else {
+ unixctl_command_reply_error(conn, "Failed to find the database.");
+ return;
+ }
+
+ sset_find_and_delete(aux->dbnames, argv[1]);
+ save_config(aux->config_tmpfile, aux);
+ unixctl_command_reply(conn, NULL);
+}
+
+static void
+ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED, void *all_dbs_)
+{
+ struct shash *all_dbs = all_dbs_;
+ struct shash_node *node;
+ struct ds s;
+
+ ds_init(&s);
+
+ SHASH_FOR_EACH(node, all_dbs) {
+ ds_put_format(&s, "%s\n", node->name);
+ }
+
+ 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)
@@ -1155,24 +1368,33 @@ usage(void)
}
/* Truncates and replaces the contents of 'config_file' by a representation
- * of 'remotes'. */
+ * of 'aux->remotes' and 'aux->all_dbs'. */
static void
-save_config(FILE *config_file, const struct sset *remotes)
+save_config(FILE *config_file, const struct load_config_aux *aux)
{
- const char *remote;
- struct json *json;
+ const char *remote, *dbname;
+ struct json *obj, *arr1, *arr2;
char *s;
if (ftruncate(fileno(config_file), 0) == -1) {
VLOG_FATAL("failed to truncate temporary file (%s)", strerror(errno));
}
- json = json_array_create_empty();
- SSET_FOR_EACH (remote, remotes) {
- json_array_add(json, json_string_create(remote));
+ arr1 = json_array_create_empty();
+ SSET_FOR_EACH (remote, aux->remotes) {
+ json_array_add(arr1, json_string_create(remote));
}
- s = json_to_string(json, 0);
- json_destroy(json);
+
+ arr2 = json_array_create_empty();
+ SSET_FOR_EACH (dbname, aux->dbnames) {
+ json_array_add(arr2, json_string_create(dbname));
+ }
+
+ obj = json_object_create();
+ json_object_put(obj, "remotes", arr1);
+ json_object_put(obj, "dbnames", arr2);
+ s = json_to_string(obj, 0);
+ json_destroy(obj);
if (fseek(config_file, 0, SEEK_SET) != 0
|| fputs(s, config_file) == EOF
@@ -1182,15 +1404,18 @@ save_config(FILE *config_file, const struct sset *remotes)
free(s);
}
-/* Clears and replaces 'remotes' by a configuration read from 'config_file',
- * which must have been previously written by save_config(). */
+/* Clears and replaces 'aux->remotes' and 'aux->dbnames' by a configuration
+ * read from 'config_file', * which must have been previously written by
+ * save_config(). */
static void
-load_config(FILE *config_file, struct sset *remotes)
+load_config(FILE *config_file, struct load_config_aux *aux)
{
- struct json *json;
+ struct json *json, *json_arr;
size_t i;
+ struct shash_node *node;
- sset_clear(remotes);
+ sset_clear(aux->remotes);
+ sset_clear(aux->dbnames);
if (fseek(config_file, 0, SEEK_SET) != 0) {
VLOG_FATAL("seek failed in temporary file (%s)", strerror(errno));
@@ -1199,10 +1424,19 @@ load_config(FILE *config_file, struct sset *remotes)
if (json->type == JSON_STRING) {
VLOG_FATAL("reading json failed (%s)", json_string(json));
}
- ovs_assert(json->type == JSON_ARRAY);
- for (i = 0; i < json->u.array.n; i++) {
- const struct json *remote = json->u.array.elems[i];
- sset_add(remotes, json_string(remote));
+ ovs_assert(json->type == JSON_OBJECT);
+
+ SHASH_FOR_EACH (node, json_object(json)) {
+ json_arr = node->data;
+ ovs_assert(json_arr->type == JSON_ARRAY);
+ for (i = 0; i < json_arr->u.array.n; i++) {
+ const struct json *elem = json_arr->u.array.elems[i];
+ if (!strcmp(node->name, "remotes")) {
+ sset_add(aux->remotes, json_string(elem));
+ } else if (!strcmp(node->name, "dbnames")) {
+ sset_add(aux->dbnames, json_string(elem));
+ }
+ }
}
json_destroy(json);
}
diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c
index 6b53f4a..35e3153 100644
--- a/ovsdb/ovsdb.c
+++ b/ovsdb/ovsdb.c
@@ -25,6 +25,9 @@
#include "simap.h"
#include "table.h"
#include "transaction.h"
+#include "vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(ovsdb);
struct ovsdb_schema *
ovsdb_schema_create(const char *name, const char *version, const char *cksum)
diff --git a/ovsdb/server.c b/ovsdb/server.c
index bf4ef3c..1a79d31 100644
--- a/ovsdb/server.c
+++ b/ovsdb/server.c
@@ -132,6 +132,15 @@ ovsdb_server_add_db(struct ovsdb_server *server, struct ovsdb *db)
return shash_add_once(&server->dbs, db->schema->name, db);
}
+/* Removes 'db' from the set of databases served out by 'server'. Returns
+ * 'db' if successful, NULL if there is no db associated with
+ * db->schema->name. */
+void *
+ovsdb_server_remove_db(struct ovsdb_server *server, struct ovsdb *db)
+{
+ return shash_find_and_delete(&server->dbs, db->schema->name);
+}
+
/* Destroys 'server'. */
void
ovsdb_server_destroy(struct ovsdb_server *server)
diff --git a/ovsdb/server.h b/ovsdb/server.h
index 561f01e..48dcd17 100644
--- a/ovsdb/server.h
+++ b/ovsdb/server.h
@@ -83,6 +83,7 @@ struct ovsdb_server {
void ovsdb_server_init(struct ovsdb_server *);
bool ovsdb_server_add_db(struct ovsdb_server *, struct ovsdb *);
+void *ovsdb_server_remove_db(struct ovsdb_server *, struct ovsdb *);
void ovsdb_server_destroy(struct ovsdb_server *);
struct ovsdb_lock_waiter *ovsdb_server_lock(struct ovsdb_server *,
diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index acb5a44..12e1100 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -164,6 +164,142 @@ AT_CHECK(
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP
+AT_SETUP([ovsdb-server/add-db and remove-db])
+AT_KEYWORDS([ovsdb server positive])
+ON_EXIT([kill `cat ovsdb-server.pid`])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema1
+constraint_schema > schema2
+AT_CHECK([ovsdb-tool create db1 schema1], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
+
+# Start ovsdb-server with just a single database - db1.
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db1], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+])
+
+# Add the second database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+db2
+])
+
+# The database is responsive.
+AT_CHECK([ovsdb-client list-tables unix:socket constraints], [0], [ignore], [ignore])
+
+# Add an already added database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [2],
+ [], [Failed to open the database file.
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+# Add a non-existing database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db3], [2],
+ [], [Failed to open the database file.
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+# Add a remote through a db path in db1.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote db:ordinals,ordinals,name], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [db:ordinals,ordinals,name
+punix:socket
+])
+
+# Removing db1 should also remove the remote.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db db1], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db2
+])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [punix:socket
+])
+AT_CHECK([ovsdb-client list-tables unix:socket ordinals], [1], [ignore], [ignore])
+
+# Remove db2.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db db2], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [])
+AT_CHECK([ovsdb-client list-tables unix:socket constraints], [1], [ignore], [ignore])
+
+# Remove a non-existant database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db db1], [2],
+ [], [Failed to find the database.
+ovs-appctl: ovsdb-server: server returned an error
+])
+
+# Add back db1.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db1], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+])
+
+# Add a remote that has a db path in db1. But do not provide a schema.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-remote db:ordinals,name], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes],
+ [0], [db:ordinals,name
+punix:socket
+])
+
+# Add database db2.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [2], [ignore],
+[Failed to add the database as there exists a db:ordinals,name with invalid db path.
+ovs-appctl: ovsdb-server: server returned an error
+])
+AT_CLEANUP
+
+AT_SETUP([ovsdb-server/add-db and remove-db with --monitor])
+AT_KEYWORDS([ovsdb server positive])
+# Start ovsdb-server, initially with one db.
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool create db1 schema], [0], [ignore], [ignore])
+ON_EXIT([kill `cat *.pid`])
+AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file db1])
+
+# Add the second database.
+constraint_schema > schema2
+AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/add-db db2], [0])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+db2
+])
+
+# Kill the daemon process, making it look like a segfault,
+# and wait for a new daemon process to get spawned.
+cp ovsdb-server.pid old.pid
+AT_CHECK([kill -SEGV `cat ovsdb-server.pid`])
+OVS_WAIT_WHILE([kill -0 `cat old.pid`])
+OVS_WAIT_UNTIL(
+ [test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat old.pid`])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+db2
+])
+
+# Remove the recently added database.
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db db2])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+])
+
+# Kill the daemon process, making it look like a segfault,
+# and wait for a new daemon process to get spawned.
+cp ovsdb-server.pid old.pid
+AT_CHECK([kill -SEGV `cat ovsdb-server.pid`])
+OVS_WAIT_WHILE([kill -0 `cat old.pid`])
+OVS_WAIT_UNTIL(
+ [test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat old.pid`])
+AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs],
+ [0], [db1
+])
+AT_CLEANUP
+
AT_SETUP([--remote=db: implementation])
AT_KEYWORDS([ovsdb server positive])
OVS_RUNDIR=`pwd`; export OVS_RUNDIR
--
1.7.9.5
More information about the dev
mailing list