diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index 4095a4e6e..66978160c 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -665,6 +665,72 @@ bool runtime_destroy_monitor(MXS_MONITOR *monitor) return rval; } +static bool extract_relations(json_t* json, set& relations, + const char** relation_types, + bool (*relation_check)(const string&, const string&)) +{ + bool rval = true; + json_t* rel; + + if ((rel = json_object_get(json, "relationships"))) + { + for (int i = 0; relation_types[i]; i++) + { + json_t* arr = json_object_get(rel, relation_types[i]); + + if (arr) + { + size_t size = json_array_size(arr); + + for (size_t j = 0; j < size; j++) + { + json_t* t = json_array_get(arr, j); + + if (json_is_string(t)) + { + string value = json_string_value(t); + + // Remove the link part + size_t pos = value.find_last_of("/"); + if (pos != string::npos) + { + value.erase(0, pos + 1); + } + + if (relation_check(relation_types[i], value)) + { + relations.insert(value); + } + else + { + rval = false; + } + } + else + { + rval = false; + } + } + } + } + } + + return rval; +} + +static inline const char* string_or_null(json_t* json, const char* name) +{ + const char* rval = NULL; + json_t* value = json_object_get(json, name); + + if (value && json_is_string(value)) + { + rval = json_string_value(value); + } + + return rval; +} + static bool server_contains_required_fields(json_t* json) { json_t* value; @@ -681,7 +747,7 @@ const char* server_relation_types[] = NULL }; -static bool server_relation_is_valid(string type, string value) +static bool server_relation_is_valid(const string& type, const string& value) { return (type == "services" && service_find(value.c_str())) || (type == "monitors" && monitor_find(value.c_str())); @@ -719,70 +785,6 @@ static bool link_server_relations(SERVER* server, set& relations) return rval; } -static bool extract_relations(json_t* json, set& relations) -{ - bool rval = true; - json_t* rel; - - if ((rel = json_object_get(json, "relationships"))) - { - for (int i = 0; server_relation_types[i]; i++) - { - json_t* arr = json_object_get(rel, server_relation_types[i]); - - if (arr) - { - size_t size = json_array_size(arr); - - for (size_t j = 0; j < size; j++) - { - json_t* t = json_array_get(arr, j); - - if (json_is_string(t)) - { - string value = json_string_value(t); - - // Remove the link part - size_t pos = value.find_last_of("/"); - if (pos != string::npos) - { - value.erase(0, pos + 1); - } - - if (server_relation_is_valid(server_relation_types[i], value)) - { - relations.insert(value); - } - else - { - rval = false; - } - } - else - { - rval = false; - } - } - } - } - } - - return rval; -} - -static inline const char* string_or_null(json_t* json, const char* name) -{ - const char* rval = NULL; - json_t* value = json_object_get(json, name); - - if (value && json_is_string(value)) - { - rval = json_string_value(value); - } - - return rval; -} - SERVER* runtime_create_server_from_json(json_t* json) { SERVER* rval = NULL; @@ -805,7 +807,7 @@ SERVER* runtime_create_server_from_json(json_t* json) set relations; - if (extract_relations(json, relations) && + if (extract_relations(json, relations, server_relation_types, server_relation_is_valid) && runtime_create_server(name, address, port, protocol, authenticator, authenticator_options)) { rval = server_find_by_unique_name(name); @@ -821,3 +823,87 @@ SERVER* runtime_create_server_from_json(json_t* json) return rval; } + +static bool monitor_contains_required_fields(json_t* json) +{ + json_t* value; + + return (value = json_object_get(json, "name")) && json_is_string(value) && + (value = json_object_get(json, "module")) && json_is_string(value); +} + +const char* monitor_relation_types[] = +{ + "servers", + NULL +}; + +static bool monitor_relation_is_valid(const string& type, const string& value) +{ + return type == "servers" && server_find_by_unique_name(value.c_str()); +} + +static bool unlink_monitor_relations(MXS_MONITOR* monitor, set& relations) +{ + bool rval = true; + + for (set::iterator it = relations.begin(); it != relations.end(); it++) + { + SERVER* server = server_find_by_unique_name(it->c_str()); + + if (!server || !runtime_unlink_server(server, monitor->name)) + { + rval = false; + break; + } + } + + return rval; +} + +static bool link_monitor_relations(MXS_MONITOR* monitor, set& relations) +{ + bool rval = true; + + for (set::iterator it = relations.begin(); it != relations.end(); it++) + { + SERVER* server = server_find_by_unique_name(it->c_str()); + + if (!server || !runtime_link_server(server, monitor->name)) + { + unlink_server_relations(server, relations); + rval = false; + break; + } + } + + return rval; +} + +MXS_MONITOR* runtime_create_monitor_from_json(json_t* json) +{ + MXS_MONITOR* rval = NULL; + + if (monitor_contains_required_fields(json)) + { + const char* name = json_string_value(json_object_get(json, "name")); + const char* module = json_string_value(json_object_get(json, "module")); + + set relations; + + if (extract_relations(json, relations, monitor_relation_types, monitor_relation_is_valid) && + runtime_create_monitor(name, module)) + { + rval = monitor_find(name); + ss_dassert(rval); + + if (!link_monitor_relations(rval, relations)) + { + runtime_destroy_monitor(rval); + rval = NULL; + } + } + } + + return rval; +} diff --git a/server/core/maxscale/config_runtime.h b/server/core/maxscale/config_runtime.h index 3940668c8..2c023a9f2 100644 --- a/server/core/maxscale/config_runtime.h +++ b/server/core/maxscale/config_runtime.h @@ -188,4 +188,13 @@ bool runtime_destroy_monitor(MXS_MONITOR *monitor); */ SERVER* runtime_create_server_from_json(json_t* json); +/** + * @brief Create a new monitor from JSON + * + * @param json JSON defining the monitor + * + * @return Created monitor or NULL on error + */ +MXS_MONITOR* runtime_create_monitor_from_json(json_t* json); + MXS_END_DECLS diff --git a/server/core/monitor.cc b/server/core/monitor.cc index da0d2c210..de6763667 100644 --- a/server/core/monitor.cc +++ b/server/core/monitor.cc @@ -1544,6 +1544,7 @@ json_t* monitor_to_json(const MXS_MONITOR* monitor, const char* host) json_t* rval = json_object(); json_object_set_new(rval, "name", json_string(monitor->name)); + json_object_set_new(rval, "module", json_string(monitor->module_name)); json_object_set_new(rval, "state", json_string(monitor_state_to_string(monitor->state))); json_object_set_new(rval, "monitor_interval", json_integer(monitor->interval)); diff --git a/server/core/resource.cc b/server/core/resource.cc index 64b719a85..54e38152c 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -120,6 +120,23 @@ HttpResponse cb_create_server(HttpRequest& request) return HttpResponse(MHD_HTTP_INTERNAL_SERVER_ERROR); } +HttpResponse cb_create_monitor(HttpRequest& request) +{ + json_t* json = request.get_json(); + + if (json) + { + MXS_MONITOR* monitor = runtime_create_monitor_from_json(json); + + if (monitor) + { + return HttpResponse(MHD_HTTP_OK, monitor_to_json(monitor, request.host())); + } + } + + return HttpResponse(MHD_HTTP_INTERNAL_SERVER_ERROR); +} + HttpResponse cb_all_servers(HttpRequest& request) { return HttpResponse(MHD_HTTP_OK, server_list_to_json(request.host())); @@ -283,6 +300,7 @@ public: m_post.push_back(SResource(new Resource(cb_flush, 3, "maxscale", "logs", "flush"))); m_post.push_back(SResource(new Resource(cb_create_server, 1, "servers"))); + m_post.push_back(SResource(new Resource(cb_create_monitor, 1, "monitors"))); } ~RootResource()