Added argument substitution to monitor scripts
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -49,6 +49,8 @@
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#define MAX_SERVER_NAME_LEN 1024
|
||||
|
||||
/**
|
||||
* The server parameters used for weighting routing decissions
|
||||
*
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user