@@ -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 \
@@ -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.
@@ -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 \
new file mode 100755
@@ -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 + '"')
@@ -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
new file mode 100644
@@ -0,0 +1,9 @@
+{"name": "_Server",
+ "version": "1.0.0",
+ "cksum": "3931859656 185",
+ "tables": {
+ "Database": {
+ "columns": {
+ "name": {"type": "string"},
+ "schema": {"type": "string"}},
+ "isRoot": true}}}
new file mode 100644
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<database name="ovsdb-server" title="ovsdb-server _Server schema">
+ <p>
+ Every <code>ovsdb-server</code> (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.
+ </p>
+
+ <table name="Database" title="Databases.">
+ <p>
+ 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.
+ </p>
+ <p>
+ Clients can use the <code>_uuid</code> column in this table as a
+ generation number. The server generates a fresh <code>_uuid</code> every
+ time it adds a database, so that removing and then re-adding a database
+ to the server causes its row <code>_uuid</code> to change.
+ </p>
+
+ <column name="name">
+ The database's name, as specified in its schema.
+ </column>
+
+ <column name="schema">
+ The database schema, as a JSON string.
+ </column>
+ </table>
+</database>
@@ -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 $@
@@ -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"
@@ -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("<internal>");
+ 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. */
@@ -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
@@ -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 */
@@ -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
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 <blp@ovn.org> --- 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