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
