[ovs-dev] [PATCH 3/4] ovsdb: Add table exclusion functionality to OVSDB

Cabrera Vega, Mario Alberto mario.cabrera at hpe.com
Tue Mar 29 21:30:16 UTC 2016


A blacklist of tables that will be excluded from replication can be
specified by the following option:

--sync-exclude-tables=db:table[,db:table]...

Where 'table' corresponds to a table name, and 'db' corresponds to the
database name where the table resides.

Signed-off-by: Mario Cabrera <mario.cabrera at hpe.com>
---
 ovsdb/ovsdb-server.c       |   6 ++
 ovsdb/replication.c        |  56 ++++++++++++++-
 ovsdb/replication.h        |   1 +
 tests/automake.mk          |   1 +
 tests/ovsdb-replication.at | 174 +++++++++++++++++++++++++++++++++++++++++++++
 tests/ovsdb-server.at      |  56 +++++++++++++++
 tests/ovsdb.at             |   1 +
 7 files changed, 292 insertions(+), 3 deletions(-)
 create mode 100644 tests/ovsdb-replication.at

diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 63dd209..93beaf0 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -1265,6 +1265,7 @@ parse_options(int *argcp, char **argvp[],
         OPT_BOOTSTRAP_CA_CERT,
         OPT_PEER_CA_CERT,
         OPT_SYNC_FROM,
+        OPT_SYNC_EXCLUDE,
         VLOG_OPTION_ENUMS,
         DAEMON_OPTION_ENUMS
     };
@@ -1284,6 +1285,7 @@ parse_options(int *argcp, char **argvp[],
         {"certificate", required_argument, NULL, 'c'},
         {"ca-cert",     required_argument, NULL, 'C'},
         {"sync-from",   required_argument, NULL, OPT_SYNC_FROM},
+        {"sync-exclude-tables", required_argument, NULL, OPT_SYNC_EXCLUDE},
         {NULL, 0, NULL, 0},
     };
     char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
@@ -1349,6 +1351,10 @@ parse_options(int *argcp, char **argvp[],
             connect_to_remote_server = true;
             break;
 
+        case OPT_SYNC_EXCLUDE:
+            set_tables_blacklist(optarg);
+            break;
+
         case '?':
             exit(EXIT_FAILURE);
 
diff --git a/ovsdb/replication.c b/ovsdb/replication.c
index d9e609e..5507a5a 100644
--- a/ovsdb/replication.c
+++ b/ovsdb/replication.c
@@ -35,8 +35,10 @@
 static char *remote_ovsdb_server;
 static struct jsonrpc *rpc;
 static struct sset monitored_tables = SSET_INITIALIZER(&monitored_tables);
+static struct sset tables_blacklist = SSET_INITIALIZER(&tables_blacklist);
 static bool reset_dbs = true;
 
+void replication_init(void);
 static struct jsonrpc *open_jsonrpc(const char *server);
 static struct ovsdb_error *check_jsonrpc_error(int error,
                                                struct jsonrpc_msg **reply_);
@@ -73,6 +75,14 @@ static struct ovsdb_error *execute_update(struct ovsdb_txn *txn,
                                           struct json *new);
 

 void
+replication_init(void)
+{
+    sset_init(&monitored_tables);
+    sset_init(&tables_blacklist);
+    reset_dbs = true;
+}
+
+void
 replication_run(struct shash *all_dbs)
 {
     if (sset_is_empty(&monitored_tables) && remote_ovsdb_server) {
@@ -109,10 +119,30 @@ set_remote_ovsdb_server(const char *remote_server)
 }
 
 void
+set_tables_blacklist(const char *blacklist)
+{
+    char *save_ptr = NULL;
+    char *blacklist_item;
+
+    replication_init();
+
+    if (blacklist) {
+       char *t_blacklist = strdup(blacklist);
+        for (blacklist_item = strtok_r(t_blacklist, ",", &save_ptr);
+             blacklist_item != NULL;
+             blacklist_item = strtok_r(NULL, ",", &save_ptr)) {
+            sset_add(&tables_blacklist, blacklist_item);
+        }
+        free(t_blacklist);
+    }
+}
+
+void
 disconnect_remote_server(void)
 {
     jsonrpc_close(rpc);
     sset_destroy(&monitored_tables);
+    sset_destroy(&tables_blacklist);
 
     if (remote_ovsdb_server) {
         free(remote_ovsdb_server);
@@ -160,8 +190,18 @@ reset_database(struct ovsdb *db, struct ovsdb_txn *txn)
         struct ovsdb_table *table = table_node->data;
         struct ovsdb_row *row;
 
-        HMAP_FOR_EACH (row, hmap_node, &table->rows) {
-            ovsdb_txn_row_delete(txn, row);
+        size_t blacklist_item_len = strlen(db->schema->name) +
+                                    strlen(table_node->name) + 2;
+
+        /* Do not reset if table is blacklisted. */
+        char blacklist_item[blacklist_item_len];
+        snprintf(blacklist_item, blacklist_item_len, "%s%s%s",
+                 db->schema->name, ":", table_node->name);
+
+        if (!sset_contains(&tables_blacklist, blacklist_item)) {
+            HMAP_FOR_EACH (row, hmap_node, &table->rows) {
+                ovsdb_txn_row_delete(txn, row);
+            }
         }
     }
 }
@@ -293,7 +333,17 @@ send_monitor_requests(struct shash *all_dbs)
 
                 for (int j = 0; j < n; j++) {
                     struct ovsdb_table_schema *table = nodes[j]->data;
-                    add_monitored_table(table, monitor_request);
+                    size_t blacklist_item_len = strlen(db_name) +
+                                                strlen(table->name) + 2;
+                    char blacklist_item[blacklist_item_len];
+
+                    snprintf(blacklist_item, blacklist_item_len, "%s%s%s",
+                             db_name, ":", table->name);
+
+                    /* Check if table is not blacklisted. */
+                    if (!sset_contains(&tables_blacklist, blacklist_item)) {
+                        add_monitored_table(table, monitor_request);
+                    }
                 }
                 free(nodes);
 
diff --git a/ovsdb/replication.h b/ovsdb/replication.h
index f9b7d63..74acdba 100644
--- a/ovsdb/replication.h
+++ b/ovsdb/replication.h
@@ -32,6 +32,7 @@ struct db {
 
 void replication_run(struct shash *dbs);
 void set_remote_ovsdb_server(const char *remote_server);
+void set_tables_blacklist(const char *blacklist);
 void disconnect_remote_server(void);
 const struct db *find_db(const struct shash *all_dbs, const char *db_name);
 void replication_usage(void);
diff --git a/tests/automake.mk b/tests/automake.mk
index ef0a2f6..b193039 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -75,6 +75,7 @@ TESTSUITE_AT = \
 	tests/ovsdb-execution.at \
 	tests/ovsdb-trigger.at \
 	tests/ovsdb-tool.at \
+	tests/ovsdb-replication.at \
 	tests/ovsdb-server.at \
 	tests/ovsdb-monitor.at \
 	tests/ovsdb-idl.at \
diff --git a/tests/ovsdb-replication.at b/tests/ovsdb-replication.at
new file mode 100644
index 0000000..bd96ae7
--- /dev/null
+++ b/tests/ovsdb-replication.at
@@ -0,0 +1,174 @@
+AT_BANNER([OVSDB -- replication])
+
+m4_divert_push([PREPARE_TESTS])
+[
+replication_schema () {
+    cat <<'EOF'
+    {"name": "mydb",
+     "tables": {
+       "a": {
+         "columns": {
+           "number": {"type": "integer"},
+           "name": {"type": "string"}},
+         "indexes": [["number"]]},
+       "b": {
+         "columns": {
+           "number": {"type": "integer"},
+           "name": {"type": "string"}},
+         "indexes": [["number"]]}}
+    }
+EOF
+}
+]
+m4_divert_pop([PREPARE_TESTS])
+
+m4_define([REPLICATION_EXAMPLES], [
+
+OVSDB_CHECK_REPLICATION([insert monitored table, insert excluded table],
+  [replication_schema],
+  [[[["mydb",
+      {"op": "insert",
+       "table": "a",
+       "row": {"number": 0, "name": "zero"}}]]],
+  [[["mydb",
+      {"op": "insert",
+       "table": "b",
+       "row": {"number": 1, "name": "one"}}]]]],
+  [[7,9c7,8
+< _uuid                                name number
+< ------------------------------------ ---- ------
+< <0> one  1     @&t@
+---
+> _uuid name number
+> ----- ---- ------]]
+)
+
+OVSDB_CHECK_REPLICATION([insert monitored table, update excluded table],
+  [replication_schema],
+  [[[["mydb",
+      {"op": "insert",
+       "table": "a",
+       "row": {"number": 0, "name": "zero"}}]]],
+  [[["mydb",
+      {"op": "insert",
+       "table": "b",
+       "row": {"number": 1, "name": "one"}}]]],
+  [[["mydb",
+      {"op": "update",
+       "table": "b",
+       "where":[["name","==","one"]],
+       "row": {"number": 2, "name": "two"}}]]]],
+  [[7,9c7,8
+< _uuid                                name number
+< ------------------------------------ ---- ------
+< <0> two  2     @&t@
+---
+> _uuid name number
+> ----- ---- ------]]
+)
+
+OVSDB_CHECK_REPLICATION([update monitored table, insert excluded table],
+  [replication_schema],
+  [[[["mydb",
+      {"op": "insert",
+       "table": "a",
+       "row": {"number": 0, "name": "zero"}}]]],
+  [[["mydb",
+      {"op": "update",
+       "table": "a",
+       "where":[["name","==","zero"]],
+       "row": {"number": 1, "name": "one"}}]]],
+  [[["mydb",
+      {"op": "insert",
+       "table": "b",
+       "row": {"number": 2, "name": "two"}}]]]],
+  [[7,9c7,8
+< _uuid                                name number
+< ------------------------------------ ---- ------
+< <0> two  2     @&t@
+---
+> _uuid name number
+> ----- ---- ------]]
+)
+
+OVSDB_CHECK_REPLICATION([update monitored table, update excluded table],
+  [replication_schema],
+  [[[["mydb",
+      {"op": "insert",
+       "table": "a",
+       "row": {"number": 0, "name": "zero"}}]]],
+  [[["mydb",
+      {"op": "update",
+       "table": "a",
+       "where":[["name","==","zero"]],
+       "row": {"number": 1, "name": "one"}}]]],
+  [[["mydb",
+      {"op": "insert",
+       "table": "b",
+       "row": {"number": 2, "name": "two"}}]]],
+  [[["mydb",
+      {"op": "update",
+       "table": "b",
+       "where":[["name","==","two"]],
+       "row": {"number": 3, "name": "three"}}]]]],
+  [[7,9c7,8
+< _uuid                                name  number
+< ------------------------------------ ----- ------
+< <0> three 3     @&t@
+---
+> _uuid name number
+> ----- ---- ------]]
+)
+
+OVSDB_CHECK_REPLICATION([delete monitored table, insert excluded table],
+  [replication_schema],
+  [[[["mydb",
+      {"op": "insert",
+       "table": "a",
+       "row": {"number": 0, "name": "zero"}}]]],
+  [[["mydb",
+      {"op": "delete",
+       "table": "a",
+       "where":[["name","==","zero"]]}]]],
+  [[["mydb",
+      {"op": "insert",
+       "table": "b",
+       "row": {"number": 1, "name": "one"}}]]]],
+  [[6,8c6,7
+< _uuid                                name number
+< ------------------------------------ ---- ------
+< <0> one  1     @&t@
+---
+> _uuid name number
+> ----- ---- ------]]
+)
+
+OVSDB_CHECK_REPLICATION([delete monitored table, update excluded table],
+  [replication_schema],
+  [[[["mydb",
+      {"op": "insert",
+       "table": "a",
+       "row": {"number": 0, "name": "zero"}}]]],
+  [[["mydb",
+      {"op": "delete",
+       "table": "a",
+       "where":[["name","==","zero"]]}]]],
+  [[["mydb",
+      {"op": "insert",
+       "table": "b",
+       "row": {"number": 1, "name": "one"}}]]],
+  [[["mydb",
+      {"op": "update",
+       "table": "b",
+       "where":[["name","==","one"]],
+       "row": {"number": 2, "name": "two"}}]]]],
+  [[6,8c6,7
+< _uuid                                name number
+< ------------------------------------ ---- ------
+< <0> two  2     @&t@
+---
+> _uuid name number
+> ----- ---- ------]]
+)
+
+])
diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
index 81209af..c7f1ba2 100644
--- a/tests/ovsdb-server.at
+++ b/tests/ovsdb-server.at
@@ -1014,3 +1014,59 @@ m4_define([OVSDB_CHECK_EXECUTION],
    AT_CLEANUP])
 
 EXECUTION_EXAMPLES
+
+AT_BANNER([OVSDB -- ovsdb-server replication table-exclusion (TCP IPv4 sockets)])
+
+# OVSDB_CHECK_REPLICATION(TITLE, SCHEMA, TRANSACTIONS, OUTPUT, [KEYWORDS])
+#
+# Creates two databases with the given SCHEMA, and starts an
+# ovsdb-server on each database.
+# Runs each of the TRANSACTIONS (which should be a quoted list of
+# quoted strings) against one of the servers with ovsdb-client one at a
+# time. The server replicates its database to the other ovsdb-server.
+#
+# Checks that the difference between the dump of the databases is
+# OUTPUT, but UUIDs in the output are replaced by markers of the form
+# <N> where N is a number.  The first unique UUID is replaced by <0>,
+# the next by <1>, and so on.
+# If a given UUID appears more than once it is always replaced by the
+# same marker.
+#
+# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
+m4_define([OVSDB_CHECK_REPLICATION],
+   [AT_SETUP([$1])
+   AT_KEYWORDS([ovsdb server tcp replication table-exclusion])
+   $2 > schema
+   AT_CHECK([ovsdb-tool create db1 schema], [0], [stdout], [ignore])
+   AT_CHECK([ovsdb-tool create db2 schema], [0], [stdout], [ignore])
+
+   AT_CHECK([ovsdb-server --detach --no-chdir --log-file=ovsdb-server1.log --pidfile="`pwd`"/pid --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl db1], [0], [ignore], [ignore])
+   PARSE_LISTENING_PORT([ovsdb-server1.log], [TCP_PORT1])
+
+   AT_CHECK([ovsdb-server --detach --no-chdir --log-file=ovsdb-server2.log --pidfile="`pwd`"/pid2 --remote=ptcp:0:127.0.0.1 --unixctl="`pwd`"/unixctl2 --sync-from=tcp:127.0.0.1:$TCP_PORT1 --sync-exclude-tables=mydb:b db2], [0], [ignore], [ignore])
+   PARSE_LISTENING_PORT([ovsdb-server2.log], [TCP_PORT2])
+
+   m4_foreach([txn], [$3],
+     [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT1 'txn'; sleep 2], [0], [stdout], [ignore],
+     [test ! -e pid || kill `cat pid`; test ! -e pid2 || kill `cat pid2`])
+   ])
+
+   AT_CHECK([ovsdb-client dump tcp:127.0.0.1:$TCP_PORT1], [0], [stdout], [ignore],
+     [test ! -e pid || kill `cat pid`; test ! -e pid2 || kill `cat pid2`])
+   cat stdout >> dump1
+   AT_CHECK([ovsdb-client dump tcp:127.0.0.1:$TCP_PORT2], [0], [stdout], [ignore],
+     [test ! -e pid || kill `cat pid`; test ! -e pid2 || kill `cat pid2`])
+   cat stdout >> dump2
+
+   AT_CHECK([diff dump1 dump2], [1], [stdout], [ignore],
+            [test ! -e pid || kill `cat pid`; test ! -e pid2 || kill `cat pid2`])
+   cat stdout >> output
+
+   AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
+            [test ! -e pid || kill `cat pid`; test ! -e pid2 || kill `cat pid2`])
+
+   OVSDB_SERVER_SHUTDOWN
+   OVSDB_SERVER_SHUTDOWN2
+   AT_CLEANUP])
+
+REPLICATION_EXAMPLES
diff --git a/tests/ovsdb.at b/tests/ovsdb.at
index 3e9918a..f361e0c 100644
--- a/tests/ovsdb.at
+++ b/tests/ovsdb.at
@@ -101,6 +101,7 @@ m4_include([tests/ovsdb-transaction.at])
 m4_include([tests/ovsdb-execution.at])
 m4_include([tests/ovsdb-trigger.at])
 m4_include([tests/ovsdb-tool.at])
+m4_include([tests/ovsdb-replication.at])
 m4_include([tests/ovsdb-server.at])
 m4_include([tests/ovsdb-monitor.at])
 m4_include([tests/ovsdb-idl.at])
-- 
1.9.1



More information about the dev mailing list