diff --git a/include/maxscale/server.h b/include/maxscale/server.h index 4291db8e3..c64496dce 100644 --- a/include/maxscale/server.h +++ b/include/maxscale/server.h @@ -263,15 +263,12 @@ enum * can use. This function will add the server to the running configuration but * will not persist the changes. * - * @param name Unique server name - * @param address The server address - * @param port The port to connect to - * @param protocol The protocol to use to connect to the server - * @param authenticator The server authenticator module - * @return The newly created server or NULL if an error occurred + * @param name Unique server name + * @param params Parameters for the server + * + * @return The newly created server or NULL if an error occurred */ -extern SERVER* server_alloc(const char *name, const char *address, unsigned short port, - const char *protocol, const char *authenticator); +extern SERVER* server_alloc(const char *name, MXS_CONFIG_PARAMETER* params); /** * @brief Find a server that can be reused diff --git a/server/core/config.cc b/server/core/config.cc index 646b9bfd1..8403483d6 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -1559,19 +1559,17 @@ bool config_append_param(CONFIG_CONTEXT* obj, const char* key, const char* value bool config_replace_param(CONFIG_CONTEXT* obj, const char* key, const char* value) { - MXS_CONFIG_PARAMETER *param = config_get_param(obj->parameters, key); - ss_dassert(param); - char *new_value = MXS_STRDUP(value); - bool rval; - - if (new_value) + if (MXS_CONFIG_PARAMETER* param = config_get_param(obj->parameters, key)) { MXS_FREE(param->value); - param->value = new_value; - rval = true; + param->value = MXS_STRDUP(value); + } + else + { + config_add_param(obj, key, value); } - return rval; + return true; } void config_remove_param(CONFIG_CONTEXT* obj, const char* name) @@ -3136,98 +3134,25 @@ bool is_normal_server_parameter(const char *param) */ int create_new_server(CONFIG_CONTEXT *obj) { - int error_count = 0; - char *address = config_get_value(obj->parameters, CN_ADDRESS); - char *port = config_get_value(obj->parameters, CN_PORT); - char *protocol = config_get_value(obj->parameters, CN_PROTOCOL); - char *monuser = config_get_value(obj->parameters, CN_MONITORUSER); - char *monpw = config_get_value(obj->parameters, CN_MONITORPW); - char *auth = config_get_value(obj->parameters, CN_AUTHENTICATOR); + bool error = false; - if (address && port && protocol) + config_add_defaults(obj, config_server_params); + + const char* module = config_get_string(obj->parameters, CN_PROTOCOL); + ss_dassert(module); + + if (const MXS_MODULE* mod = get_module(module, MODULE_PROTOCOL)) { - if ((obj->element = server_alloc(obj->object, address, atoi(port), protocol, auth)) == NULL) - { - MXS_ERROR("Failed to create a new server, memory allocation failed."); - error_count++; - } + config_add_defaults(obj, mod->parameters); } else { - obj->element = NULL; - MXS_ERROR("Server '%s' is missing a required configuration parameter. A " - "server must have address, port and protocol defined.", obj->object); - error_count++; + MXS_ERROR("Unable to load protocol module '%s'.", module); + return 1; } - if (error_count == 0) + if (SERVER* server = server_alloc(obj->object, obj->parameters)) { - SERVER *server = (SERVER*)obj->element; - - if (monuser && monpw) - { - server_add_mon_user(server, monuser, monpw); - } - else if (monuser && monpw == NULL) - { - MXS_ERROR("Server '%s' has a monitoruser defined but no corresponding " - "password.", obj->object); - error_count++; - } - - char *endptr; - const char *poolmax = config_get_value_string(obj->parameters, CN_PERSISTPOOLMAX); - if (poolmax) - { - long int persistpoolmax = strtol(poolmax, &endptr, 0); - if (*endptr != '\0' || persistpoolmax < 0) - { - MXS_ERROR("Invalid value for 'persistpoolmax' for server %s: %s", - server->name, poolmax); - error_count++; - } - else - { - server->persistpoolmax = persistpoolmax; - } - } - - const char *persistmax = config_get_value_string(obj->parameters, CN_PERSISTMAXTIME); - if (persistmax) - { - long int persistmaxtime = strtol(persistmax, &endptr, 0); - if (*endptr != '\0' || persistmaxtime < 0) - { - MXS_ERROR("Invalid value for 'persistmaxtime' for server %s: %s", - server->name, persistmax); - error_count++; - } - else - { - server->persistmaxtime = persistmaxtime; - } - } - - const char* proxy_protocol = config_get_value_string(obj->parameters, CN_PROXY_PROTOCOL); - if (*proxy_protocol) - { - int truth_value = config_truth_value(proxy_protocol); - if (truth_value == 1) - { - server->proxy_protocol = true; - } - else if (truth_value == 0) - { - server->proxy_protocol = false; - } - else - { - MXS_ERROR("Invalid value for '%s' for server %s: %s", - CN_PROXY_PROTOCOL, server->name, proxy_protocol); - error_count++; - } - } - const char* disk_space_threshold = config_get_value(obj->parameters, CN_DISK_SPACE_THRESHOLD); if (disk_space_threshold) { @@ -3235,28 +3160,18 @@ int create_new_server(CONFIG_CONTEXT *obj) { MXS_ERROR("Invalid value for '%s' for server %s: %s", CN_DISK_SPACE_THRESHOLD, server->name, disk_space_threshold); - error_count++; + error = true; } } - MXS_CONFIG_PARAMETER *params = obj->parameters; - - server->server_ssl = make_ssl_structure(obj, false, &error_count); - if (server->server_ssl && listener_init_SSL(server->server_ssl) != 0) - { - MXS_ERROR("Unable to initialize server SSL"); - } - - while (params) - { - if (!is_normal_server_parameter(params->name)) - { - server_add_parameter(server, params->name, params->value); - } - params = params->next; - } } - return error_count; + else + { + MXS_ERROR("Failed to create a new server, memory allocation failed."); + error = true; + } + + return error; } /** diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index 7846c03a7..5a4ec3e12 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -62,6 +62,64 @@ static std::string runtime_get_error() return rval; } +static const MXS_MODULE_PARAM* get_type_parameters(const char* type) +{ + if (strcmp(type, CN_SERVICE) == 0) + { + return config_service_params; + } + else if (strcmp(type, CN_LISTENER) == 0) + { + return config_listener_params; + } + else if (strcmp(type, CN_MONITOR) == 0) + { + return config_monitor_params; + } + else if (strcmp(type, CN_FILTER) == 0) + { + return config_filter_params; + } + else if (strcmp(type, CN_SERVER) == 0) + { + return config_server_params; + } + + MXS_NOTICE("Module type with no default parameters used: %s", type); + ss_info_dassert(!true, "Module type with no default parameters used"); + return NULL; +} + +/** + * @brief Load module default parameters + * + * @param name Name of the module to load + * @param module_type Type of the module (MODULE_ROUTER, MODULE_PROTOCOL etc.) + * @param object_type Type of the object (server, service, listener etc.) + * + * @return List of default parameters or NULL on error + */ +static MXS_CONFIG_PARAMETER* load_defaults(const char* name, const char* module_type, + const char* object_type) +{ + MXS_CONFIG_PARAMETER* rval = NULL; + CONFIG_CONTEXT ctx = {(char*)""}; + + if (const MXS_MODULE* mod = get_module(name, module_type)) + { + config_add_defaults(&ctx, get_type_parameters(object_type)); + config_add_defaults(&ctx, mod->parameters); + rval = ctx.parameters; + } + else + { + MXS_ERROR("Failed to load module '%s'. See previous error messages for " + "more details.", name); + } + + return rval; +} + bool runtime_link_server(SERVER *server, const char *target) { spinlock_acquire(&crt_lock); @@ -145,45 +203,58 @@ bool runtime_create_server(const char *name, const char *address, const char *po if (server_find_by_unique_name(name) == NULL) { - // TODO: Get default values from the protocol module - if (port == NULL) - { - port = "3306"; - } if (protocol == NULL) { protocol = "mariadbbackend"; } - if (authenticator == NULL && (authenticator = get_default_authenticator(protocol)) == NULL) - { - MXS_ERROR("No authenticator defined for server '%s' and no default " - "authenticator for protocol '%s'.", name, protocol); - spinlock_release(&crt_lock); - return false; - } - /** First check if this service has been created before */ - SERVER *server = server_repurpose_destroyed(name, protocol, authenticator, address, port); + CONFIG_CONTEXT ctx{(char*)""}; + ctx.parameters = load_defaults(protocol, MODULE_PROTOCOL, CN_SERVER); - if (server) + if (ctx.parameters) { - MXS_DEBUG("Reusing server '%s'", name); + if (address) + { + config_replace_param(&ctx, "address", address); + } + if (port) + { + config_replace_param(&ctx, "port", port); + } + if (authenticator) + { + config_replace_param(&ctx, "authenticator", authenticator); + } + + /** First check if this service has been created before */ + SERVER *server = server_repurpose_destroyed(name, protocol, authenticator, + address, port); + + if (server) + { + MXS_INFO("Reusing server '%s'", name); + } + else + { + server = server_alloc(name, ctx.parameters); + } + + if (server && server_serialize(server)) + { + rval = true; + MXS_NOTICE("Created server '%s' at %s:%u", server->name, + server->address, server->port); + } + else + { + runtime_error("Failed to create server '%s', see error log for more details", name); + } + + config_parameter_free(ctx.parameters); } else { - MXS_DEBUG("Creating server '%s'", name); - server = server_alloc(name, address, atoi(port), protocol, authenticator); - } - - if (server && server_serialize(server)) - { - rval = true; - MXS_NOTICE("Created server '%s' at %s:%u", server->name, - server->address, server->port); - } - else - { - runtime_error("Failed to create server '%s', see error log for more details", name); + runtime_error("Server creation failed when loading protocol module '%s'", protocol); } } else @@ -412,56 +483,6 @@ bool runtime_alter_server(SERVER *server, const char *key, const char *value) return valid; } -static const MXS_MODULE_PARAM* get_type_parameters(const char* type) -{ - if (strcmp(type, CN_SERVICE) == 0) - { - return config_service_params; - } - else if (strcmp(type, CN_LISTENER) == 0) - { - return config_listener_params; - } - else if (strcmp(type, CN_MONITOR) == 0) - { - return config_monitor_params; - } - else if (strcmp(type, CN_FILTER) == 0) - { - return config_filter_params; - } - - MXS_NOTICE("Module type with no default parameters used: %s", type); - ss_info_dassert(!true, "Module type with no default parameters used"); - return NULL; -} - -/** - * @brief Add default parameters to a monitor - * - * @param monitor Monitor to modify - */ -static MXS_CONFIG_PARAMETER* load_defaults(const char* name, const char* module_type, - const char* object_type) -{ - MXS_CONFIG_PARAMETER* rval = NULL; - CONFIG_CONTEXT ctx = {(char*)""}; - - if (const MXS_MODULE* mod = get_module(name, module_type)) - { - config_add_defaults(&ctx, get_type_parameters(object_type)); - config_add_defaults(&ctx, mod->parameters); - rval = ctx.parameters; - } - else - { - MXS_ERROR("Failed to load module '%s'. See previous error messages for " - "more details.", name); - } - - return rval; -} - bool runtime_alter_monitor(MXS_MONITOR *monitor, const char *key, const char *value) { spinlock_acquire(&crt_lock); diff --git a/server/core/internal/config.h b/server/core/internal/config.h index d47651ed6..9fed61ade 100644 --- a/server/core/internal/config.h +++ b/server/core/internal/config.h @@ -198,4 +198,6 @@ bool config_global_serialize(); */ bool export_config_file(const char* filename); +bool is_normal_server_parameter(const char *param); + MXS_END_DECLS diff --git a/server/core/server.cc b/server/core/server.cc index 7b0b87858..ab79cc140 100644 --- a/server/core/server.cc +++ b/server/core/server.cc @@ -44,6 +44,7 @@ #include "internal/monitor.h" #include "internal/poll.h" #include "internal/routingworker.hh" +#include "internal/config.h" using maxscale::Semaphore; @@ -72,10 +73,22 @@ static void spin_reporter(void *, char *, int); static void server_parameter_free(SERVER_PARAM *tofree); -SERVER* server_alloc(const char *name, const char *address, unsigned short port, - const char *protocol, const char *authenticator) +SERVER* server_alloc(const char *name, MXS_CONFIG_PARAMETER* params) { - if (authenticator == NULL && (authenticator = get_default_authenticator(protocol)) == NULL) + const char* monuser = config_get_string(params, CN_MONITORUSER); + const char* monpw = config_get_string(params, CN_MONITORPW); + + if ((*monuser != '\0') != (*monpw != '\0')) + { + MXS_ERROR("Both '%s' and '%s' need to be defined for server '%s'", + CN_MONITORUSER, CN_MONITORPW, name); + return NULL; + } + + const char* protocol = config_get_string(params, CN_PROTOCOL); + const char* authenticator = config_get_string(params, CN_AUTHENTICATOR); + + if (!authenticator[0] && !(authenticator = get_default_authenticator(protocol))) { MXS_ERROR("No authenticator defined for server '%s' and no default " "authenticator for protocol '%s'.", name, protocol); @@ -91,12 +104,19 @@ SERVER* server_alloc(const char *name, const char *address, unsigned short port, return NULL; } - int nthr = config_threadcount(); + SSL_LISTENER* ssl = NULL; + + if (!config_create_ssl(name, params, false, &ssl)) + { + MXS_ERROR("Unable to initialize SSL for server '%s'", name); + return NULL; + } + SERVER *server = (SERVER *)MXS_CALLOC(1, sizeof(SERVER)); char *my_name = MXS_STRDUP(name); char *my_protocol = MXS_STRDUP(protocol); char *my_authenticator = MXS_STRDUP(authenticator); - DCB **persistent = (DCB**)MXS_CALLOC(nthr, sizeof(*persistent)); + DCB **persistent = (DCB**)MXS_CALLOC(config_threadcount(), sizeof(*persistent)); if (!server || !my_name || !my_protocol || !my_authenticator || !persistent) { @@ -105,9 +125,12 @@ SERVER* server_alloc(const char *name, const char *address, unsigned short port, MXS_FREE(persistent); MXS_FREE(my_protocol); MXS_FREE(my_authenticator); + SSL_LISTENER_free(ssl); return NULL; } + const char* address = config_get_string(params, CN_ADDRESS); + if (snprintf(server->address, sizeof(server->address), "%s", address) > (int)sizeof(server->address)) { MXS_WARNING("Truncated server address '%s' to the maximum size of %lu characters.", @@ -122,7 +145,8 @@ SERVER* server_alloc(const char *name, const char *address, unsigned short port, server->protocol = my_protocol; server->authenticator = my_authenticator; server->auth_instance = auth_instance; - server->port = port; + server->port = config_get_integer(params, CN_PORT); + server->server_ssl = ssl; server->status = SERVER_RUNNING; server->maint_request = MAINTENANCE_NO_CHANGE; server->node_id = -1; @@ -132,13 +156,13 @@ SERVER* server_alloc(const char *name, const char *address, unsigned short port, spinlock_init(&server->lock); server->persistent = persistent; server->persistmax = 0; - server->persistmaxtime = 0; - server->persistpoolmax = 0; + server->persistpoolmax = config_get_integer(params, CN_PERSISTPOOLMAX); + server->persistmaxtime = config_get_integer(params, CN_PERSISTMAXTIME); server->monuser[0] = '\0'; server->monpw[0] = '\0'; server->is_active = true; server->charset = SERVER_DEFAULT_CHARSET; - server->proxy_protocol = false; + server->proxy_protocol = config_get_bool(params, CN_PROXY_PROTOCOL); // Set last event to server_up as the server is in Running state on startup server->last_event = SERVER_UP_EVENT; @@ -148,6 +172,20 @@ SERVER* server_alloc(const char *name, const char *address, unsigned short port, server->warn_ssl_not_enabled = true; server->disk_space_threshold = NULL; + + if (*monuser && *monpw) + { + server_add_mon_user(server, monuser, monpw); + } + + for (MXS_CONFIG_PARAMETER *p = params; p; p = p->next) + { + if (!is_normal_server_parameter(p->name)) + { + server_add_parameter(server, p->name, p->value); + } + } + spinlock_acquire(&server_spin); server->next = allServers; allServers = server;