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 <gshe...@nicira.com> --- ovsdb/jsonrpc-server.c | 9 ++ ovsdb/jsonrpc-server.h | 2 + ovsdb/ovsdb-server.1.in | 24 ++++ ovsdb/ovsdb-server.c | 296 ++++++++++++++++++++++++++++++++++++++--------- ovsdb/server.c | 13 +++ ovsdb/server.h | 1 + tests/ovsdb-server.at | 118 +++++++++++++++++++ 7 files changed, 407 insertions(+), 56 deletions(-) diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c index 9f99d64..016dd33 100644 --- a/ovsdb/jsonrpc-server.c +++ b/ovsdb/jsonrpc-server.c @@ -132,6 +132,15 @@ 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 + * true if successful, false if there is no database associated with 'db'. */ +bool +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..e6a1642 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 *); +bool 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 ceefef5..4339620 100644 --- a/ovsdb/ovsdb-server.1.in +++ b/ovsdb/ovsdb-server.1.in @@ -150,6 +150,30 @@ not list remotes added indirectly because they were read from the database by configuring a \fBdb:\fIdb\fB,\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 \fIdatabase\fR from the running \fBovsdb\-server\fR. \fIdatabase\fR +must be a database name as listed by \fBovsdb-server/list\-dbs\fR. +.IP +If a remote has been configured that points to the specified +\fIdatabase\fR (e.g. \fB\-\-remote=db:\fIdatabase\fB,\fR... on the +command line), then it is automatically removed. +.IP +Any public key infrastructure options specified through this database +(e.g. \fB\-\-private\-key=db:\fIdatabase,\fR... on the command line) +are no longer checked for new changes, but any files previously +configured are still used. (Adding \fIdatabase\fR back will cause the +public key infrastructure options specified through it to update +again.) +. +.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 72c13c6..cd6961a 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -78,20 +78,21 @@ 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 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); @@ -108,8 +109,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 +119,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 +149,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 +220,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(); @@ -429,6 +440,28 @@ parse_db_string_column(const struct shash *all_dbs, return NULL; } +static bool +ssl_path_valid(const struct shash *all_dbs, const char *path) +{ + const struct ovsdb_column *column; + const struct ovsdb_table *table; + char *retval; + const struct db *db; + + if (!path) { + return true; + } + + retval = (strncmp("db:", path, 3) + ? NULL + : parse_db_column(all_dbs, path, &db, &table, &column)); + if (retval) { + free(retval); + return false; + } + return true; +} + static OVS_UNUSED const char * query_db_string(const struct shash *all_dbs, const char *name) { @@ -860,6 +893,8 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc, { struct shash resolved_remotes; const char *name; + static char *ssl_error_message; + static bool ssl_reconfigure; /* Configure remotes. */ shash_init(&resolved_remotes); @@ -873,11 +908,28 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc, ovsdb_jsonrpc_server_set_remotes(jsonrpc, &resolved_remotes); shash_destroy_free_data(&resolved_remotes); - /* Configure SSL. */ + /* During ovsd-server run, a database that is referenced by a SSL path + * may have been removed. If a SSL path is invalid, raise an error. */ + 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)) { + if (!ssl_error_message) { + ssl_error_message = xasprintf("SSL paths no longer valid."); + VLOG_ERR("%s", ssl_error_message); + } + return; + } else if (ssl_error_message) { + VLOG_INFO("SSL paths are valid again."); + free(ssl_error_message); + ssl_error_message = NULL; + } + } 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), bootstrap_ca_cert); + ssl_reconfigure = true; } static void @@ -954,7 +1006,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; @@ -968,7 +1020,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 { @@ -983,13 +1035,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"); @@ -1017,6 +1069,117 @@ ovsdb_server_list_remotes(struct unixctl_conn *conn, int argc OVS_UNUSED, ds_destroy(&s); } + +/* "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; + + 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); + + 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); + } 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) @@ -1142,24 +1305,33 @@ usage(void) } /* Truncates and replaces the contents of 'config_file' by a representation - * of 'remotes'. */ + * of 'aux->remotes' and 'aux->dbnames'. */ 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 @@ -1169,15 +1341,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)); @@ -1186,10 +1361,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/server.c b/ovsdb/server.c index bf4ef3c..82f55cb 100644 --- a/ovsdb/server.c +++ b/ovsdb/server.c @@ -132,6 +132,19 @@ 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 + * true if successful, false if there is no db associated with + * db->schema->name. */ +bool +ovsdb_server_remove_db(struct ovsdb_server *server, struct ovsdb *db) +{ + void *data = shash_find_and_delete(&server->dbs, db->schema->name); + if (data) { + return true; + } + return false; +} + /* Destroys 'server'. */ void ovsdb_server_destroy(struct ovsdb_server *server) diff --git a/ovsdb/server.h b/ovsdb/server.h index 561f01e..047cbb7 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 *); +bool 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 2368cbc..d775aa7 100644 --- a/tests/ovsdb-server.at +++ b/tests/ovsdb-server.at @@ -164,6 +164,124 @@ 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 databases are responsive. +AT_CHECK([ovsdb-client list-tables unix:socket constraints], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client list-tables unix:socket ordinals], [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 +]) +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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev