MXS-2271 Monitor modifications always go through Monitor::configure()

Previously, runtime monitor modifications could directly alter monitor fields,
which could leave the text-form parameters and reality out-of-sync. Also,
the configure-function was not called for the entire monitor-object, only the
module-implementation.

Now, all modifications go through the overridden configure-function, which calls the
base-class function. As most configuration changes are given in text-form, this
removes the need for specific setters. The only exceptions are the server add/remove
operations, which must modify the text-form serverlist.
This commit is contained in:
Esa Korhonen
2019-01-29 15:34:05 +02:00
parent 703f65700a
commit 1858fe9127
13 changed files with 192 additions and 164 deletions

View File

@ -131,6 +131,78 @@ static std::pair<bool, MXS_CONFIG_PARAMETER> load_defaults(const char* name,
return {rval, params};
}
bool runtime_add_server(Monitor* mon, Server* server)
{
using std::string;
mxb_assert(mon && server);
bool rval = false;
if (monitor_server_in_use(server))
{
MXS_ERROR("Server '%s' is already monitored.", server->name());
}
else
{
// To keep monitor modifications straightforward, all changes should go through the same
// alter_monitor function. As the function accepts key-value combinations (so that they are easily
// serialized), construct the value here.
string serverlist = mon->parameters.get_string(CN_SERVERS);
if (serverlist.empty())
{
// Unusual.
serverlist += server->name();
}
else
{
serverlist += string(", ") + server->name();
}
rval = runtime_alter_monitor(mon, CN_SERVERS, serverlist.c_str());
}
return rval;
}
bool runtime_remove_server(Monitor* mon, Server* server)
{
using std::string;
mxb_assert(mon && server);
bool rval = false;
if (monitor_server_in_use(server) != mon)
{
MXS_ERROR("Server '%s' is not monitored by '%s'.", server->name(), mon->m_name);
}
else
{
// Construct the new list. The removed value could be anywhere.
string serverlist = mon->parameters.get_string(CN_SERVERS);
auto names = config_break_list_string(serverlist);
bool found = false;
for (auto iter = names.begin(); iter != names.end(); ++iter)
{
if (*iter == server->name())
{
found = true;
names.erase(iter);
break;
}
}
if (found)
{
// Rebuild the string.
string new_list;
string separator;
for (auto name : names)
{
new_list += separator + name;
separator = ", ";
}
rval = runtime_alter_monitor(mon, CN_SERVERS, new_list.c_str());
}
}
return rval;
}
bool runtime_link_server(Server* server, const char* target)
{
std::lock_guard<std::mutex> guard(crt_lock);
@ -165,7 +237,7 @@ bool runtime_link_server(Server* server, const char* target)
}
else if (monitor)
{
if (MonitorManager::add_server(monitor, server))
if (runtime_add_server(monitor, server))
{
monitor_serialize(monitor);
rval = true;
@ -213,7 +285,7 @@ bool runtime_unlink_server(Server* server, const char* target)
}
else if (monitor)
{
MonitorManager::remove_server(monitor, server);
runtime_remove_server(monitor, server);
monitor_serialize(monitor);
rval = true;
}
@ -597,86 +669,24 @@ bool do_alter_monitor(Monitor* monitor, const char* key, const char* value)
{
return false;
}
else if (strcmp(key, "servers") == 0)
{
config_runtime_error("Parameter '%s' cannot be altered via this method", key);
return false;
}
std::lock_guard<std::mutex> guard(crt_lock);
monitor->parameters.set(key, value);
bool success = true;
if (strcmp(key, CN_USER) == 0)
{
monitor->set_user(value);
}
else if (strcmp(key, CN_PASSWORD) == 0)
{
monitor->set_password(value);
}
else if (strcmp(key, CN_MONITOR_INTERVAL) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->set_interval(ival);
}
}
else if (strcmp(key, CN_BACKEND_CONNECT_TIMEOUT) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->set_network_timeout(MONITOR_CONNECT_TIMEOUT, ival, CN_BACKEND_CONNECT_TIMEOUT);
}
}
else if (strcmp(key, CN_BACKEND_WRITE_TIMEOUT) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->set_network_timeout(MONITOR_WRITE_TIMEOUT, ival, CN_BACKEND_WRITE_TIMEOUT);
}
}
else if (strcmp(key, CN_BACKEND_READ_TIMEOUT) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->set_network_timeout(MONITOR_READ_TIMEOUT, ival, CN_BACKEND_READ_TIMEOUT);
}
}
else if (strcmp(key, CN_BACKEND_CONNECT_ATTEMPTS) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->set_network_timeout(MONITOR_CONNECT_ATTEMPTS, ival, CN_BACKEND_CONNECT_ATTEMPTS);
}
}
else if (strcmp(key, CN_JOURNAL_MAX_AGE) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->monitor_set_journal_max_age(ival);
}
}
else if (strcmp(key, CN_SCRIPT_TIMEOUT) == 0)
{
if (auto ival = get_positive_int(value))
{
monitor->set_script_timeout(ival);
}
}
else if (strcmp(key, CN_DISK_SPACE_THRESHOLD) == 0)
{
success = monitor->set_disk_space_threshold(value);
}
else
{
// This should be a module specific parameter
mxb_assert(config_param_is_valid(mod->parameters, key, value, NULL));
}
// Backup monitor parameters in case configure fails.
MXS_CONFIG_PARAMETER originals = monitor->parameters;
MXS_CONFIG_PARAMETER modified = monitor->parameters;
modified.set(key, value);
bool success = monitor->configure(&modified);
if (success)
{
MXS_NOTICE("Updated monitor '%s': %s=%s", monitor->m_name, key, value);
}
else
{
// Configure failed, restore original configs. This should not fail.
// TODO: add a flag to monitor which prevents startup if config is wrong.
MXB_AT_DEBUG(bool check =) monitor->configure(&originals);
mxb_assert(check);
}
return success;
}
@ -686,7 +696,7 @@ bool runtime_alter_monitor(Monitor* monitor, const char* key, const char* value)
bool was_running = (monitor->state() == MONITOR_STATE_RUNNING);
if (was_running)
{
monitor_stop(monitor);
MonitorManager::monitor_stop(monitor);
}
bool success = do_alter_monitor(monitor, key, value);
if (success)
@ -695,7 +705,7 @@ bool runtime_alter_monitor(Monitor* monitor, const char* key, const char* value)
}
if (was_running)
{
MonitorManager::monitor_start(monitor, &monitor->parameters);
MonitorManager::monitor_start(monitor);
}
return success;
}
@ -1422,7 +1432,7 @@ bool runtime_destroy_monitor(Monitor* monitor)
if (rval)
{
monitor_stop(monitor);
MonitorManager::monitor_stop(monitor);
while (!monitor->m_servers.empty())
{
@ -2258,7 +2268,7 @@ Monitor* runtime_create_monitor_from_json(json_t* json)
}
else
{
MonitorManager::monitor_start(rval, &rval->parameters);
MonitorManager::monitor_start(rval);
}
}
}
@ -2392,14 +2402,15 @@ bool service_to_filter_relations(Service* service, json_t* old_json, json_t* new
bool runtime_alter_monitor_from_json(Monitor* monitor, json_t* new_json)
{
bool rval = false;
bool success = false;
std::unique_ptr<json_t> old_json(monitor_to_json(monitor, ""));
mxb_assert(old_json.get());
if (is_valid_resource_body(new_json)
&& object_to_server_relations(monitor->m_name, old_json.get(), new_json))
{
rval = true;
success = true;
bool changed = false;
json_t* parameters = mxs_json_pointer(new_json, MXS_JSON_PTR_PARAMETERS);
json_t* old_parameters = mxs_json_pointer(old_json.get(), MXS_JSON_PTR_PARAMETERS);
@ -2409,7 +2420,7 @@ bool runtime_alter_monitor_from_json(Monitor* monitor, json_t* new_json)
if (parameters)
{
bool restart = (monitor->state() != MONITOR_STATE_STOPPED);
monitor_stop(monitor);
MonitorManager::monitor_stop(monitor);
const char* key;
json_t* value;
@ -2428,24 +2439,24 @@ bool runtime_alter_monitor_from_json(Monitor* monitor, json_t* new_json)
}
else
{
rval = false;
success = false;
break;
}
}
if (rval && changed)
if (success && changed)
{
monitor_serialize(monitor);
}
if (restart)
{
MonitorManager::monitor_start(monitor, &monitor->parameters);
MonitorManager::monitor_start(monitor);
}
}
}
return rval;
return success;
}
bool runtime_alter_monitor_relationships_from_json(Monitor* monitor, json_t* json)