diff mbox series

[ovs-dev,v2] ovsdb-idl : Add APIs to query if a table and a column is present or not.

Message ID 20210820030812.853368-1-numans@ovn.org
State Superseded
Headers show
Series [ovs-dev,v2] ovsdb-idl : Add APIs to query if a table and a column is present or not. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Numan Siddique Aug. 20, 2021, 3:08 a.m. UTC
From: Numan Siddique <nusiddiq@redhat.com>

This patch adds 2 new APIs in the ovsdb-idl client library
 - ovsdb_idl_has_table() and ovsdb_idl_has_column_in_table() to
query if a table and a column is present in the IDL or not.  This
is required for scenarios where the server schema is old and
missing a table or column and the client (built with a new schema
version) does a transaction with the missing table or column.  This
results in a continuous loop of transaction failures.

OVN would require the API - ovsdb_idl_has_table() to address this issue
when an old ovsdb-server is used (OVS 2.11) which has the 'datapath'
table missing.  A recent commit in OVN creates a 'datapath' row
in the local ovsdb-server.  ovsdb_idl_has_column_in_table() would be
useful to have.

Related issue: https://bugzilla.redhat.com/show_bug.cgi?id=1992705
Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
---
 lib/ovsdb-idl.c    | 25 ++++++++++++++++++
 lib/ovsdb-idl.h    |  4 +++
 tests/ovsdb-idl.at | 17 +++++++++++++
 tests/test-ovsdb.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+)
diff mbox series

Patch

diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 2198c69c6..c5795fb7f 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -4256,3 +4256,28 @@  ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *loop)
 
     return retval;
 }
+
+bool
+ovsdb_idl_has_table(struct ovsdb_idl *idl, const char *table_name)
+{
+    struct ovsdb_idl_table *table = shash_find_data(&idl->table_by_name,
+                                                    table_name);
+    return table ? true: false;
+}
+
+bool
+ovsdb_idl_has_column_in_table(struct ovsdb_idl *idl, const char *table_name,
+                              const char *column_name)
+{
+    struct ovsdb_idl_table *table = shash_find_data(&idl->table_by_name,
+                                                    table_name);
+    if (!table) {
+        return false;
+    }
+
+    if (shash_find_data(&table->columns, column_name)) {
+        return true;
+    }
+
+    return false;
+}
diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
index d93483245..216db4c6d 100644
--- a/lib/ovsdb-idl.h
+++ b/lib/ovsdb-idl.h
@@ -474,6 +474,10 @@  void ovsdb_idl_cursor_next_eq(struct ovsdb_idl_cursor *);
 
 struct ovsdb_idl_row *ovsdb_idl_cursor_data(struct ovsdb_idl_cursor *);
 
+bool ovsdb_idl_has_table(struct ovsdb_idl *idl, const char *table_name);
+bool ovsdb_idl_has_column_in_table(struct ovsdb_idl *idl,
+                                   const char *table_name,
+                                   const char *column_name);
 #ifdef __cplusplus
 }
 #endif
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index 1386f1377..c1464095d 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -2372,3 +2372,20 @@  OVSDB_CHECK_CLUSTER_IDL([simple idl, initially empty, force reconnect],
 [],
 [],
 reconnect.*waiting .* seconds before reconnect)
+
+AT_SETUP([idl table and column presence check])
+AT_KEYWORDS([ovsdb server idl table column check])
+AT_CHECK([ovsdb_start_idltest])
+
+AT_CHECK([test-ovsdb -vconsole:off -t10 idl-table-column-check unix:socket simple5 foo bar simple5:irefmap simple5:foo foo:foocol],
+          [0], [dnl
+table simple5 is present
+table foo is not present
+table bar is not present
+column irefmap in table simple5 is present
+column foo in table simple5 is not present
+table foo is not present
+])
+
+OVSDB_SERVER_SHUTDOWN
+AT_CLEANUP
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index daa55dab7..6b94f7fb5 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -3268,6 +3268,67 @@  do_idl_compound_index(struct ovs_cmdl_context *ctx)
     printf("%03d: done\n", step);
 }
 
+static void
+do_idl_table_column_check(struct ovs_cmdl_context *ctx)
+{
+    struct jsonrpc *rpc;
+    struct ovsdb_idl *idl;
+    unsigned int seqno = 0;
+    int error;
+    int i;
+
+    if (ctx->argc < 3) {
+        exit(1);
+    }
+
+    idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, true, true);
+    ovsdb_idl_set_leader_only(idl, false);
+    struct stream *stream;
+
+    error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream,
+                              DSCP_DEFAULT), -1, &stream);
+    if (error) {
+        ovs_fatal(error, "failed to connect to \"%s\"", ctx->argv[1]);
+    }
+    rpc = jsonrpc_open(stream);
+
+    /* Wait for update. */
+    for (;;) {
+        ovsdb_idl_run(idl);
+        ovsdb_idl_check_consistency(idl);
+        if (ovsdb_idl_get_seqno(idl) != seqno) {
+            break;
+        }
+        jsonrpc_run(rpc);
+
+        ovsdb_idl_wait(idl);
+        jsonrpc_wait(rpc);
+        poll_block();
+    }
+
+    for (i = 2; i < ctx->argc; i++) {
+        char *save_ptr2 = NULL;
+        char *table_name = strtok_r(ctx->argv[i], ":", &save_ptr2);
+        char *column_name = strtok_r(NULL, ":", &save_ptr2);
+
+        bool table_present = ovsdb_idl_has_table(idl, table_name) ;
+        if (!table_present || !column_name) {
+            printf("table %s %s present\n", table_name,
+                   table_present ? "is" : "is not");
+        }
+        if (table_present && column_name) {
+            printf("column %s in table %s %s present\n", column_name,
+                   table_name,
+                   ovsdb_idl_has_column_in_table(idl, table_name,
+                                                 column_name) ?
+                   "is" : "is not");
+        }
+    }
+
+    jsonrpc_close(rpc);
+    ovsdb_idl_destroy(idl);
+}
+
 static struct ovs_cmdl_command all_commands[] = {
     { "log-io", NULL, 2, INT_MAX, do_log_io, OVS_RO },
     { "default-atoms", NULL, 0, 0, do_default_atoms, OVS_RO },
@@ -3306,6 +3367,8 @@  static struct ovs_cmdl_command all_commands[] = {
         do_idl_partial_update_map_column, OVS_RO },
     { "idl-partial-update-set-column", NULL, 1, INT_MAX,
         do_idl_partial_update_set_column, OVS_RO },
+    { "idl-table-column-check", NULL, 1, INT_MAX,
+        do_idl_table_column_check, OVS_RO },
     { "help", NULL, 0, INT_MAX, do_help, OVS_RO },
     { NULL, NULL, 0, 0, NULL, OVS_RO },
 };