From dbedf57c9ad5d65c000e9cf8d337d83b32a19136 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Tue, 8 Nov 2016 20:58:17 +0200 Subject: [PATCH] Add and remove servers for monitors The `add server` command accepts a server name and either a service name or a monitor name. It will add servers to services and monitors. Since all monitors use the MONITOR_SERVER structures directly, the monitors need to be stopped before new servers are added to them --- include/maxscale/monitor.h | 3 +- server/core/monitor.c | 78 +++++++++++++++++++- server/modules/routing/debugcli/debugcmd.c | 86 ++++++++++++++++------ 3 files changed, 141 insertions(+), 26 deletions(-) diff --git a/include/maxscale/monitor.h b/include/maxscale/monitor.h index 106b17113..5ae9df416 100644 --- a/include/maxscale/monitor.h +++ b/include/maxscale/monitor.h @@ -201,7 +201,8 @@ struct monitor extern MONITOR *monitor_alloc(char *, char *); extern void monitor_free(MONITOR *); extern MONITOR *monitor_find(char *); -extern void monitorAddServer(MONITOR *, SERVER *); +extern void monitorAddServer(MONITOR *mon, SERVER *server); +extern void monitorRemoveServer(MONITOR *mon, SERVER *server); extern void monitorAddUser(MONITOR *, char *, char *); extern void monitorAddParameters(MONITOR *monitor, CONFIG_PARAMETER *params); extern void monitorStop(MONITOR *); diff --git a/server/core/monitor.c b/server/core/monitor.c index 60bc4e238..b67e6ecf4 100644 --- a/server/core/monitor.c +++ b/server/core/monitor.c @@ -258,6 +258,13 @@ monitorAddServer(MONITOR *mon, SERVER *server) /* pending status is updated by get_replication_tree */ db->pending_status = 0; + monitor_state_t old_state = mon->state; + + if (old_state == MONITOR_STATE_RUNNING) + { + monitorStop(mon); + } + spinlock_acquire(&mon->lock); if (mon->databases == NULL) @@ -274,6 +281,23 @@ monitorAddServer(MONITOR *mon, SERVER *server) ptr->next = db; } spinlock_release(&mon->lock); + + if (old_state == MONITOR_STATE_RUNNING) + { + monitorStart(mon, mon->parameters); + } +} + +static void monitor_server_free(MONITOR_SERVERS *tofree) +{ + if (tofree) + { + if (tofree->con) + { + mysql_close(tofree->con); + } + MXS_FREE(tofree); + } } /** @@ -286,11 +310,59 @@ static void monitor_servers_free(MONITOR_SERVERS *servers) { MONITOR_SERVERS *tofree = servers; servers = servers->next; - if (tofree->con) + monitor_server_free(tofree); + } +} + +/** + * Remove a server from a monitor. + * + * @param mon The Monitor instance + * @param server The Server to remove + */ +void monitorRemoveServer(MONITOR *mon, SERVER *server) +{ + monitor_state_t old_state = mon->state; + + if (old_state == MONITOR_STATE_RUNNING) + { + monitorStop(mon); + } + + spinlock_acquire(&mon->lock); + + ss_dassert(mon->databases); + MONITOR_SERVERS *ptr = mon->databases; + + if (ptr->server == server) + { + mon->databases = mon->databases->next; + } + else + { + MONITOR_SERVERS *prev = ptr; + + while (ptr) { - mysql_close(tofree->con); + if (ptr->server == server) + { + prev->next = ptr->next; + break; + } + prev = ptr; + ptr = ptr->next; } - MXS_FREE(tofree); + } + spinlock_release(&mon->lock); + + if (ptr) + { + monitor_servers_free(ptr); + } + + if (old_state == MONITOR_STATE_RUNNING) + { + monitorStart(mon, mon->parameters); } } diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index 183d64e31..973b72258 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -779,15 +779,36 @@ struct subcommand failoptions[] = static void telnetdAddUser(DCB *, char *user, char *password); -static void cmd_serviceAddBackend(DCB *dcb, void *a, void *b) +static void cmd_AddServer(DCB *dcb, void *a, void *b) { - SERVICE *service = (SERVICE*)a; - SERVER *server = (SERVER*)b; + SERVER *server = (SERVER*)a; + char *name = (char*)b; - serviceAddBackend(service, server); + SERVICE *service = service_find(name); + MONITOR *monitor = monitor_find(name); - MXS_NOTICE("Added server '%s' to service '%s'", server->unique_name, service->name); - dcb_printf(dcb, "Added server '%s' to service '%s'\n", server->unique_name, service->name); + if (service || monitor) + { + ss_dassert(service == NULL || monitor == NULL); + + if (service) + { + serviceAddBackend(service, server); + } + else if (monitor) + { + monitorAddServer(monitor, server); + } + + const char *target = service ? "service" : "monitor"; + + MXS_NOTICE("Added server '%s' to %s '%s'", server->unique_name, target, name); + dcb_printf(dcb, "Added server '%s' to %s '%s'\n", server->unique_name, target, name); + } + else + { + dcb_printf(dcb, "No service or monitor with the name '%s'\n", name); + } } /** @@ -803,26 +824,46 @@ struct subcommand addoptions[] = {ARG_TYPE_STRING, ARG_TYPE_STRING, 0} }, { - "server", 2, 2, cmd_serviceAddBackend, + "server", 2, 2, cmd_AddServer, "Add a new server to a service", - "Takes a server name as the parameter. The server must exist in the configuration file.", - {ARG_TYPE_SERVICE, ARG_TYPE_SERVER, 0} + "Usage: add server SERVER TARGET\n" + "The TARGET must be either a service or a monitor", + {ARG_TYPE_SERVER, ARG_TYPE_STRING, 0} }, - { EMPTY_OPTION } + { EMPTY_OPTION} }; static void telnetdRemoveUser(DCB *, char *user, char *password); -static void cmd_serviceRemoveBackend(DCB *dcb, void *a, void *b) +static void cmd_RemoveServer(DCB *dcb, void *a, void *b) { - SERVICE *service = (SERVICE*)a; - SERVER *server = (SERVER*)b; + SERVER *server = (SERVER*)a; + char *name = (char*)b; + SERVICE *service = service_find(name); + MONITOR *monitor = monitor_find(name); - serviceRemoveBackend(service, server); + if (service || monitor) + { + ss_dassert(service == NULL || monitor == NULL); - MXS_NOTICE("Removed server '%s' from service '%s'", server->unique_name, service->name); - dcb_printf(dcb, "Removed server '%s' from service '%s'\n", server->unique_name, service->name); + if (service) + { + serviceRemoveBackend(service, server); + } + else if (monitor) + { + monitorRemoveServer(monitor, server); + } + + const char *target = service ? "service" : "monitor"; + MXS_NOTICE("Removed server '%s' from %s '%s'", server->unique_name, target, name); + dcb_printf(dcb, "Removed server '%s' from %s '%s'\n", server->unique_name, target, name); + } + else + { + dcb_printf(dcb, "No service or monitor with the name '%s'\n", name); + } } /** @@ -837,13 +878,14 @@ struct subcommand removeoptions[] = "Remove account from maxadmin", "Remove account for using maxadmin over the network. E.g.:\n" " MaxAdmin> remove user bob somepass", - {ARG_TYPE_STRING, ARG_TYPE_STRING, 0} + {ARG_TYPE_STRING, ARG_TYPE_STRING} }, { - "server", 2, 2, cmd_serviceRemoveBackend, - "Remove a server from a service", - "Takes a server name as the parameter. The server must exist in the configuration file.", - {ARG_TYPE_SERVICE, ARG_TYPE_SERVER, 0} + "server", 2, 2, cmd_RemoveServer, + "Remove a server from a service or a monitor", + "Usage: remove server SERVER TARGET\n" + "The TARGET must be either a service or a monitor", + {ARG_TYPE_SERVER, ARG_TYPE_STRING} }, { EMPTY_OPTION @@ -1331,7 +1373,7 @@ execute_cmd(CLI_SESSION *cli) } } - switch (argc) + switch (cmds[i].options[j].argc_max) { case 0: cmds[i].options[j].fn(dcb);