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
This commit is contained in:
Markus Makela
2016-11-08 20:58:17 +02:00
parent 3b465c0d41
commit dbedf57c9a
3 changed files with 141 additions and 26 deletions

View File

@ -201,7 +201,8 @@ struct monitor
extern MONITOR *monitor_alloc(char *, char *); extern MONITOR *monitor_alloc(char *, char *);
extern void monitor_free(MONITOR *); extern void monitor_free(MONITOR *);
extern MONITOR *monitor_find(char *); 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 monitorAddUser(MONITOR *, char *, char *);
extern void monitorAddParameters(MONITOR *monitor, CONFIG_PARAMETER *params); extern void monitorAddParameters(MONITOR *monitor, CONFIG_PARAMETER *params);
extern void monitorStop(MONITOR *); extern void monitorStop(MONITOR *);

View File

@ -258,6 +258,13 @@ monitorAddServer(MONITOR *mon, SERVER *server)
/* pending status is updated by get_replication_tree */ /* pending status is updated by get_replication_tree */
db->pending_status = 0; db->pending_status = 0;
monitor_state_t old_state = mon->state;
if (old_state == MONITOR_STATE_RUNNING)
{
monitorStop(mon);
}
spinlock_acquire(&mon->lock); spinlock_acquire(&mon->lock);
if (mon->databases == NULL) if (mon->databases == NULL)
@ -274,6 +281,23 @@ monitorAddServer(MONITOR *mon, SERVER *server)
ptr->next = db; ptr->next = db;
} }
spinlock_release(&mon->lock); 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; MONITOR_SERVERS *tofree = servers;
servers = servers->next; servers = servers->next;
if (tofree->con) monitor_server_free(tofree);
{
mysql_close(tofree->con);
} }
MXS_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)
{
if (ptr->server == server)
{
prev->next = ptr->next;
break;
}
prev = ptr;
ptr = ptr->next;
}
}
spinlock_release(&mon->lock);
if (ptr)
{
monitor_servers_free(ptr);
}
if (old_state == MONITOR_STATE_RUNNING)
{
monitorStart(mon, mon->parameters);
} }
} }

View File

@ -779,15 +779,36 @@ struct subcommand failoptions[] =
static void telnetdAddUser(DCB *, char *user, char *password); 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*)a;
SERVER *server = (SERVER*)b; char *name = (char*)b;
SERVICE *service = service_find(name);
MONITOR *monitor = monitor_find(name);
if (service || monitor)
{
ss_dassert(service == NULL || monitor == NULL);
if (service)
{
serviceAddBackend(service, server); serviceAddBackend(service, server);
}
else if (monitor)
{
monitorAddServer(monitor, server);
}
MXS_NOTICE("Added server '%s' to service '%s'", server->unique_name, service->name); const char *target = service ? "service" : "monitor";
dcb_printf(dcb, "Added server '%s' to service '%s'\n", server->unique_name, service->name);
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,10 +824,11 @@ struct subcommand addoptions[] =
{ARG_TYPE_STRING, ARG_TYPE_STRING, 0} {ARG_TYPE_STRING, ARG_TYPE_STRING, 0}
}, },
{ {
"server", 2, 2, cmd_serviceAddBackend, "server", 2, 2, cmd_AddServer,
"Add a new server to a service", "Add a new server to a service",
"Takes a server name as the parameter. The server must exist in the configuration file.", "Usage: add server SERVER TARGET\n"
{ARG_TYPE_SERVICE, ARG_TYPE_SERVER, 0} "The TARGET must be either a service or a monitor",
{ARG_TYPE_SERVER, ARG_TYPE_STRING, 0}
}, },
{ EMPTY_OPTION} { EMPTY_OPTION}
}; };
@ -814,15 +836,34 @@ struct subcommand addoptions[] =
static void telnetdRemoveUser(DCB *, char *user, char *password); 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*)a;
SERVER *server = (SERVER*)b; char *name = (char*)b;
SERVICE *service = service_find(name);
MONITOR *monitor = monitor_find(name);
if (service || monitor)
{
ss_dassert(service == NULL || monitor == NULL);
if (service)
{
serviceRemoveBackend(service, server); serviceRemoveBackend(service, server);
}
else if (monitor)
{
monitorRemoveServer(monitor, server);
}
MXS_NOTICE("Removed server '%s' from service '%s'", server->unique_name, service->name); const char *target = service ? "service" : "monitor";
dcb_printf(dcb, "Removed server '%s' from service '%s'\n", server->unique_name, service->name); 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 from maxadmin",
"Remove account for using maxadmin over the network. E.g.:\n" "Remove account for using maxadmin over the network. E.g.:\n"
" MaxAdmin> remove user bob somepass", " MaxAdmin> remove user bob somepass",
{ARG_TYPE_STRING, ARG_TYPE_STRING, 0} {ARG_TYPE_STRING, ARG_TYPE_STRING}
}, },
{ {
"server", 2, 2, cmd_serviceRemoveBackend, "server", 2, 2, cmd_RemoveServer,
"Remove a server from a service", "Remove a server from a service or a monitor",
"Takes a server name as the parameter. The server must exist in the configuration file.", "Usage: remove server SERVER TARGET\n"
{ARG_TYPE_SERVICE, ARG_TYPE_SERVER, 0} "The TARGET must be either a service or a monitor",
{ARG_TYPE_SERVER, ARG_TYPE_STRING}
}, },
{ {
EMPTY_OPTION EMPTY_OPTION
@ -1331,7 +1373,7 @@ execute_cmd(CLI_SESSION *cli)
} }
} }
switch (argc) switch (cmds[i].options[j].argc_max)
{ {
case 0: case 0:
cmds[i].options[j].fn(dcb); cmds[i].options[j].fn(dcb);