diff --git a/include/maxscale/config_runtime.h b/include/maxscale/config_runtime.h index 8384ebbb9..06ae263a8 100644 --- a/include/maxscale/config_runtime.h +++ b/include/maxscale/config_runtime.h @@ -144,3 +144,16 @@ bool runtime_create_listener(SERVICE *service, const char *name, const char *add const char *auth_opt, const char *ssl_key, const char *ssl_cert, const char *ssl_ca, const char *ssl_version, const char *ssl_depth); + +/** + * @brief Destroy a listener + * + * This disables the listener by removing it from the polling system. It also + * removes any generated configurations for this listener. + * + * @param service Service where the listener exists + * @param name Name of the listener + * + * @return True if the listener was successfully destroyed + */ +bool runtime_destroy_listener(SERVICE *service, const char *name); diff --git a/include/maxscale/service.h b/include/maxscale/service.h index 723d1259d..caa773625 100644 --- a/include/maxscale/service.h +++ b/include/maxscale/service.h @@ -262,13 +262,13 @@ bool serviceStop(SERVICE *service); bool serviceStart(SERVICE *service); /** - * @brief Start a listener for a service + * @brief Start new a listener for a service * * @param service Service where the listener is linked * @param port Listener to start * @return True if listener was started */ -bool serviceStartListener(SERVICE *service, SERV_LISTENER *port); +bool serviceLaunchListener(SERVICE *service, SERV_LISTENER *port); /** * @brief Stop a listener for a service diff --git a/server/core/config_runtime.c b/server/core/config_runtime.c index f7d56628d..c5acb8fdd 100644 --- a/server/core/config_runtime.c +++ b/server/core/config_runtime.c @@ -412,9 +412,9 @@ bool runtime_create_listener(SERVICE *service, const char *name, const char *add { const char *print_addr = addr ? addr : "0.0.0.0"; SERV_LISTENER *listener = serviceCreateListener(service, name, proto, addr, - u_port, auth, auth_opt, ssl); + u_port, auth, auth_opt, ssl); - if (listener && listener_serialize(listener) && serviceStartListener(service, listener)) + if (listener && listener_serialize(listener) && serviceLaunchListener(service, listener)) { MXS_NOTICE("Listener '%s' at %s:%s for service '%s' created", name, print_addr, port, service->name); @@ -429,3 +429,52 @@ bool runtime_create_listener(SERVICE *service, const char *name, const char *add spinlock_release(&crt_lock); return rval; } + +bool runtime_destroy_listener(SERVICE *service, const char *name) +{ + bool rval = false; + char filename[PATH_MAX]; + snprintf(filename, sizeof(filename), "%s/%s.cnf", get_config_persistdir(), name); + + spinlock_acquire(&crt_lock); + + if (unlink(filename) == -1) + { + if (errno != ENOENT) + { + char err[MXS_STRERROR_BUFLEN]; + MXS_ERROR("Failed to remove persisted listener configuration '%s': %d, %s", + filename, errno, strerror_r(errno, err, sizeof(err))); + } + else + { + rval = false; + MXS_WARNING("Listener '%s' was not created at runtime. Remove the " + "listener manually from the correct configuration file.", + name); + } + } + else + { + rval = true; + } + + if (rval) + { + rval = serviceStopListener(service, name); + + if (rval) + { + MXS_NOTICE("Destroyed listener '%s' for service '%s'. The listener " + "will be removed after the next restart of MaxScale.", + name, service->name); + } + else + { + MXS_ERROR("Failed to destroy listener '%s' for service '%s'", name, service->name); + } + } + + spinlock_release(&crt_lock); + return rval; +} diff --git a/server/core/service.c b/server/core/service.c index 128f018f8..3df2e19af 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -490,7 +490,7 @@ int serviceInitialize(SERVICE *service) return listeners; } -bool serviceStartListener(SERVICE *service, SERV_LISTENER *port) +bool serviceLaunchListener(SERVICE *service, SERV_LISTENER *port) { return serviceStartPort(service, port); } diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index 34907326c..fb584b268 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -1111,6 +1111,18 @@ static void destroyServer(DCB *dcb, SERVER *server) } } +static void destroyListener(DCB *dcb, SERVICE *service, const char *name) +{ + if (runtime_destroy_listener(service, name)) + { + dcb_printf(dcb, "Destroyed listener '%s'\n", name); + } + else + { + dcb_printf(dcb, "Failed to destroy listener '%s', see log file for more details\n", name); + } +} + struct subcommand destroyoptions[] = { { @@ -1119,6 +1131,12 @@ struct subcommand destroyoptions[] = "Usage: destroy server NAME", {ARG_TYPE_SERVER} }, + { + "listener", 2, 2, destroyListener, + "Destroy a listener", + "Usage: destroy listener SERVICE NAME", + {ARG_TYPE_SERVICE, ARG_TYPE_STRING} + }, { EMPTY_OPTION }