From 1e1c4abcb7377687b5d6a1c847c55a2b7a12f4c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sat, 22 Apr 2017 10:22:08 +0300 Subject: [PATCH] MXS-1220: Add PUT support for monitors Monitor resources can now be altered with a PUT request. The method allows alterations on all parameters that the maxadmin `alter monitor` command allows. --- server/core/config_runtime.cc | 120 +++++++++++++++++++++----- server/core/maxscale/config_runtime.h | 14 ++- server/core/maxscale/monitor.h | 2 +- server/core/monitor.cc | 4 +- server/core/resource.cc | 18 ++++ 5 files changed, 134 insertions(+), 24 deletions(-) diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index 69c03ca38..9e6170653 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -377,7 +377,7 @@ static void add_monitor_defaults(MXS_MONITOR *monitor) } } -bool runtime_alter_monitor(MXS_MONITOR *monitor, char *key, char *value) +bool runtime_alter_monitor(MXS_MONITOR *monitor, const char *key, const char *value) { spinlock_acquire(&crt_lock); bool valid = false; @@ -450,8 +450,8 @@ bool runtime_alter_monitor(MXS_MONITOR *monitor, char *key, char *value) if (value[0]) { MXS_CONFIG_PARAMETER p = {}; - p.name = key; - p.value = value; + p.name = const_cast(key); + p.value = const_cast(value); monitorAddParameters(monitor, &p); } @@ -760,7 +760,7 @@ static bool server_relation_is_valid(const string& type, const string& value) (type == CN_MONITORS && monitor_find(value.c_str())); } -static bool unlink_server_relations(SERVER* server, set& relations) +static bool unlink_server_from_objects(SERVER* server, set& relations) { bool rval = true; @@ -775,7 +775,7 @@ static bool unlink_server_relations(SERVER* server, set& relations) return rval; } -static bool link_server_relations(SERVER* server, set& relations) +static bool link_server_to_objects(SERVER* server, set& relations) { bool rval = true; @@ -783,7 +783,7 @@ static bool link_server_relations(SERVER* server, set& relations) { if (!runtime_link_server(server, it->c_str())) { - unlink_server_relations(server, relations); + unlink_server_from_objects(server, relations); rval = false; break; } @@ -820,7 +820,7 @@ SERVER* runtime_create_server_from_json(json_t* json) rval = server_find_by_unique_name(name); ss_dassert(rval); - if (!link_server_relations(rval, relations)) + if (!link_server_to_objects(rval, relations)) { runtime_destroy_server(rval); rval = NULL; @@ -831,7 +831,7 @@ SERVER* runtime_create_server_from_json(json_t* json) return rval; } -bool handle_alter_server_relations(SERVER* server, json_t* old_json, json_t* new_json) +bool server_to_object_relations(SERVER* server, json_t* old_json, json_t* new_json) { bool rval = false; set old_relations; @@ -851,8 +851,8 @@ bool handle_alter_server_relations(SERVER* server, json_t* old_json, json_t* new old_relations.begin(), old_relations.end(), std::inserter(added_relations, added_relations.begin())); - if (link_server_relations(server, added_relations) && - unlink_server_relations(server, removed_relations)) + if (link_server_to_objects(server, added_relations) && + unlink_server_from_objects(server, removed_relations)) { rval = true; } @@ -867,7 +867,7 @@ bool runtime_alter_server_from_json(SERVER* server, json_t* new_json) Closer old_json(server_to_json(server, "")); ss_dassert(old_json.get()); - if (handle_alter_server_relations(server, old_json.get(), new_json)) + if (server_to_object_relations(server, old_json.get(), new_json)) { json_t* parameters = json_object_get(new_json, CN_PARAMETERS); json_t* old_parameters = json_object_get(old_json.get(), CN_PARAMETERS);; @@ -907,18 +907,18 @@ static bool monitor_contains_required_fields(json_t* json) (value = json_object_get(json, CN_MODULE)) && json_is_string(value); } -const char* monitor_relation_types[] = +const char* object_relation_types[] = { CN_SERVERS, NULL }; -static bool monitor_relation_is_valid(const string& type, const string& value) +static bool object_relation_is_valid(const string& type, const string& value) { return type == CN_SERVERS && server_find_by_unique_name(value.c_str()); } -static bool unlink_monitor_relations(MXS_MONITOR* monitor, set& relations) +static bool unlink_object_from_servers(const char* target, set& relations) { bool rval = true; @@ -926,7 +926,7 @@ static bool unlink_monitor_relations(MXS_MONITOR* monitor, set& relation { SERVER* server = server_find_by_unique_name(it->c_str()); - if (!server || !runtime_unlink_server(server, monitor->name)) + if (!server || !runtime_unlink_server(server, target)) { rval = false; break; @@ -936,7 +936,7 @@ static bool unlink_monitor_relations(MXS_MONITOR* monitor, set& relation return rval; } -static bool link_monitor_relations(MXS_MONITOR* monitor, set& relations) +static bool link_object_to_servers(const char* target, set& relations) { bool rval = true; @@ -944,9 +944,9 @@ static bool link_monitor_relations(MXS_MONITOR* monitor, set& relations) { SERVER* server = server_find_by_unique_name(it->c_str()); - if (!server || !runtime_link_server(server, monitor->name)) + if (!server || !runtime_link_server(server, target)) { - unlink_server_relations(server, relations); + unlink_server_from_objects(server, relations); rval = false; break; } @@ -966,13 +966,13 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json) set relations; - if (extract_relations(json, relations, monitor_relation_types, monitor_relation_is_valid) && + if (extract_relations(json, relations, object_relation_types, object_relation_is_valid) && runtime_create_monitor(name, module)) { rval = monitor_find(name); ss_dassert(rval); - if (!link_monitor_relations(rval, relations)) + if (!link_object_to_servers(rval->name, relations)) { runtime_destroy_monitor(rval); rval = NULL; @@ -982,3 +982,83 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json) return rval; } + +bool object_to_server_relations(const char* target, json_t* old_json, json_t* new_json) +{ + bool rval = false; + set old_relations; + set new_relations; + + if (extract_relations(old_json, old_relations, object_relation_types, object_relation_is_valid) && + extract_relations(new_json, new_relations, object_relation_types, object_relation_is_valid)) + { + set removed_relations; + set added_relations; + + std::set_difference(old_relations.begin(), old_relations.end(), + new_relations.begin(), new_relations.end(), + std::inserter(removed_relations, removed_relations.begin())); + + std::set_difference(new_relations.begin(), new_relations.end(), + old_relations.begin(), old_relations.end(), + std::inserter(added_relations, added_relations.begin())); + + if (link_object_to_servers(target, added_relations) && + unlink_object_from_servers(target, removed_relations)) + { + rval = true; + } + } + + return rval; +} + +bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json) +{ + bool rval = false; + Closer old_json(monitor_to_json(monitor, "")); + ss_dassert(old_json.get()); + + if (object_to_server_relations(monitor->name, old_json.get(), new_json)) + { + bool changed = false; + json_t* parameters = json_object_get(new_json, CN_PARAMETERS); + json_t* old_parameters = json_object_get(old_json.get(), CN_PARAMETERS);; + ss_dassert(old_parameters); + + if (parameters) + { + rval = true; + const char* key; + json_t* value; + + json_object_foreach(parameters, key, value) + { + json_t* new_val = json_object_get(parameters, key); + json_t* old_val = json_object_get(old_parameters, key); + + if (old_val && new_val && mxs::json_to_string(new_val) == mxs::json_to_string(old_val)) + { + /** No change in values */ + } + else if (runtime_alter_monitor(monitor, key, mxs::json_to_string(value).c_str())) + { + changed = true; + } + else + { + rval = false; + } + } + } + + if (changed) + { + /** A configuration change was made, restart the monitor */ + monitorStop(monitor); + monitorStart(monitor, monitor->parameters); + } + } + + return rval; +} diff --git a/server/core/maxscale/config_runtime.h b/server/core/maxscale/config_runtime.h index 1765a5086..638b86834 100644 --- a/server/core/maxscale/config_runtime.h +++ b/server/core/maxscale/config_runtime.h @@ -118,7 +118,7 @@ bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert * @param value New value * @return True if @c key was one of the supported parameters */ -bool runtime_alter_monitor(MXS_MONITOR *monitor, char *key, char *value); +bool runtime_alter_monitor(MXS_MONITOR *monitor, const char *key, const char *value); /** * @brief Create a new listener for a service @@ -192,7 +192,7 @@ SERVER* runtime_create_server_from_json(json_t* json); * @brief Alter a server using JSON * * @param server Server to alter - * @param new_json JSON definition of the new server + * @param new_json JSON definition of the updated server * * @return True if the server was successfully modified to represent @c new_json */ @@ -207,4 +207,14 @@ bool runtime_alter_server_from_json(SERVER* server, json_t* new_json); */ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json); +/** + * @brief Alter a monitor using JSON + * + * @param monitor Monitor to alter + * @param new_json JSON definition of the updated monitor + * + * @return True if the monitor was successfully modified to represent @c new_json + */ +bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json); + MXS_END_DECLS diff --git a/server/core/maxscale/monitor.h b/server/core/maxscale/monitor.h index d71f88411..f74e84b14 100644 --- a/server/core/maxscale/monitor.h +++ b/server/core/maxscale/monitor.h @@ -58,7 +58,7 @@ RESULTSET *monitorGetList(); bool monitorAddServer(MXS_MONITOR *mon, SERVER *server); void monitorRemoveServer(MXS_MONITOR *mon, SERVER *server); -void monitorAddUser(MXS_MONITOR *, char *, char *); +void monitorAddUser(MXS_MONITOR *, const char *, const char *); void monitorAddParameters(MXS_MONITOR *monitor, MXS_CONFIG_PARAMETER *params); bool monitorRemoveParameter(MXS_MONITOR *monitor, const char *key); diff --git a/server/core/monitor.cc b/server/core/monitor.cc index 5a1d30469..bd8ff70da 100644 --- a/server/core/monitor.cc +++ b/server/core/monitor.cc @@ -393,7 +393,7 @@ void monitorRemoveServer(MXS_MONITOR *mon, SERVER *server) * @param passwd The default password associated to the default user. */ void -monitorAddUser(MXS_MONITOR *mon, char *user, char *passwd) +monitorAddUser(MXS_MONITOR *mon, const char *user, const char *passwd) { if (user != mon->user) { @@ -1535,6 +1535,8 @@ json_t* monitor_parameters_to_json(const MXS_MONITOR* monitor) { json_t* rval = json_object(); + json_object_set_new(rval, CN_USER, json_string(monitor->user)); + json_object_set_new(rval, CN_PASSWORD, json_string(monitor->password)); json_object_set_new(rval, CN_MONITOR_INTERVAL, json_integer(monitor->interval)); json_object_set_new(rval, CN_BACKEND_CONNECT_TIMEOUT, json_integer(monitor->connect_timeout)); json_object_set_new(rval, CN_BACKEND_READ_TIMEOUT, json_integer(monitor->read_timeout)); diff --git a/server/core/resource.cc b/server/core/resource.cc index b02009ff2..93614e327 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -158,6 +158,23 @@ HttpResponse cb_create_monitor(const HttpRequest& request) return HttpResponse(MHD_HTTP_BAD_REQUEST); } +HttpResponse cb_alter_monitor(const HttpRequest& request) +{ + json_t* json = request.get_json(); + + if (json) + { + MXS_MONITOR* monitor = monitor_find(request.uri_part(1).c_str()); + + if (monitor && runtime_alter_monitor_from_json(monitor, json)) + { + return HttpResponse(MHD_HTTP_OK, monitor_to_json(monitor, request.host())); + } + } + + return HttpResponse(MHD_HTTP_BAD_REQUEST); +} + HttpResponse cb_all_servers(const HttpRequest& request) { return HttpResponse(MHD_HTTP_OK, server_list_to_json(request.host())); @@ -334,6 +351,7 @@ public: m_post.push_back(SResource(new Resource(cb_create_monitor, 1, "monitors"))); m_put.push_back(SResource(new Resource(cb_alter_server, 2, "servers", ":server"))); + m_put.push_back(SResource(new Resource(cb_alter_monitor, 2, "monitors", ":monitor"))); } ~RootResource()