From patchwork Mon Jan 1 05:16:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 854292 X-Patchwork-Delegate: jpettit@nicira.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3z95C04D9Mz9t84 for ; Mon, 1 Jan 2018 16:21:16 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C41D8CD0; Mon, 1 Jan 2018 05:17:05 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 12A23CCF for ; Mon, 1 Jan 2018 05:17:05 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B9A2D4EC for ; Mon, 1 Jan 2018 05:17:01 +0000 (UTC) X-Originating-IP: 173.228.112.64 Received: from sigabrt.gateway.sonic.net (173-228-112-64.dsl.dynamic.fusionbroadband.com [173.228.112.64]) (Authenticated sender: blp@ovn.org) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 8C492C5A51; Mon, 1 Jan 2018 06:16:59 +0100 (CET) From: Ben Pfaff To: dev@openvswitch.org Date: Sun, 31 Dec 2017 21:16:34 -0800 Message-Id: <20180101051640.13043-9-blp@ovn.org> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20180101051640.13043-1-blp@ovn.org> References: <20180101051640.13043-1-blp@ovn.org> X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, URI_NOVOWEL autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH 09/15] ovsdb-server: Add support for a built-in _Server database. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The _Server database is valuable primarily because it provides database clients a way to find out the details of changes to databases, schemas, etc. in a granular, natural way. Until now, the only way that the server could notify clients about these kinds of changes was to close the session; when the client reconnects, it is expected to reassess the server's state. One way to provide this kind of granular information would be to add specific JSON-RPC requests to obtain notifications for different kinds of changes, but since ovsdb-server already provides granular and flexible notification support for databases, using a database for the purpose is convenient and avoids duplicating functionality. Initially this database only reports databases' names and schemas, but when clustering support is added in a later commit it will also report important aspects of clustering and cluster status. Thus, this database also reduces the need to add JSON-RPC calls to retrieve information about new features. Signed-off-by: Ben Pfaff Acked-by: Justin Pettit --- Makefile.am | 8 --- NEWS | 2 + build-aux/automake.mk | 12 ++++- build-aux/text2c | 16 ++++++ ovsdb/.gitignore | 3 ++ ovsdb/_server.ovsschema | 9 ++++ ovsdb/_server.xml | 31 ++++++++++++ ovsdb/automake.mk | 26 ++++++++++ ovsdb/ovsdb-server.1.in | 6 +++ ovsdb/ovsdb-server.c | 131 +++++++++++++++++++++++++++++++++++++++++++++--- ovsdb/ovsdb-util.c | 93 +++++++++++++++++++++++++++++++--- ovsdb/ovsdb-util.h | 9 ++++ tests/ovsdb-server.at | 70 +++++++++++++------------- 13 files changed, 359 insertions(+), 57 deletions(-) create mode 100755 build-aux/text2c create mode 100644 ovsdb/_server.ovsschema create mode 100644 ovsdb/_server.xml diff --git a/Makefile.am b/Makefile.am index d7cfdcd52a98..8eef4e3f5640 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,14 +82,6 @@ EXTRA_DIST = \ .travis/osx-prepare.sh \ appveyor.yml \ boot.sh \ - build-aux/cccl \ - build-aux/cksum-schema-check \ - build-aux/calculate-schema-cksum \ - build-aux/dist-docs \ - build-aux/dpdkstrip.py \ - build-aux/sodepends.py \ - build-aux/soexpand.py \ - build-aux/xml2nroff \ $(MAN_FRAGMENTS) \ $(MAN_ROOTS) \ Vagrantfile \ diff --git a/NEWS b/NEWS index af98c2f80f5a..b697e4968072 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ Post-v2.8.0 * New high-level documentation in ovsdb(7). * New file format documentation for developers in ovsdb(5). * Protocol documentation moved from ovsdb-server(1) to ovsdb-server(7). + * ovsdb-server now always hosts a built-in database named _Server. See + ovsdb-server(5) for more details. * ovsdb-client: New "get-schema-cksum" and "query" commands. * ovsdb-client: New "backup" and "restore" commands. * ovsdb-tool: New "db-name" and "schema-name" commands. diff --git a/build-aux/automake.mk b/build-aux/automake.mk index 6baafab0e867..a1f2f856f939 100644 --- a/build-aux/automake.mk +++ b/build-aux/automake.mk @@ -1,4 +1,14 @@ -# This file is purely used for checking the style of the python build tools. +EXTRA_DIST += \ + build-aux/calculate-schema-cksum \ + build-aux/cccl \ + build-aux/cksum-schema-check \ + build-aux/dist-docs \ + build-aux/dpdkstrip.py \ + build-aux/sodepends.py \ + build-aux/soexpand.py \ + build-aux/text2c \ + build-aux/xml2nroff + FLAKE8_PYFILES += \ $(srcdir)/build-aux/xml2nroff \ build-aux/dpdkstrip.py \ diff --git a/build-aux/text2c b/build-aux/text2c new file mode 100755 index 000000000000..cb1f256f1775 --- /dev/null +++ b/build-aux/text2c @@ -0,0 +1,16 @@ +#! /usr/bin/python + +import re +import sys + +"""This utility reads its input, which should be plain text, and +prints it back transformed into quoted strings that may be #included +into C source code.""" + +while True: + line = sys.stdin.readline() + if not line: + break + + s = line.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n") + print('"' + s + '"') diff --git a/ovsdb/.gitignore b/ovsdb/.gitignore index d715dee925b9..fbcefafc6e97 100644 --- a/ovsdb/.gitignore +++ b/ovsdb/.gitignore @@ -1,3 +1,5 @@ +/_server.ovsschema.inc +/_server.ovsschema.stamp /ovsdb-client /ovsdb-client.1 /ovsdb-doc @@ -5,6 +7,7 @@ /ovsdb-idlc /ovsdb-server /ovsdb-server.1 +/ovsdb-server.5 /ovsdb-tool /ovsdb-tool.1 /libovsdb.pc diff --git a/ovsdb/_server.ovsschema b/ovsdb/_server.ovsschema new file mode 100644 index 000000000000..8997bae5fa36 --- /dev/null +++ b/ovsdb/_server.ovsschema @@ -0,0 +1,9 @@ +{"name": "_Server", + "version": "1.0.0", + "cksum": "3931859656 185", + "tables": { + "Database": { + "columns": { + "name": {"type": "string"}, + "schema": {"type": "string"}}, + "isRoot": true}}} diff --git a/ovsdb/_server.xml b/ovsdb/_server.xml new file mode 100644 index 000000000000..a55beb9bd6de --- /dev/null +++ b/ovsdb/_server.xml @@ -0,0 +1,31 @@ + + +

+ Every ovsdb-server (version 2.9 or later) always hosts an + instance of this schema, which holds information on the status and + configuration of the server itself. This database is read-only. This + manpage describes the schema for this database. +

+ + +

+ This table describes the databases hosted by the database server, with + one row per database. As its database configuration and status changes, + the server automatically and immediately updates the table to match. +

+

+ Clients can use the _uuid column in this table as a + generation number. The server generates a fresh _uuid every + time it adds a database, so that removing and then re-adding a database + to the server causes its row _uuid to change. +

+ + + The database's name, as specified in its schema. + + + + The database schema, as a JSON string. + +
+
diff --git a/ovsdb/automake.mk b/ovsdb/automake.mk index d040fc6de886..c90e2e5b77f9 100644 --- a/ovsdb/automake.mk +++ b/ovsdb/automake.mk @@ -109,3 +109,29 @@ EXTRA_DIST += ovsdb/ovsdb-dot.in ovsdb/dot2pic noinst_SCRIPTS += ovsdb/ovsdb-dot CLEANFILES += ovsdb/ovsdb-dot OVSDB_DOT = $(run_python) $(srcdir)/ovsdb/ovsdb-dot.in + +EXTRA_DIST += ovsdb/_server.ovsschema +CLEANFILES += ovsdb/_server.ovsschema.inc +ovsdb/ovsdb-server.o: ovsdb/_server.ovsschema.inc +ovsdb/_server.ovsschema.inc: ovsdb/_server.ovsschema $(srcdir)/build-aux/text2c + $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/text2c < $< > $@.tmp + $(AM_V_at)mv $@.tmp $@ + +# Version checking for _server.ovsschema. +ALL_LOCAL += ovsdb/_server.ovsschema.stamp +ovsdb/_server.ovsschema.stamp: ovsdb/_server.ovsschema + $(srcdir)/build-aux/cksum-schema-check $? $@ +CLEANFILES += ovsdb/_server.ovsschema.stamp + +# _Server schema documentation +EXTRA_DIST += ovsdb/_server.xml +CLEANFILES += ovsdb/ovsdb-server.5 +man_MANS += ovsdb/ovsdb-server.5 +ovsdb/ovsdb-server.5: \ + ovsdb/ovsdb-doc ovsdb/_server.xml ovsdb/_server.ovsschema \ + $(VSWITCH_PIC) + $(AM_V_GEN)$(OVSDB_DOC) \ + --version=$(VERSION) \ + $(srcdir)/ovsdb/_server.ovsschema \ + $(srcdir)/ovsdb/_server.xml > $@.tmp && \ + mv $@.tmp $@ diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in index 15ff77fd28aa..dfca40d4ef79 100644 --- a/ovsdb/ovsdb-server.1.in +++ b/ovsdb/ovsdb-server.1.in @@ -45,6 +45,12 @@ example, \fBovsdb\-tool create\fR. This OVSDB implementation supports standalone and active-backup databases, as well as database replication. See the Service Models section of \fBovsdb\fR(7) for more information. +.PP +In addition to user-specified databases, \fBovsdb\-server\fR version +2.9 and later also always hosts a built-in database named +\fB_Server\fR. Please see \fBovsdb\-server\fR(5) for documentation on +this database's schema. +. .SH OPTIONS . .IP "\fB\-\-remote=\fIremote\fR" diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 1efb5552da5a..dd0cdfe6a38b 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -65,6 +65,7 @@ struct db { char *filename; struct ovsdb_file *file; struct ovsdb *db; + struct uuid row_uuid; }; /* SSL configuration. */ @@ -107,6 +108,7 @@ static unixctl_cb_func ovsdb_server_remove_database; static unixctl_cb_func ovsdb_server_list_databases; static char *open_db(struct server_config *config, const char *filename); +static void add_server_db(struct server_config *); static void close_db(struct db *db); static void parse_options(int *argc, char **argvp[], @@ -124,6 +126,7 @@ static void report_error_if_changed(char *error, char **last_errorp); static void update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc, const struct sset *remotes, struct shash *all_dbs); +static void update_server_status(struct shash *all_dbs); static void save_config__(FILE *config_file, const struct sset *remotes, const struct sset *db_filenames, @@ -214,6 +217,8 @@ main_loop(struct ovsdb_jsonrpc_server *jsonrpc, struct shash *all_dbs, update_remote_status(jsonrpc, remotes, all_dbs); } + update_server_status(all_dbs); + memory_wait(); if (*is_backup) { replication_wait(); @@ -328,6 +333,7 @@ main(int argc, char *argv[]) ovs_fatal(0, "%s", error); } } + add_server_db(&server_config); error = reconfigure_remotes(jsonrpc, &all_dbs, &remotes); if (!error) { @@ -490,6 +496,16 @@ close_db(struct db *db) free(db); } +static void +add_db(struct server_config *config, const char *name, struct db *db) +{ + db->row_uuid = UUID_ZERO; + shash_add_assert(config->all_dbs, name, db); + bool ok OVS_UNUSED = ovsdb_jsonrpc_server_add_db(config->jsonrpc, + db->db); + ovs_assert(ok); +} + static char * open_db(struct server_config *config, const char *filename) { @@ -524,6 +540,27 @@ open_db(struct server_config *config, const char *filename) return error; } +/* Add the internal _Server database to the server configuration. */ +static void +add_server_db(struct server_config *config) +{ + struct json *schema_json = json_from_string( +#include "ovsdb/_server.ovsschema.inc" + ); + ovs_assert(schema_json->type == JSON_OBJECT); + + struct ovsdb_schema *schema; + struct ovsdb_error *error OVS_UNUSED = ovsdb_schema_from_json(schema_json, + &schema); + ovs_assert(!error); + json_destroy(schema_json); + + struct db *db = xzalloc(sizeof *db); + db->filename = xstrdup(""); + db->db = ovsdb_create(schema); + add_db(config, db->db->schema->name, db); +} + static char * OVS_WARN_UNUSED_RESULT parse_db_column__(const struct shash *all_dbs, const char *name_, char *name, @@ -888,6 +925,18 @@ update_remote_rows(const struct shash *all_dbs, const struct db *db_, } static void +commit_txn(struct ovsdb_txn *txn, const char *name) +{ + struct ovsdb_error *error = ovsdb_txn_commit(txn, false); + if (error) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + char *msg = ovsdb_error_to_string_free(error); + VLOG_ERR_RL(&rl, "Failed to update %s: %s", name, msg); + free(msg); + } +} + +static void update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc, const struct sset *remotes, struct shash *all_dbs) @@ -903,14 +952,84 @@ update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc, update_remote_rows(all_dbs, db, remote, jsonrpc, txn); } - struct ovsdb_error *error = ovsdb_txn_commit(txn, false); - if (error) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - char *msg = ovsdb_error_to_string_free(error); - VLOG_ERR_RL(&rl, "Failed to update remote status: %s", msg); - free(msg); + commit_txn(txn, node->name); + } +} + +/* Updates 'row', a row in the _Server database's Database table, to match + * 'db'. */ +static void +update_database_status(struct ovsdb_row *row, struct db *db) +{ + ovsdb_util_write_string_column(row, "name", db->db->schema->name); + + const struct uuid *row_uuid = ovsdb_row_get_uuid(row); + if (!uuid_equals(row_uuid, &db->row_uuid)) { + db->row_uuid = *row_uuid; + + /* The schema can only change if the row UUID changes, so only update + * it in that case. Presumably, this is worth optimizing because + * schemas are often kilobytes in size and nontrivial to serialize. */ + struct json *json_schema = ovsdb_schema_to_json(db->db->schema); + char *schema = json_to_string(json_schema, JSSF_SORT); + ovsdb_util_write_string_column(row, "schema", schema); + free(schema); + json_destroy(json_schema); + } +} + +/* Updates the Database table in the _Server database. */ +static void +update_server_status(struct shash *all_dbs) +{ + struct db *server_db = shash_find_data(all_dbs, "_Server"); + struct ovsdb_table *database_table = shash_find_data( + &server_db->db->tables, "Database"); + struct ovsdb_txn *txn = ovsdb_txn_create(server_db->db); + + /* Update rows for databases that still exist. + * Delete rows for databases that no longer exist. */ + const struct ovsdb_row *row, *next_row; + HMAP_FOR_EACH_SAFE (row, next_row, hmap_node, &database_table->rows) { + const char *name; + ovsdb_util_read_string_column(row, "name", &name); + struct db *db = shash_find_data(all_dbs, name); + if (!db || !db->db) { + ovsdb_txn_row_delete(txn, row); + } else { + update_database_status(ovsdb_txn_row_modify(txn, row), db); } } + + /* Add rows for new databases. + * + * This is O(n**2) but usually there are only 2 or 3 databases. */ + struct shash_node *node; + SHASH_FOR_EACH (node, all_dbs) { + struct db *db = node->data; + + if (!db->db) { + continue; + } + + HMAP_FOR_EACH (row, hmap_node, &database_table->rows) { + const char *name; + ovsdb_util_read_string_column(row, "name", &name); + if (!strcmp(name, node->name)) { + goto next; + } + } + + /* Add row. */ + struct ovsdb_row *row = ovsdb_row_create(database_table); + uuid_generate(ovsdb_row_get_uuid_rw(row)); + update_database_status(row, db); + ovsdb_txn_row_insert(txn, row); + + next:; + } + + commit_txn(txn, "_Server"); } /* Reconfigures ovsdb-server's remotes based on information in the database. */ diff --git a/ovsdb/ovsdb-util.c b/ovsdb/ovsdb-util.c index 5ee5e4ddaf8d..06d25af49a18 100644 --- a/ovsdb/ovsdb-util.c +++ b/ovsdb/ovsdb-util.c @@ -22,6 +22,38 @@ VLOG_DEFINE_THIS_MODULE(ovsdb_util); +static void +ovsdb_util_clear_column(struct ovsdb_row *row, const char *column_name) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + const struct ovsdb_table_schema *schema = row->table->schema; + const struct ovsdb_column *column; + + column = ovsdb_table_schema_get_column(schema, column_name); + if (!column) { + VLOG_DBG_RL(&rl, "Table `%s' has no `%s' column", + schema->name, column_name); + return; + } + + if (column->type.n_min) { + if (!VLOG_DROP_DBG(&rl)) { + char *type_name = ovsdb_type_to_english(&column->type); + VLOG_DBG("Table `%s' column `%s' has type %s, which requires " + "a value, when it was expected to be optional", + schema->name, column_name, type_name); + free(type_name); + } + return; + } + + struct ovsdb_datum *datum = &row->fields[column->index]; + if (datum->n) { + ovsdb_datum_destroy(datum, &column->type); + ovsdb_datum_init_empty(datum); + } +} + struct ovsdb_datum * ovsdb_util_get_datum(struct ovsdb_row *row, const char *column_name, const enum ovsdb_atomic_type key_type, @@ -164,29 +196,74 @@ ovsdb_util_read_bool_column(const struct ovsdb_row *row, return atom != NULL; } -void -ovsdb_util_write_bool_column(struct ovsdb_row *row, const char *column_name, - bool value) +bool +ovsdb_util_read_uuid_column(const struct ovsdb_row *row, + const char *column_name, struct uuid *uuid) +{ + const union ovsdb_atom *atom; + + atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_UUID); + *uuid = atom ? atom->uuid : UUID_ZERO; + return atom != NULL; +} + +static void +ovsdb_util_write_singleton(struct ovsdb_row *row, const char *column_name, + const union ovsdb_atom *atom, + enum ovsdb_atomic_type type) { const struct ovsdb_column *column; struct ovsdb_datum *datum; column = ovsdb_table_schema_get_column(row->table->schema, column_name); - datum = ovsdb_util_get_datum(row, column_name, OVSDB_TYPE_BOOLEAN, - OVSDB_TYPE_VOID, 1); + datum = ovsdb_util_get_datum(row, column_name, type, OVSDB_TYPE_VOID, 1); if (!datum) { return; } - if (datum->n != 1) { + if (datum->n == 1) { + if (ovsdb_atom_equals(&datum->keys[0], atom, type)) { + return; + } + } else { ovsdb_datum_destroy(datum, &column->type); - datum->n = 1; datum->keys = xmalloc(sizeof *datum->keys); datum->values = NULL; } + ovsdb_atom_clone(&datum->keys[0], atom, type); +} - datum->keys[0].boolean = value; +void +ovsdb_util_write_bool_column(struct ovsdb_row *row, const char *column_name, + bool value) +{ + const union ovsdb_atom atom = { .boolean = value }; + ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_BOOLEAN); +} + +void +ovsdb_util_write_uuid_column(struct ovsdb_row *row, const char *column_name, + const struct uuid *uuid) +{ + if (uuid) { + const union ovsdb_atom atom = { .uuid = *uuid }; + ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_UUID); + } else { + ovsdb_util_clear_column(row, column_name); + } +} + +void +ovsdb_util_write_string_column(struct ovsdb_row *row, const char *column_name, + const char *string) +{ + if (string) { + const union ovsdb_atom atom = { .string = CONST_CAST(char *, string) }; + ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_STRING); + } else { + ovsdb_util_clear_column(row, column_name); + } } void diff --git a/ovsdb/ovsdb-util.h b/ovsdb/ovsdb-util.h index abd81ff38cd2..a0404a3a7ff0 100644 --- a/ovsdb/ovsdb-util.h +++ b/ovsdb/ovsdb-util.h @@ -38,6 +38,9 @@ bool ovsdb_util_read_integer_column(const struct ovsdb_row *row, bool ovsdb_util_read_string_column(const struct ovsdb_row *row, const char *column_name, const char **stringp); +void ovsdb_util_write_string_column(struct ovsdb_row *row, + const char *column_name, + const char *string); void ovsdb_util_write_string_string_column(struct ovsdb_row *row, const char *column_name, char **keys, char **values, @@ -48,5 +51,11 @@ bool ovsdb_util_read_bool_column(const struct ovsdb_row *row, void ovsdb_util_write_bool_column(struct ovsdb_row *row, const char *column_name, bool value); +bool ovsdb_util_read_uuid_column(const struct ovsdb_row *row, + const char *column_name, + struct uuid *); +void ovsdb_util_write_uuid_column(struct ovsdb_row *row, + const char *column_name, + const struct uuid *); #endif /* ovsdb/util.h */ diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at index 968356781604..07ceda92496d 100644 --- a/tests/ovsdb-server.at +++ b/tests/ovsdb-server.at @@ -137,20 +137,31 @@ AT_CHECK([uuidfilt output], [0], [test ! -e pid || kill `cat pid`]) AT_CLEANUP +dnl CHECK_DBS([databases]) +dnl +dnl Checks that ovsdb-server hosts the given 'databases', each of which +dnl needs to be followed by a newline. +m4_define([CHECK_DBS], + [AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], + [0], [_Server +$1]) +AT_CHECK([ovsdb-client --no-headings dump _Server Database name | sort], [0], [dnl +Database table +_Server +$1])]) + AT_SETUP([database multiplexing implementation]) AT_KEYWORDS([ovsdb server positive]) 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]) -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db1 db2], [0], [ignore], [ignore]) -AT_CHECK( - [[ovsdb-client list-dbs unix:socket]], - [0], [constraints +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:db.sock db1 db2], [0], [ignore], [ignore]) +CHECK_DBS([constraints ordinals -], [ignore], [test ! -e pid || kill `cat pid`]) +]) AT_CHECK( - [[ovstest test-jsonrpc request unix:socket get_schema [\"nonexistent\"]]], [0], + [[ovstest test-jsonrpc request unix:db.sock get_schema [\"nonexistent\"]]], [0], [[{"error":{"details":"get_schema request specifies unknown database nonexistent","error":"unknown database","syntax":"[\"nonexistent\"]"},"id":0,"result":null} ]], [], [test ! -e pid || kill `cat pid`]) OVSDB_SERVER_SHUTDOWN @@ -165,21 +176,19 @@ 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], [ordinals +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:db.sock db1], [0]) +CHECK_DBS([ordinals ]) # 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], [constraints +CHECK_DBS([constraints ordinals ]) # 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]) +AT_CHECK([ovsdb-client list-tables unix:db.sock constraints], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client list-tables unix:db.sock ordinals], [0], [ignore], [ignore]) # Add an already added database. if test $IS_WIN32 = "yes"; then @@ -205,25 +214,23 @@ ovs-appctl: ovsdb-server: server returned an error 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 +punix:db.sock ]) # Removing db1 has no effect on its remote. AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db ordinals], [0]) -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], - [0], [constraints +CHECK_DBS([constraints ]) AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-remotes], [0], [db:ordinals,ordinals,name -punix:socket +punix:db.sock ]) -AT_CHECK([ovsdb-client list-tables unix:socket ordinals], [1], [ignore], [ignore]) +AT_CHECK([ovsdb-client list-tables unix:db.sock ordinals], [1], [ignore], [ignore]) # Remove db2. AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db constraints], [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]) +CHECK_DBS() +AT_CHECK([ovsdb-client list-tables unix:db.sock constraints], [1], [ignore], [ignore]) # Remove a non-existent database. AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db ordinals], [2], @@ -233,10 +240,9 @@ ovs-appctl: ovsdb-server: server returned an error # Add a removed 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], [constraints +CHECK_DBS([constraints ]) -AT_CHECK([ovsdb-client list-tables unix:socket constraints], [0], [ignore], [ignore]) +AT_CHECK([ovsdb-client list-tables unix:db.sock constraints], [0], [ignore], [ignore]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP @@ -247,14 +253,13 @@ AT_SKIP_IF([test "$IS_WIN32" = "yes"]) 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]) +AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file --remote=punix:db.sock 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], [constraints +CHECK_DBS([constraints ordinals ]) @@ -266,8 +271,7 @@ OVS_WAIT_WHILE([kill -0 `cat old.pid`]) OVS_WAIT_UNTIL( [test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat old.pid`]) OVS_WAIT_UNTIL([ovs-appctl -t ovsdb-server version]) -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], - [0], [constraints +CHECK_DBS([constraints ordinals ]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) @@ -282,12 +286,11 @@ AT_CHECK([ovsdb-tool create db1 schema], [0], [ignore], [ignore]) constraint_schema > schema2 AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore]) on_exit 'kill `cat *.pid`' -AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file db1 db2]) +AT_CHECK([ovsdb-server -v -vvlog:off --monitor --detach --no-chdir --pidfile --log-file --remote=punix:db.sock db1 db2]) # Remove the second database. AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/remove-db constraints]) -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], - [0], [ordinals +CHECK_DBS([ordinals ]) # Kill the daemon process, making it look like a segfault, @@ -298,8 +301,7 @@ OVS_WAIT_WHILE([kill -0 `cat old.pid`]) OVS_WAIT_UNTIL( [test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat old.pid`]) OVS_WAIT_UNTIL([ovs-appctl -t ovsdb-server version]) -AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], - [0], [ordinals +CHECK_DBS([ordinals ]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP