After creating the new cluster database write a raft entry that
sets the desired election timer. This allows CMSes to set the
election timer at cluster start and avoid an error-prone
election timer modification process after the cluster is up.

Reported-at: https://bugzilla.redhat.com/1831778

Signed-off-by: Dan Williams <[email protected]>
---
 ovsdb/ovsdb-tool.c | 30 +++++++++++++++++++++++++++++-
 ovsdb/raft.c       |  2 +-
 ovsdb/raft.h       |  8 ++++++++
 3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c
index b8560f850cd08..8d029cef56df6 100644
--- a/ovsdb/ovsdb-tool.c
+++ b/ovsdb/ovsdb-tool.c
@@ -276,10 +276,22 @@ do_create_cluster(struct ovs_cmdl_context *ctx)
     const char *db_file_name = ctx->argv[1];
     const char *src_file_name = ctx->argv[2];
     const char *local = ctx->argv[3];
+    uint64_t election_timer = 0;
 
     struct ovsdb_schema *schema;
     struct json *data;
 
+    if (ctx->argc >= 5) {
+        election_timer = atoll(ctx->argv[4]);
+        /* Election timer smaller than 100ms or bigger than 10min doesn't make
+         * sense. */
+        if (election_timer < 100 || election_timer > 600000) {
+            ovs_fatal(0, "election timer must be between 100 and 600000, "
+                      "in msec.");
+            return;
+        }
+    }
+
     struct ovsdb_error *error = ovsdb_schema_from_file(src_file_name, &schema);
     if (!error) {
         /* It's just a schema file. */
@@ -306,6 +318,21 @@ do_create_cluster(struct ovs_cmdl_context *ctx)
                                           local, snapshot));
     ovsdb_schema_destroy(schema);
     json_destroy(snapshot);
+
+    if (election_timer > 0) {
+        struct ovsdb_log *log = NULL;
+        struct raft *raft = NULL;
+
+        check_ovsdb_error(ovsdb_log_open(db_file_name, RAFT_MAGIC,
+                                         OVSDB_LOG_READ_WRITE, -1, &log));
+        check_ovsdb_error(raft_open(log, &raft));
+        /* Use term=1 since raft_open() triggers leader election and sets
+         * the term to 1. */
+        check_ovsdb_error(raft_write_entry(raft, 1, json_nullable_clone(NULL),
+                                           NULL, json_nullable_clone(NULL),
+                                           election_timer));
+        raft_close(raft);
+    }
 }
 
 static void
@@ -1675,7 +1702,8 @@ do_list_commands(struct ovs_cmdl_context *ctx OVS_UNUSED)
 
 static const struct ovs_cmdl_command all_commands[] = {
     { "create", "[db [schema]]", 0, 2, do_create, OVS_RW },
-    { "create-cluster", "db contents local", 3, 3, do_create_cluster, OVS_RW },
+    { "create-cluster", "db contents local [election timer ms]", 3, 4,
+      do_create_cluster, OVS_RW },
     { "join-cluster", "db name local remote...", 4, INT_MAX, do_join_cluster,
       OVS_RW },
     { "compact", "[db [dst]]", 0, 2, do_compact, OVS_RW },
diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index d2ff643b27379..4e2a508033ce0 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -697,7 +697,7 @@ raft_add_entry(struct raft *raft,
 
 /* Writes a RAFT_REC_ENTRY record for 'term', 'data', 'eid', 'servers',
  * 'election_timer' to * 'raft''s log and returns an error indication. */
-static struct ovsdb_error * OVS_WARN_UNUSED_RESULT
+struct ovsdb_error * OVS_WARN_UNUSED_RESULT
 raft_write_entry(struct raft *raft, uint64_t term, struct json *data,
                  const struct uuid *eid, struct json *servers,
                  uint64_t election_timer)
diff --git a/ovsdb/raft.h b/ovsdb/raft.h
index 99d5307e54684..92b1c7741ed96 100644
--- a/ovsdb/raft.h
+++ b/ovsdb/raft.h
@@ -170,6 +170,14 @@ uint64_t raft_command_get_commit_index(const struct 
raft_command *);
 void raft_command_unref(struct raft_command *);
 void raft_command_wait(const struct raft_command *);
 
+struct ovsdb_error *raft_write_entry(struct raft *raft,
+                                     uint64_t term,
+                                     struct json *data,
+                                     const struct uuid *eid,
+                                     struct json *servers,
+                                     uint64_t election_timer)
+    OVS_WARN_UNUSED_RESULT;
+
 /* Replacing the local log by a snapshot. */
 bool raft_grew_lots(const struct raft *);
 uint64_t raft_get_log_length(const struct raft *);
-- 
2.30.2


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to