Add ReloadConfiguration() function - when called it will read fmd.conf and look for 'export FMS_XXXXX=', and overwrite current environment variable settings in the caller.
This allows split brain prevention parameters to be changed at runtime without a node restart. --- src/osaf/consensus/consensus.cc | 67 +++++++++++++++++++++++++++++++---------- src/osaf/consensus/consensus.h | 20 ++++++++---- src/osaf/consensus/key_value.cc | 41 +++++++++++++------------ 3 files changed, 86 insertions(+), 42 deletions(-) diff --git a/src/osaf/consensus/consensus.cc b/src/osaf/consensus/consensus.cc index 878e3a7..cf307b3 100644 --- a/src/osaf/consensus/consensus.cc +++ b/src/osaf/consensus/consensus.cc @@ -18,6 +18,7 @@ #include <sstream> #include <thread> #include "base/conf.h" +#include "base/config_file_reader.h" #include "base/getenv.h" #include "base/logtrace.h" #include "base/ncssysf_def.h" @@ -234,22 +235,32 @@ std::string Consensus::CurrentActive() const { Consensus::Consensus() { TRACE_ENTER(); + // needed for base::Conf::NodeName() later + base::Conf::InitNodeName(); + + ProcessEnvironmentSettings(); +} + +Consensus::~Consensus() {} + +void Consensus::ProcessEnvironmentSettings() { uint32_t split_brain_enable = base::GetEnv("FMS_SPLIT_BRAIN_PREVENTION", 0); - std::string kv_store_cmd = base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + plugin_path_ = base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); uint32_t use_remote_fencing = base::GetEnv("FMS_USE_REMOTE_FENCING", 0); uint32_t prioritise_partition_size = base::GetEnv("FMS_TAKEOVER_PRIORITISE_PARTITION_SIZE", 1); uint32_t relaxed_node_promotion = base::GetEnv("FMS_RELAXED_NODE_PROMOTION", 0); + config_file_ = base::GetEnv("FMS_CONF_FILE", ""); // if not specified in fmd.conf, // takeover requests are valid for 20 seconds - takeover_valid_time = + takeover_valid_time_ = base::GetEnv("FMS_TAKEOVER_REQUEST_VALID_TIME", 20); // expiration time of takeover request is twice the max wait time - max_takeover_retry = takeover_valid_time / 2; + max_takeover_retry_ = takeover_valid_time_ / 2; - if (split_brain_enable == 1 && kv_store_cmd.empty() == false) { + if (split_brain_enable == 1 && plugin_path_.empty() == false) { use_consensus_ = true; } else { use_consensus_ = false; @@ -259,19 +270,43 @@ Consensus::Consensus() { use_remote_fencing_ = true; } - if (prioritise_partition_size == 1) { - prioritise_partition_size_ = true; + if (prioritise_partition_size == 0) { + prioritise_partition_size_ = false; } if (use_consensus_ == true && relaxed_node_promotion == 1) { relaxed_node_promotion_ = true; } +} - // needed for base::Conf::NodeName() later - base::Conf::InitNodeName(); +bool Consensus::ReloadConfiguration() { + ConfigFileReader reader; + ConfigFileReader::SettingsMap map; + + if (config_file_.empty() == true) { + LOG_ER("config file not defined"); + return false; + } + + map = reader.ParseFile(config_file_); + for (const auto& kv : map) { + if (kv.first.compare(0, kFmsEnvPrefix.size(), kFmsEnvPrefix) != 0) { + // we only care about environment variables beginning with 'FMS' + continue; + } + int rc; + rc = setenv(kv.first.c_str(), kv.second.c_str(), 1); + osafassert(rc == 0); + } + + ProcessEnvironmentSettings(); + + return true; } -Consensus::~Consensus() {} +std::string Consensus::PluginPath() const { + return plugin_path_; +} bool Consensus::FenceNode(const std::string& node) { if (use_remote_fencing_ == true) { @@ -325,7 +360,7 @@ void Consensus::CheckForExistingTakeoverRequest() { // or until the takeover request is gone rc = ReadTakeoverRequest(tokens); while (rc == SA_AIS_OK && - retries < max_takeover_retry) { + retries < max_takeover_retry_) { ++retries; TRACE("Takeover request still present"); std::this_thread::sleep_for(kSleepInterval); @@ -355,12 +390,12 @@ SaAisErrorT Consensus::CreateTakeoverRequest(const std::string& current_owner, SaAisErrorT rc; uint32_t retries = 0; rc = KeyValue::Create(kTakeoverRequestKeyname, takeover_request, - takeover_valid_time); + takeover_valid_time_); while (rc == SA_AIS_ERR_FAILED_OPERATION && retries < kMaxRetry) { ++retries; std::this_thread::sleep_for(kSleepInterval); rc = KeyValue::Create(kTakeoverRequestKeyname, takeover_request, - takeover_valid_time); + takeover_valid_time_); } if (rc == SA_AIS_ERR_EXIST) { @@ -373,7 +408,7 @@ SaAisErrorT Consensus::CreateTakeoverRequest(const std::string& current_owner, // or until the takeover request is gone rc = ReadTakeoverRequest(tokens); while (rc == SA_AIS_OK && - retries < max_takeover_retry) { + retries < max_takeover_retry_) { ++retries; TRACE("Takeover request still present"); std::this_thread::sleep_for(kSleepInterval); @@ -400,7 +435,7 @@ SaAisErrorT Consensus::CreateTakeoverRequest(const std::string& current_owner, // wait up to max_takeover_retry seconds for request to be answered retries = 0; - while (retries < max_takeover_retry) { + while (retries < max_takeover_retry_) { std::vector<std::string> tokens; if (ReadTakeoverRequest(tokens) == SA_AIS_OK) { const std::string state = @@ -462,7 +497,7 @@ SaAisErrorT Consensus::WriteTakeoverResult( // previous value must match rc = KeyValue::Set(kTakeoverRequestKeyname, takeover_result, - takeover_request, takeover_valid_time); + takeover_request, takeover_valid_time_); return rc; } @@ -569,7 +604,7 @@ Consensus::TakeoverState Consensus::HandleTakeoverRequest( .c_str(), 0, 10); - LOG_NO("Other network size: %" PRIu64 ", our network size: %" PRIu64, + TRACE("Other network size: %" PRIu64 ", our network size: %" PRIu64, proposed_cluster_size, cluster_size); const std::string state_str = diff --git a/src/osaf/consensus/consensus.h b/src/osaf/consensus/consensus.h index c408a6f..eb12b2c 100644 --- a/src/osaf/consensus/consensus.h +++ b/src/osaf/consensus/consensus.h @@ -66,6 +66,9 @@ class Consensus { // of connectivity to the KV store bool SelfFence(const std::string& request) const; + bool ReloadConfiguration(); + std::string PluginPath() const; + Consensus(); virtual ~Consensus(); @@ -92,13 +95,17 @@ class Consensus { const std::string& request); private: - bool use_consensus_ = false; - bool use_remote_fencing_ = false; - bool prioritise_partition_size_ = false; - bool relaxed_node_promotion_ = false; - uint32_t takeover_valid_time; - uint32_t max_takeover_retry; + bool use_consensus_{false}; + bool use_remote_fencing_{false}; + bool prioritise_partition_size_{true}; + bool relaxed_node_promotion_{false}; + uint32_t takeover_valid_time_{20}; + uint32_t max_takeover_retry_{0}; + std::string config_file_{}; + std::string plugin_path_{}; + const std::string kTestKeyname = "opensaf_write_test"; + const std::string kFmsEnvPrefix = "FMS"; const std::chrono::milliseconds kSleepInterval = std::chrono::milliseconds(1000); // in ms static constexpr uint32_t kLockTimeout = 0; // lock is persistent by default @@ -125,6 +132,7 @@ class Consensus { bool FenceNode(const std::string& node); void Split(const std::string& str, std::vector<std::string>& tokens) const; + void ProcessEnvironmentSettings(); DELETE_COPY_AND_MOVE_OPERATORS(Consensus); }; diff --git a/src/osaf/consensus/key_value.cc b/src/osaf/consensus/key_value.cc index 73a0e70..692dd3f 100644 --- a/src/osaf/consensus/key_value.cc +++ b/src/osaf/consensus/key_value.cc @@ -17,6 +17,7 @@ #include "base/conf.h" #include "base/getenv.h" #include "base/logtrace.h" +#include "osaf/consensus/consensus.h" int KeyValue::Execute(const std::string& command, std::string& output) { TRACE_ENTER(); @@ -45,8 +46,8 @@ int KeyValue::Execute(const std::string& command, std::string& output) { SaAisErrorT KeyValue::Get(const std::string& key, std::string& value) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " get \"" + key + "\""); int rc = KeyValue::Execute(command, value); TRACE("Read '%s'", value.c_str()); @@ -64,8 +65,8 @@ SaAisErrorT KeyValue::Set(const std::string& key, const std::string& value, const unsigned int timeout) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " set \"" + key + "\" \"" + value + "\" " + std::to_string(timeout)); std::string output; @@ -81,8 +82,8 @@ SaAisErrorT KeyValue::Set(const std::string& key, const std::string& value, SaAisErrorT KeyValue::Set(const std::string& key, const std::string& value, const std::string& prev_value, const unsigned int timeout) { - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " set_if_prev \"" + key + "\" \"" + value + "\" \"" + prev_value + "\" " + std::to_string(timeout)); @@ -100,8 +101,8 @@ SaAisErrorT KeyValue::Create(const std::string& key, const std::string& value, const unsigned int timeout) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " create \"" + key + "\" \"" + value + "\" " + std::to_string(timeout)); std::string output; @@ -121,8 +122,8 @@ SaAisErrorT KeyValue::Create(const std::string& key, const std::string& value, SaAisErrorT KeyValue::Erase(const std::string& key) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " erase \"" + key + "\""); std::string output; int rc = KeyValue::Execute(command, output); @@ -138,8 +139,8 @@ SaAisErrorT KeyValue::Lock(const std::string& owner, const unsigned int timeout) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " lock \"" + owner + "\" " + std::to_string(timeout)); std::string output; @@ -160,8 +161,8 @@ SaAisErrorT KeyValue::Lock(const std::string& owner, SaAisErrorT KeyValue::Unlock(const std::string& owner) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " unlock \"" + owner + "\""); std::string output; int rc = Execute(command, output); @@ -180,8 +181,8 @@ SaAisErrorT KeyValue::Unlock(const std::string& owner) { SaAisErrorT KeyValue::LockOwner(std::string& owner) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " lock_owner"); std::string output; int rc = KeyValue::Execute(command, output); @@ -207,8 +208,8 @@ void WatchKeyFunction(const std::string& key, const ConsensusCallback& callback, const uint32_t user_defined) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " watch \"" + key + "\""); std::string value; uint32_t retries = 0; @@ -234,8 +235,8 @@ void WatchLockFunction(const ConsensusCallback& callback, const uint32_t user_defined) { TRACE_ENTER(); - const std::string kv_store_cmd = - base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + Consensus consensus_service; + const std::string kv_store_cmd = consensus_service.PluginPath(); const std::string command(kv_store_cmd + " watch_lock"); std::string value; uint32_t retries = 0; -- 2.7.4 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel