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.
This commit is contained in:
Markus Mäkelä
2017-04-22 10:22:08 +03:00
committed by Markus Mäkelä
parent 690d592a94
commit 1e1c4abcb7
5 changed files with 134 additions and 24 deletions

View File

@ -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); spinlock_acquire(&crt_lock);
bool valid = false; bool valid = false;
@ -450,8 +450,8 @@ bool runtime_alter_monitor(MXS_MONITOR *monitor, char *key, char *value)
if (value[0]) if (value[0])
{ {
MXS_CONFIG_PARAMETER p = {}; MXS_CONFIG_PARAMETER p = {};
p.name = key; p.name = const_cast<char*>(key);
p.value = value; p.value = const_cast<char*>(value);
monitorAddParameters(monitor, &p); 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())); (type == CN_MONITORS && monitor_find(value.c_str()));
} }
static bool unlink_server_relations(SERVER* server, set<string>& relations) static bool unlink_server_from_objects(SERVER* server, set<string>& relations)
{ {
bool rval = true; bool rval = true;
@ -775,7 +775,7 @@ static bool unlink_server_relations(SERVER* server, set<string>& relations)
return rval; return rval;
} }
static bool link_server_relations(SERVER* server, set<string>& relations) static bool link_server_to_objects(SERVER* server, set<string>& relations)
{ {
bool rval = true; bool rval = true;
@ -783,7 +783,7 @@ static bool link_server_relations(SERVER* server, set<string>& relations)
{ {
if (!runtime_link_server(server, it->c_str())) if (!runtime_link_server(server, it->c_str()))
{ {
unlink_server_relations(server, relations); unlink_server_from_objects(server, relations);
rval = false; rval = false;
break; break;
} }
@ -820,7 +820,7 @@ SERVER* runtime_create_server_from_json(json_t* json)
rval = server_find_by_unique_name(name); rval = server_find_by_unique_name(name);
ss_dassert(rval); ss_dassert(rval);
if (!link_server_relations(rval, relations)) if (!link_server_to_objects(rval, relations))
{ {
runtime_destroy_server(rval); runtime_destroy_server(rval);
rval = NULL; rval = NULL;
@ -831,7 +831,7 @@ SERVER* runtime_create_server_from_json(json_t* json)
return rval; 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; bool rval = false;
set<string> old_relations; set<string> 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(), old_relations.begin(), old_relations.end(),
std::inserter(added_relations, added_relations.begin())); std::inserter(added_relations, added_relations.begin()));
if (link_server_relations(server, added_relations) && if (link_server_to_objects(server, added_relations) &&
unlink_server_relations(server, removed_relations)) unlink_server_from_objects(server, removed_relations))
{ {
rval = true; rval = true;
} }
@ -867,7 +867,7 @@ bool runtime_alter_server_from_json(SERVER* server, json_t* new_json)
Closer<json_t*> old_json(server_to_json(server, "")); Closer<json_t*> old_json(server_to_json(server, ""));
ss_dassert(old_json.get()); 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* parameters = json_object_get(new_json, CN_PARAMETERS);
json_t* old_parameters = json_object_get(old_json.get(), 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); (value = json_object_get(json, CN_MODULE)) && json_is_string(value);
} }
const char* monitor_relation_types[] = const char* object_relation_types[] =
{ {
CN_SERVERS, CN_SERVERS,
NULL 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()); return type == CN_SERVERS && server_find_by_unique_name(value.c_str());
} }
static bool unlink_monitor_relations(MXS_MONITOR* monitor, set<string>& relations) static bool unlink_object_from_servers(const char* target, set<string>& relations)
{ {
bool rval = true; bool rval = true;
@ -926,7 +926,7 @@ static bool unlink_monitor_relations(MXS_MONITOR* monitor, set<string>& relation
{ {
SERVER* server = server_find_by_unique_name(it->c_str()); 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; rval = false;
break; break;
@ -936,7 +936,7 @@ static bool unlink_monitor_relations(MXS_MONITOR* monitor, set<string>& relation
return rval; return rval;
} }
static bool link_monitor_relations(MXS_MONITOR* monitor, set<string>& relations) static bool link_object_to_servers(const char* target, set<string>& relations)
{ {
bool rval = true; bool rval = true;
@ -944,9 +944,9 @@ static bool link_monitor_relations(MXS_MONITOR* monitor, set<string>& relations)
{ {
SERVER* server = server_find_by_unique_name(it->c_str()); 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; rval = false;
break; break;
} }
@ -966,13 +966,13 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json)
set<string> relations; set<string> 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)) runtime_create_monitor(name, module))
{ {
rval = monitor_find(name); rval = monitor_find(name);
ss_dassert(rval); ss_dassert(rval);
if (!link_monitor_relations(rval, relations)) if (!link_object_to_servers(rval->name, relations))
{ {
runtime_destroy_monitor(rval); runtime_destroy_monitor(rval);
rval = NULL; rval = NULL;
@ -982,3 +982,83 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json)
return rval; return rval;
} }
bool object_to_server_relations(const char* target, json_t* old_json, json_t* new_json)
{
bool rval = false;
set<string> old_relations;
set<string> 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<string> removed_relations;
set<string> 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<json_t*> 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;
}

View File

@ -118,7 +118,7 @@ bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert
* @param value New value * @param value New value
* @return True if @c key was one of the supported parameters * @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 * @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 * @brief Alter a server using JSON
* *
* @param server Server to alter * @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 * @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); 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 MXS_END_DECLS

View File

@ -58,7 +58,7 @@ RESULTSET *monitorGetList();
bool monitorAddServer(MXS_MONITOR *mon, SERVER *server); bool monitorAddServer(MXS_MONITOR *mon, SERVER *server);
void monitorRemoveServer(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); void monitorAddParameters(MXS_MONITOR *monitor, MXS_CONFIG_PARAMETER *params);
bool monitorRemoveParameter(MXS_MONITOR *monitor, const char *key); bool monitorRemoveParameter(MXS_MONITOR *monitor, const char *key);

View File

@ -393,7 +393,7 @@ void monitorRemoveServer(MXS_MONITOR *mon, SERVER *server)
* @param passwd The default password associated to the default user. * @param passwd The default password associated to the default user.
*/ */
void void
monitorAddUser(MXS_MONITOR *mon, char *user, char *passwd) monitorAddUser(MXS_MONITOR *mon, const char *user, const char *passwd)
{ {
if (user != mon->user) if (user != mon->user)
{ {
@ -1535,6 +1535,8 @@ json_t* monitor_parameters_to_json(const MXS_MONITOR* monitor)
{ {
json_t* rval = json_object(); 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_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_CONNECT_TIMEOUT, json_integer(monitor->connect_timeout));
json_object_set_new(rval, CN_BACKEND_READ_TIMEOUT, json_integer(monitor->read_timeout)); json_object_set_new(rval, CN_BACKEND_READ_TIMEOUT, json_integer(monitor->read_timeout));

View File

@ -158,6 +158,23 @@ HttpResponse cb_create_monitor(const HttpRequest& request)
return HttpResponse(MHD_HTTP_BAD_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) HttpResponse cb_all_servers(const HttpRequest& request)
{ {
return HttpResponse(MHD_HTTP_OK, server_list_to_json(request.host())); 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_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_server, 2, "servers", ":server")));
m_put.push_back(SResource(new Resource(cb_alter_monitor, 2, "monitors", ":monitor")));
} }
~RootResource() ~RootResource()