From a384665141fc801edcb456b4b47b7763ad57b564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 5 May 2017 22:21:01 +0300 Subject: [PATCH] MXS-1220: Allow modification of logging options The logging options can now be modified with a PUT request. --- include/maxscale/config.h | 19 ++++ server/core/config_runtime.cc | 157 +++++++++++++++++++------- server/core/log_manager.cc | 12 +- server/core/maxscale/config_runtime.h | 9 ++ server/core/resource.cc | 15 ++- 5 files changed, 167 insertions(+), 45 deletions(-) diff --git a/include/maxscale/config.h b/include/maxscale/config.h index 07d467b5b..5efb52991 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -36,6 +36,25 @@ MXS_BEGIN_DECLS #define MAX_ADMIN_PW_LEN 1024 #define MAX_ADMIN_HOST_LEN 1024 +/** JSON Pointers to key parts of JSON objects */ +#define MXS_JSON_PTR_ID "/data/id" +#define MXS_JSON_PTR_PARAMETERS "/data/attributes/parameters" + +/** Pointers to relation lists */ +#define MXS_JSON_PTR_RELATIONSHIPS_SERVERS "/data/relationships/servers/data" +#define MXS_JSON_PTR_RELATIONSHIPS_SERVICES "/data/relationships/services/data" +#define MXS_JSON_PTR_RELATIONSHIPS_MONITORS "/data/relationships/monitors/data" +#define MXS_JSON_PTR_RELATIONSHIPS_FILTERS "/data/relationships/filters/data" + +/** Server JSON Pointers */ +#define MXS_JSON_PTR_SRV_PORT MXS_JSON_PTR_PARAMETERS "/port" +#define MXS_JSON_PTR_SRV_ADDRESS MXS_JSON_PTR_PARAMETERS "/address" +#define MXS_JSON_PTR_SRV_PROTOCOL MXS_JSON_PTR_PARAMETERS "/protocol" +#define MXS_JSON_PTR_SRV_AUTHENTICATOR MXS_JSON_PTR_PARAMETERS "/authenticator" +#define MXS_JSON_PTR_SRV_AUTHENTICATOR_OPTIONS MXS_JSON_PTR_PARAMETERS "/authenticator_options" + +#define PTR_MON_MODULE "/data/attributes/module" + /** * Common configuration parameters names * diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index d3ad49727..eec8406f8 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -38,25 +38,6 @@ using std::stringstream; using std::set; using mxs::Closer; -/** JSON Pointers to key parts of JSON objects */ -#define PTR_ID "/data/id" -#define PTR_PARAMETERS "/data/attributes/parameters" - -/** Pointers to relation lists */ -static const char PTR_RELATIONSHIPS_SERVERS[] = "/data/relationships/servers/data"; -static const char PTR_RELATIONSHIPS_SERVICES[] = "/data/relationships/services/data"; -static const char PTR_RELATIONSHIPS_MONITORS[] = "/data/relationships/monitors/data"; -static const char PTR_RELATIONSHIPS_FILTERS[] = "/data/relationships/filters/data"; - -/** Server JSON Pointers */ -static const char PTR_SRV_PORT[] = PTR_PARAMETERS "/port"; -static const char PTR_SRV_ADDRESS[] = PTR_PARAMETERS "/address"; -static const char PTR_SRV_PROTOCOL[] = PTR_PARAMETERS "/protocol"; -static const char PTR_SRV_AUTHENTICATOR[] = PTR_PARAMETERS "/authenticator"; -static const char PTR_SRV_AUTHENTICATOR_OPTIONS[] = PTR_PARAMETERS "/authenticator_options"; - -static const char PTR_MON_MODULE[] = "/data/attributes/module"; - static SPINLOCK crt_lock = SPINLOCK_INIT; bool runtime_link_server(SERVER *server, const char *target) @@ -834,9 +815,9 @@ static inline const char* string_or_null(json_t* json, const char* path) static bool server_contains_required_fields(json_t* json) { - json_t* id = mxs_json_pointer(json, PTR_ID); - json_t* port = mxs_json_pointer(json, PTR_SRV_PORT); - json_t* address = mxs_json_pointer(json, PTR_SRV_ADDRESS); + json_t* id = mxs_json_pointer(json, MXS_JSON_PTR_ID); + json_t* port = mxs_json_pointer(json, MXS_JSON_PTR_SRV_PORT); + json_t* address = mxs_json_pointer(json, MXS_JSON_PTR_SRV_ADDRESS); return (id && json_is_string(id) && address && json_is_string(address) && @@ -845,8 +826,8 @@ static bool server_contains_required_fields(json_t* json) const char* server_relation_types[] = { - PTR_RELATIONSHIPS_SERVICES, - PTR_RELATIONSHIPS_MONITORS, + MXS_JSON_PTR_RELATIONSHIPS_SERVICES, + MXS_JSON_PTR_RELATIONSHIPS_MONITORS, NULL }; @@ -894,18 +875,18 @@ SERVER* runtime_create_server_from_json(json_t* json) if (server_contains_required_fields(json)) { - const char* name = json_string_value(mxs_json_pointer(json, PTR_ID)); - const char* address = json_string_value(mxs_json_pointer(json, PTR_SRV_ADDRESS)); + const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID)); + const char* address = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_SRV_ADDRESS)); /** The port needs to be in string format */ char port[200]; // Enough to store any port value - int i = json_integer_value(mxs_json_pointer(json, PTR_SRV_PORT)); + int i = json_integer_value(mxs_json_pointer(json, MXS_JSON_PTR_SRV_PORT)); snprintf(port, sizeof(port), "%d", i); /** Optional parameters */ - const char* protocol = string_or_null(json, PTR_SRV_PROTOCOL); - const char* authenticator = string_or_null(json, PTR_SRV_AUTHENTICATOR); - const char* authenticator_options = string_or_null(json, PTR_SRV_AUTHENTICATOR_OPTIONS); + const char* protocol = string_or_null(json, MXS_JSON_PTR_SRV_PROTOCOL); + const char* authenticator = string_or_null(json, MXS_JSON_PTR_SRV_AUTHENTICATOR); + const char* authenticator_options = string_or_null(json, MXS_JSON_PTR_SRV_AUTHENTICATOR_OPTIONS); set relations; @@ -964,8 +945,8 @@ bool runtime_alter_server_from_json(SERVER* server, json_t* new_json) if (server_to_object_relations(server, old_json.get(), new_json)) { - json_t* parameters = mxs_json_pointer(new_json, PTR_PARAMETERS); - json_t* old_parameters = mxs_json_pointer(old_json.get(), PTR_PARAMETERS); + 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); ss_dassert(old_parameters); @@ -997,7 +978,7 @@ bool runtime_alter_server_from_json(SERVER* server, json_t* new_json) const char* object_relation_types[] = { - PTR_RELATIONSHIPS_SERVERS, + MXS_JSON_PTR_RELATIONSHIPS_SERVERS, NULL }; @@ -1018,7 +999,7 @@ static bool validate_monitor_json(json_t* json) bool rval = false; json_t* value; - if ((value = mxs_json_pointer(json, PTR_ID)) && json_is_string(value) && + if ((value = mxs_json_pointer(json, MXS_JSON_PTR_ID)) && json_is_string(value) && (value = mxs_json_pointer(json, PTR_MON_MODULE)) && json_is_string(value)) { set relations; @@ -1074,7 +1055,7 @@ MXS_MONITOR* runtime_create_monitor_from_json(json_t* json) if (validate_monitor_json(json)) { - const char* name = json_string_value(mxs_json_pointer(json, PTR_ID)); + const char* name = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_ID)); const char* module = json_string_value(mxs_json_pointer(json, PTR_MON_MODULE)); if (runtime_create_monitor(name, module)) @@ -1137,8 +1118,8 @@ bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json) { rval = true; bool changed = false; - json_t* parameters = mxs_json_pointer(new_json, PTR_PARAMETERS); - json_t* old_parameters = mxs_json_pointer(old_json.get(), PTR_PARAMETERS); + 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); ss_dassert(old_parameters); @@ -1201,8 +1182,8 @@ bool runtime_alter_service_from_json(SERVICE* service, json_t* new_json) if (object_to_server_relations(service->name, old_json.get(), new_json)) { bool changed = false; - json_t* parameters = mxs_json_pointer(new_json, PTR_PARAMETERS); - json_t* old_parameters = mxs_json_pointer(old_json.get(), PTR_PARAMETERS); + 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); ss_dassert(old_parameters); @@ -1245,3 +1226,101 @@ bool runtime_alter_service_from_json(SERVICE* service, json_t* new_json) return rval; } + +bool runtime_alter_logs_from_json(json_t* json) +{ + bool rval = false; + json_t* param = mxs_json_pointer(json, MXS_JSON_PTR_PARAMETERS); + + if (param && json_is_object(param)) + { + json_t* value; + rval = true; + + if ((value = mxs_json_pointer(param, "highprecision")) && json_is_boolean(value)) + { + if (json_is_boolean(value)) + { + mxs_log_set_highprecision_enabled(json_boolean_value(value)); + } + else + { + rval = false; + } + } + + if ((value = mxs_json_pointer(param, "maxlog")) && json_is_boolean(value)) + { + if (json_is_boolean(value)) + { + mxs_log_set_maxlog_enabled(json_boolean_value(value)); + } + else + { + rval = false; + } + } + + if ((value = mxs_json_pointer(param, "syslog"))) + { + if (json_is_boolean(value)) + { + mxs_log_set_syslog_enabled(json_boolean_value(value)); + } + else + { + rval = false; + } + } + + if ((param = mxs_json_pointer(param, "throttling")) && json_is_object(param)) + { + int intval; + MXS_LOG_THROTTLING throttle; + mxs_log_get_throttling(&throttle); + + if ((value = mxs_json_pointer(param, "count"))) + { + if (json_is_integer(value) && (intval = json_integer_value(value)) > 0) + { + throttle.count = intval; + } + else + { + rval = false; + } + } + + if ((value = mxs_json_pointer(param, "suppress_ms"))) + { + if (json_is_integer(value) && (intval = json_integer_value(value)) > 0) + { + throttle.suppress_ms = intval; + } + else + { + rval = false; + } + } + + if ((value = mxs_json_pointer(param, "window_ms"))) + { + if (json_is_integer(value) && (intval = json_integer_value(value)) > 0) + { + throttle.window_ms = intval; + } + else + { + rval = false; + } + } + + if (rval) + { + mxs_log_set_throttling(&throttle); + } + } + } + + return rval; +} diff --git a/server/core/log_manager.cc b/server/core/log_manager.cc index b9119769c..5626ec91a 100644 --- a/server/core/log_manager.cc +++ b/server/core/log_manager.cc @@ -3019,17 +3019,19 @@ const char* mxs_strerror(int error) json_t* mxs_logs_to_json(const char* host) { - json_t* attr = json_object(); - json_object_set_new(attr, "highprecision", json_boolean(log_config.do_highprecision)); - json_object_set_new(attr, "maxlog", json_boolean(log_config.do_maxlog)); - json_object_set_new(attr, "syslog", json_boolean(log_config.do_syslog)); + json_t* param = json_object(); + json_object_set_new(param, "highprecision", json_boolean(log_config.do_highprecision)); + json_object_set_new(param, "maxlog", json_boolean(log_config.do_maxlog)); + json_object_set_new(param, "syslog", json_boolean(log_config.do_syslog)); json_t* throttling = json_object(); json_object_set_new(throttling, "count", json_integer(log_config.throttling.count)); json_object_set_new(throttling, "suppress_ms", json_integer(log_config.throttling.suppress_ms)); json_object_set_new(throttling, "window_ms", json_integer(log_config.throttling.window_ms)); + json_object_set_new(param, "throttling", throttling); - json_object_set_new(attr, "throttling", throttling); + json_t* attr = json_object(); + json_object_set_new(attr, CN_PARAMETERS, param); json_t* data = json_object(); json_object_set_new(data, CN_ATTRIBUTES, attr); diff --git a/server/core/maxscale/config_runtime.h b/server/core/maxscale/config_runtime.h index d5473269d..b5600efb2 100644 --- a/server/core/maxscale/config_runtime.h +++ b/server/core/maxscale/config_runtime.h @@ -238,4 +238,13 @@ bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json); */ bool runtime_alter_service_from_json(SERVICE* service, json_t* new_json); +/** + * @brief Alter logging options using JSON + * + * @param json JSON definition of the updated logging options + * + * @return True if the modifications were successful + */ +bool runtime_alter_logs_from_json(json_t* json); + MXS_END_DECLS diff --git a/server/core/resource.cc b/server/core/resource.cc index 70e8207fa..fd043d7cc 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -234,6 +234,18 @@ HttpResponse cb_alter_service(const HttpRequest& request) return HttpResponse(MHD_HTTP_FORBIDDEN); } +HttpResponse cb_alter_logs(const HttpRequest& request) +{ + json_t* json = request.get_json(); + + if (json && runtime_alter_logs_from_json(json)) + { + return HttpResponse(MHD_HTTP_NO_CONTENT); + } + + return HttpResponse(MHD_HTTP_FORBIDDEN); +} + HttpResponse cb_delete_server(const HttpRequest& request) { SERVER* server = server_find_by_unique_name(request.uri_part(1).c_str()); @@ -419,7 +431,7 @@ public: RootResource() { // Special resources required by OPTION etc. - m_get.push_back(SResource(new Resource(cb_send_ok, 1, "/"))); + m_get.push_back(SResource(new Resource(cb_send_ok, 0))); m_get.push_back(SResource(new Resource(cb_send_ok, 1, "*"))); m_get.push_back(SResource(new Resource(cb_all_servers, 1, "servers"))); @@ -456,6 +468,7 @@ public: 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"))); m_put.push_back(SResource(new Resource(cb_alter_service, 2, "services", ":service"))); + m_put.push_back(SResource(new Resource(cb_alter_logs, 2, "maxscale", "logs"))); /** Change resource states */ m_put.push_back(SResource(new Resource(cb_stop_monitor, 3, "monitors", ":monitor", "stop")));