[ovs-dev,09/15] ovsdb-server: Add support for a built-in _Server database.

Message ID 20180101051640.13043-9-blp@ovn.org
State New
Headers show
Series
  • [ovs-dev,01/15] log: Add async commit support.
Related show

Commit Message

Ben Pfaff Jan. 1, 2018, 5:16 a.m.
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

Patch

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 @@ 
+<?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>
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("<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. */
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