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);
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<char*>(key);
p.value = const_cast<char*>(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<string>& relations)
static bool unlink_server_from_objects(SERVER* server, set<string>& relations)
{
bool rval = true;
@ -775,7 +775,7 @@ static bool unlink_server_relations(SERVER* server, set<string>& relations)
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;
@ -783,7 +783,7 @@ static bool link_server_relations(SERVER* server, set<string>& 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<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(),
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<json_t*> 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<string>& relations)
static bool unlink_object_from_servers(const char* target, set<string>& relations)
{
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());
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<string>& relation
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;
@ -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());
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<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))
{
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<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
* @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

View File

@ -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);

View File

@ -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));

View File

@ -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()