diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index 93aa62d81..c3cb1969e 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -474,6 +474,86 @@ bool runtime_alter_monitor(MXS_MONITOR *monitor, const char *key, const char *va return valid; } +bool runtime_alter_service(SERVICE *service, const char* zKey, const char* zValue) +{ + string key(zKey); + string value(zValue); + bool valid = true; + + spinlock_acquire(&crt_lock); + + if (key == CN_USER) + { + serviceSetUser(service, value.c_str(), service->credentials.authdata); + } + else if (key == CN_PASSWORD) + { + serviceSetUser(service, service->credentials.name, value.c_str()); + } + else if (key == CN_ENABLE_ROOT_USER) + { + serviceEnableRootUser(service, config_truth_value(value.c_str())); + } + else if (key == CN_MAX_RETRY_INTERVAL) + { + service_set_retry_interval(service, strtol(value.c_str(), NULL, 10)); + } + else if (key == CN_MAX_CONNECTIONS) + { + // TODO: Once connection queues are implemented, use correct values + serviceSetConnectionLimits(service, strtol(value.c_str(), NULL, 10), 0, 0); + } + else if (key == CN_CONNECTION_TIMEOUT) + { + serviceSetTimeout(service, strtol(value.c_str(), NULL, 10)); + } + else if (key == CN_AUTH_ALL_SERVERS) + { + serviceAuthAllServers(service, config_truth_value(value.c_str())); + } + else if (key == CN_STRIP_DB_ESC) + { + serviceStripDbEsc(service, config_truth_value(value.c_str())); + } + else if (key == CN_LOCALHOST_MATCH_WILDCARD_HOST) + { + serviceEnableLocalhostMatchWildcardHost(service, config_truth_value(value.c_str())); + } + else if (key == CN_VERSION_STRING) + { + serviceSetVersionString(service, value.c_str()); + } + else if (key == CN_WEIGHTBY) + { + serviceWeightBy(service, value.c_str()); + } + else if (key == CN_LOG_AUTH_WARNINGS) + { + // TODO: Move this inside the service source + service->log_auth_warnings = config_truth_value(value.c_str()); + } + else if (key == CN_RETRY_ON_FAILURE) + { + serviceSetRetryOnFailure(service, value.c_str()); + } + else + { + MXS_ERROR("Unknown parameter for service '%s': %s=%s", + service->name, key.c_str(), value.c_str()); + valid = false; + } + + if (valid) + { + service_serialize(service); + MXS_NOTICE("Updated service '%s': %s=%s", service->name, key.c_str(), value.c_str()); + } + + spinlock_release(&crt_lock); + + return valid; +} + bool runtime_create_listener(SERVICE *service, const char *name, const char *addr, const char *port, const char *proto, const char *auth, const char *auth_opt, const char *ssl_key, diff --git a/server/core/maxscale/config_runtime.h b/server/core/maxscale/config_runtime.h index 638b86834..5270df470 100644 --- a/server/core/maxscale/config_runtime.h +++ b/server/core/maxscale/config_runtime.h @@ -120,6 +120,17 @@ bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert */ bool runtime_alter_monitor(MXS_MONITOR *monitor, const char *key, const char *value); +/** + * @brief Alter service parameters + * + * @param monitor Service to alter + * @param key Key to modify + * @param value New value + * + * @return True if @c key was one of the supported parameters + */ +bool runtime_alter_service(SERVICE *service, const char* zKey, const char* zValue); + /** * @brief Create a new listener for a service * diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index 1ec2e4576..6d44e7245 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -1513,6 +1513,34 @@ static void alterMonitor(DCB *dcb, MXS_MONITOR *monitor, char *v1, char *v2, cha } +static void alterService(DCB *dcb, SERVICE *service, char *v1, char *v2, char *v3, + char *v4, char *v5, char *v6, char *v7, char *v8, char *v9, + char *v10, char *v11) +{ + char *values[11] = {v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11}; + const int items = sizeof(values) / sizeof(values[0]); + + for (int i = 0; i < items && values[i]; i++) + { + char *key = values[i]; + char *value = strchr(key, '='); + + if (value) + { + *value++ = '\0'; + + if (!runtime_alter_service(service, key, value)) + { + dcb_printf(dcb, "Error: Bad key-value parameter: %s=%s\n", key, value); + } + } + else + { + dcb_printf(dcb, "Error: not a key-value parameter: %s\n", values[i]); + } + } +} + struct subcommand alteroptions[] = { { @@ -1574,6 +1602,37 @@ struct subcommand alteroptions[] = ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING } }, + { + "service", 2, 12, alterService, + "Alter service parameters", + "Usage: alter service NAME KEY=VALUE ...\n" + "\n" + "Parameters:\n" + "NAME Service name\n" + "KEY=VALUE List of `key=value` pairs separated by spaces\n" + "\n" + "All services support the following values for KEY:\n" + "user Username used when connecting to servers\n" + "password Password used when connecting to servers\n" + "enable_root_user Allow root user access through this service\n" + "max_retry_interval Maximum restart retry interval\n" + "max_connections Maximum connection limit\n" + "connection_timeout Client idle timeout in seconds\n" + "auth_all_servers Retrieve authentication data from all servers\n" + "strip_db_esc Strip escape characters from database names\n" + "localhost_match_wildcard_host Match wildcard host to 'localhost' address\n" + "version_string The version string given to client connections\n" + "weightby Weighting parameter name\n" + "log_auth_warnings Log authentication warnings\n" + "retry_on_failure Retry service start on failure\n" + "\n" + "Example: alter service my-service user=maxuser password=maxpwd", + { + ARG_TYPE_SERVICE, ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING, + ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING, + ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING + } + }, { EMPTY_OPTION }