Added argument substitution to monitor scripts

This commit is contained in:
Markus Makela
2015-11-11 16:52:24 +02:00
parent 466224b316
commit 2d600868f5
10 changed files with 161 additions and 184 deletions

View File

@ -139,20 +139,20 @@ int externcmd_execute(EXTERNCMD* cmd)
{
int rval = 0;
pid_t pid;
pid = fork();
if(pid < 0)
if (pid < 0)
{
char errbuf[STRERROR_BUFLEN];
skygw_log_write(LOGFILE_ERROR, "Failed to execute command '%s', fork failed: [%d] %s",
cmd->argv[0], errno, strerror_r(errno, errbuf, sizeof(errbuf)));
rval = -1;
}
else if(pid == 0)
else if (pid == 0)
{
/** Child process, execute command */
execvp(cmd->argv[0],cmd->argv);
execvp(cmd->argv[0], cmd->argv);
_exit(1);
}
else
@ -161,6 +161,54 @@ int externcmd_execute(EXTERNCMD* cmd)
cmd->n_exec++;
LOGIF(LD, skygw_log_write(LD, "[monitor_exec_cmd] Forked child process %d : %s.", pid, cmd));
}
return rval;
}
/**
* Substitute all occurrences of @c match with @c replace in the arguments for @c cmd.
* @param cmd External command
* @param match Match string
* @param replace Replacement string
* @return true if replacement was successful, false on error
*/
bool externcmd_substitute_arg(EXTERNCMD* cmd, const char* match, const char* replace)
{
int err;
bool rval = true;
size_t errpos;
pcre2_code *re = pcre2_compile((PCRE2_SPTR) match, PCRE2_ZERO_TERMINATED, 0, &err, &errpos, NULL);
if (re)
{
for (int i = 0; cmd->argv[i] && rval; i++)
{
size_t size = strlen(cmd->argv[i]);
char* dest = malloc(size);
if (dest)
{
mxs_pcre2_result_t rc = mxs_pcre2_substitute(re, cmd->argv[i], replace, &dest, &size);
switch (rc)
{
case MXS_PCRE2_ERROR:
free(dest);
rval = false;
break;
case MXS_PCRE2_MATCH:
free(cmd->argv[i]);
cmd->argv[i] = dest;
break;
case MXS_PCRE2_NOMATCH:
free(dest);
break;
}
}
}
}
else
{
rval = false;
LOGIF(LD, skygw_log_write(LD, "[monitor_exec_cmd] Forked child process %d : %s.", pid, cmd));
}
return rval;
}

View File

@ -74,7 +74,7 @@ SERVER *server;
server->server_chk_top = CHK_NUM_SERVER;
server->server_chk_tail = CHK_NUM_SERVER;
#endif
server->name = strdup(servname);
server->name = strndup(servname, MAX_SERVER_NAME_LEN);
server->protocol = strdup(protocol);
server->port = port;
server->status = SERVER_RUNNING;

View File

@ -6,6 +6,8 @@
#include <errno.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <maxscale_pcre2.h>
#define MAXSCALE_EXTCMD_ARG_MAX 256
typedef struct extern_cmd_t{
@ -15,8 +17,10 @@ typedef struct extern_cmd_t{
pid_t child; /*< PID of the child process */
}EXTERNCMD;
char* externcmd_extract_command(const char* argstr);
EXTERNCMD* externcmd_allocate(char* argstr);
void externcmd_free(EXTERNCMD* cmd);
int externcmd_execute(EXTERNCMD* cmd);
bool externcmd_can_execute(char* argstr);
bool externcmd_substitute_arg(EXTERNCMD* cmd, const char* re, const char* replace);
bool externcmd_can_execute(const char* argstr);
#endif

View File

@ -49,6 +49,8 @@
* @endverbatim
*/
#define MAX_SERVER_NAME_LEN 1024
/**
* The server parameters used for weighting routing decissions
*

View File

@ -17,6 +17,7 @@
*/
#include <monitor_common.h>
#include <maxscale_pcre2.h>
monitor_event_t mon_name_to_event(char* tok);
@ -225,23 +226,32 @@ case NEW_DONOR_EVENT:
}
void mon_append_node_names(MONITOR_SERVERS* start,char* str, int len)
/**
* Create a list of running servers
* @param start Monitored servers
* @param dest Destination where the string is formed
* @param len Length of @c dest
*/
void mon_append_node_names(MONITOR_SERVERS* start, char* dest, int len)
{
MONITOR_SERVERS* ptr = start;
bool first = true;
int slen = strlen(str);
char arr[256];
while(ptr && slen < len)
int slen = strlen(dest);
char arr[MAX_SERVER_NAME_LEN + 32]; // Some extra space for port
while (ptr && slen < len)
{
if(!first)
{
strncat(str,",",len);
}
first = false;
sprintf(arr,"%s:%d",ptr->server->name,ptr->server->port);
strncat(str,arr,len);
ptr = ptr->next;
slen = strlen(str);
if(SERVER_IS_RUNNING(ptr->server))
{
if (!first)
{
strncat(dest, ",", len);
}
first = false;
snprintf(arr, sizeof(arr), "%s:%d", ptr->server->name, ptr->server->port);
strncat(dest, arr, len);
slen = strlen(dest);
}
ptr = ptr->next;
}
}
@ -302,23 +312,26 @@ bool mon_print_fail_status(
*/
void monitor_launch_script(MONITOR* mon, MONITOR_SERVERS* ptr, char* script)
{
char argstr[PATH_MAX + MON_ARG_MAX + 1];
EXTERNCMD* cmd;
char nodelist[PATH_MAX + MON_ARG_MAX + 1] = {'\0'};
char event[strlen(mon_get_event_name(ptr))];
char initiator[strlen(ptr->server->name) + 24]; // Extra space for port
snprintf(argstr, PATH_MAX + MON_ARG_MAX,
"%s --event=%s --initiator=%s:%d --nodelist=",
script,
mon_get_event_name(ptr),
ptr->server->name,
ptr->server->port);
snprintf(initiator, sizeof(initiator), "%s:%d", ptr->server->name, ptr->server->port);
snprintf(event, sizeof(event), "%s", mon_get_event_name(ptr));
mon_append_node_names(mon->databases, nodelist, PATH_MAX + MON_ARG_MAX);
mon_append_node_names(mon->databases, argstr, PATH_MAX + MON_ARG_MAX);
if ((cmd = externcmd_allocate(argstr)) == NULL)
EXTERNCMD* cmd = externcmd_allocate(script);
if (cmd == NULL)
{
skygw_log_write(LE, "Failed to initialize script: %s", script);
return;
}
externcmd_substitute_arg(cmd, "[$]INITIATOR", initiator);
externcmd_substitute_arg(cmd, "[$]EVENT", event);
externcmd_substitute_arg(cmd, "[$]NODELIST", nodelist);
if (externcmd_execute(cmd))
{
skygw_log_write(LOGFILE_ERROR,