Create ExternalCmd during monitor configuration
The command object need not be recreated every time it's ran.
This commit is contained in:
@ -540,24 +540,12 @@ private:
|
|||||||
void remove_all_servers();
|
void remove_all_servers();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch a script
|
* Launch a command. All default script variables will be replaced.
|
||||||
*
|
|
||||||
* @param ptr The server which has changed state
|
|
||||||
* @return Return value of the executed script or -1 on error
|
|
||||||
*/
|
|
||||||
int launch_script(MonitorServer* ptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch a command
|
|
||||||
*
|
*
|
||||||
* @param ptr The server which has changed state
|
* @param ptr The server which has changed state
|
||||||
* @param cmd The command to execute.
|
|
||||||
*
|
|
||||||
* @note All default script variables will be replaced.
|
|
||||||
*
|
|
||||||
* @return Return value of the executed script or -1 on error.
|
* @return Return value of the executed script or -1 on error.
|
||||||
*/
|
*/
|
||||||
int launch_command(MonitorServer* ptr, ExternalCmd* cmd);
|
int launch_command(MonitorServer* ptr);
|
||||||
|
|
||||||
enum class CredentialsApproach
|
enum class CredentialsApproach
|
||||||
{
|
{
|
||||||
@ -583,6 +571,8 @@ private:
|
|||||||
std::atomic_bool m_status_change_pending {false}; /**< Set when admin requests a status change. */
|
std::atomic_bool m_status_change_pending {false}; /**< Set when admin requests a status change. */
|
||||||
uint8_t m_journal_hash[SHA_DIGEST_LENGTH]; /**< SHA1 hash of the latest written journal */
|
uint8_t m_journal_hash[SHA_DIGEST_LENGTH]; /**< SHA1 hash of the latest written journal */
|
||||||
|
|
||||||
|
std::unique_ptr<ExternalCmd> m_scriptcmd; /**< External command representing the monitor script */
|
||||||
|
|
||||||
ServerVector m_servers; /**< Monitored servers */
|
ServerVector m_servers; /**< Monitored servers */
|
||||||
MXS_CONFIG_PARAMETER m_parameters; /**< Configuration parameters in text form */
|
MXS_CONFIG_PARAMETER m_parameters; /**< Configuration parameters in text form */
|
||||||
Settings m_settings; /**< Base class settings */
|
Settings m_settings; /**< Base class settings */
|
||||||
|
@ -92,43 +92,39 @@ int ExternalCmd::tokenize_args(char* dest[], int dest_size)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalCmd* ExternalCmd::create(const char* argstr, int timeout)
|
std::unique_ptr<ExternalCmd> ExternalCmd::create(const string& argstr, int timeout)
|
||||||
{
|
{
|
||||||
auto cmd = new ExternalCmd(argstr, timeout);
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (argstr && cmd)
|
std::unique_ptr<ExternalCmd> cmd(new ExternalCmd(argstr, timeout));
|
||||||
|
char* argvec[1] {}; // Parse just one argument for testing file existence and permissions.
|
||||||
|
if (cmd->tokenize_args(argvec, 1) > 0)
|
||||||
{
|
{
|
||||||
char* argvec[1] {}; // Parse just one argument for testing.
|
const char* cmdname = argvec[0];
|
||||||
if (cmd->tokenize_args(argvec, 1) > 0)
|
if (access(cmdname, X_OK) != 0)
|
||||||
{
|
{
|
||||||
const char* cmdname = argvec[0];
|
if (access(cmdname, F_OK) != 0)
|
||||||
if (access(cmdname, X_OK) != 0)
|
|
||||||
{
|
{
|
||||||
if (access(cmdname, F_OK) != 0)
|
MXS_ERROR("Cannot find file '%s'.", cmdname);
|
||||||
{
|
|
||||||
MXS_ERROR("Cannot find file: %s", cmdname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MXS_ERROR("Cannot execute file '%s'. Missing execution permissions.", cmdname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
success = true;
|
MXS_ERROR("Cannot execute file '%s'. Missing execution permissions.", cmdname);
|
||||||
}
|
}
|
||||||
MXS_FREE(argvec[0]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MXS_ERROR("Failed to parse argument string for external command: %s", argstr);
|
success = true;
|
||||||
}
|
}
|
||||||
|
MXS_FREE(argvec[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to parse argument string '%s' for external command.", argstr.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
delete cmd;
|
cmd.reset();
|
||||||
cmd = nullptr;
|
|
||||||
}
|
}
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
@ -421,6 +417,11 @@ bool ExternalCmd::externcmd_matches(const char* match)
|
|||||||
return m_command.find(match) != string::npos;
|
return m_command.find(match) != string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExternalCmd::reset_substituted()
|
||||||
|
{
|
||||||
|
m_command_substituted = m_command;
|
||||||
|
}
|
||||||
|
|
||||||
const char* ExternalCmd::substituted() const
|
const char* ExternalCmd::substituted() const
|
||||||
{
|
{
|
||||||
return m_command_substituted.c_str();
|
return m_command_substituted.c_str();
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <maxscale/ccdefs.hh>
|
#include <maxscale/ccdefs.hh>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class ExternalCmd
|
class ExternalCmd
|
||||||
{
|
{
|
||||||
@ -26,7 +27,7 @@ public:
|
|||||||
* @param timeout Command timeout in seconds
|
* @param timeout Command timeout in seconds
|
||||||
* @return Pointer to new external command struct or NULL if an error occurred
|
* @return Pointer to new external command struct or NULL if an error occurred
|
||||||
*/
|
*/
|
||||||
static ExternalCmd* create(const char* argstr, int timeout);
|
static std::unique_ptr<ExternalCmd> create(const std::string& argstr, int timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a command
|
* Execute a command
|
||||||
@ -54,15 +55,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool externcmd_matches(const char* match);
|
bool externcmd_matches(const char* match);
|
||||||
|
|
||||||
|
void reset_substituted();
|
||||||
|
|
||||||
const char* substituted() const;
|
const char* substituted() const;
|
||||||
|
|
||||||
|
private:
|
||||||
static const int MAX_ARGS {256};
|
static const int MAX_ARGS {256};
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_command; /**< Original command */
|
std::string m_command; /**< Original command */
|
||||||
std::string m_command_substituted; /**< Command with substitutions */
|
std::string m_command_substituted; /**< Command with substitutions */
|
||||||
|
int m_timeout; /**< Command timeout in seconds */
|
||||||
int m_timeout; /**< Command timeout in seconds */
|
|
||||||
|
|
||||||
ExternalCmd(const std::string& script, int timeout);
|
ExternalCmd(const std::string& script, int timeout);
|
||||||
|
|
||||||
|
@ -462,8 +462,6 @@ bool Monitor::configure(const MXS_CONFIG_PARAMETER* params)
|
|||||||
{
|
{
|
||||||
m_settings.interval = params->get_duration<milliseconds>(CN_MONITOR_INTERVAL).count();
|
m_settings.interval = params->get_duration<milliseconds>(CN_MONITOR_INTERVAL).count();
|
||||||
m_settings.journal_max_age = params->get_duration<seconds>(CN_JOURNAL_MAX_AGE).count();
|
m_settings.journal_max_age = params->get_duration<seconds>(CN_JOURNAL_MAX_AGE).count();
|
||||||
m_settings.script_timeout = params->get_duration<seconds>(CN_SCRIPT_TIMEOUT).count();
|
|
||||||
m_settings.script = params->get_string(CN_SCRIPT);
|
|
||||||
m_settings.events = params->get_enum(CN_EVENTS, mxs_monitor_event_enum_values);
|
m_settings.events = params->get_enum(CN_EVENTS, mxs_monitor_event_enum_values);
|
||||||
|
|
||||||
MonitorServer::ConnectionSettings& conn_settings = m_settings.conn_settings;
|
MonitorServer::ConnectionSettings& conn_settings = m_settings.conn_settings;
|
||||||
@ -504,6 +502,23 @@ bool Monitor::configure(const MXS_CONFIG_PARAMETER* params)
|
|||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_settings.script_timeout = params->get_duration<seconds>(CN_SCRIPT_TIMEOUT).count();
|
||||||
|
m_settings.script = params->get_string(CN_SCRIPT);
|
||||||
|
if (m_settings.script.empty())
|
||||||
|
{
|
||||||
|
// Reset current external cmd if any.
|
||||||
|
m_scriptcmd.reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_scriptcmd = ExternalCmd::create(m_settings.script, m_settings.script_timeout);
|
||||||
|
if (!m_scriptcmd)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to initialize script '%s'.", m_settings.script.c_str());
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
// Store module name into parameter storage.
|
// Store module name into parameter storage.
|
||||||
@ -1054,8 +1069,11 @@ std::string Monitor::child_nodes(MonitorServer* parent)
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Monitor::launch_command(MonitorServer* ptr, ExternalCmd* cmd)
|
int Monitor::launch_command(MonitorServer* ptr)
|
||||||
{
|
{
|
||||||
|
auto cmd = m_scriptcmd.get();
|
||||||
|
cmd->reset_substituted();
|
||||||
|
|
||||||
if (cmd->externcmd_matches("$INITIATOR"))
|
if (cmd->externcmd_matches("$INITIATOR"))
|
||||||
{
|
{
|
||||||
char initiator[strlen(ptr->server->address) + 24]; // Extra space for port
|
char initiator[strlen(ptr->server->address) + 24]; // Extra space for port
|
||||||
@ -1150,27 +1168,6 @@ int Monitor::launch_command(MonitorServer* ptr, ExternalCmd* cmd)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Monitor::launch_script(MonitorServer* ptr)
|
|
||||||
{
|
|
||||||
const char* script = m_settings.script.c_str();
|
|
||||||
char arg[strlen(script) + 1];
|
|
||||||
strcpy(arg, script);
|
|
||||||
|
|
||||||
ExternalCmd* cmd = ExternalCmd::create(arg, m_settings.script_timeout);
|
|
||||||
|
|
||||||
if (cmd == NULL)
|
|
||||||
{
|
|
||||||
MXS_ERROR("Failed to initialize script '%s'. See previous errors for the "
|
|
||||||
"cause of this failure.",
|
|
||||||
script);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rv = launch_command(ptr, cmd);
|
|
||||||
delete cmd;
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonitorServer::ConnectResult
|
MonitorServer::ConnectResult
|
||||||
Monitor::ping_or_connect_to_db(const MonitorServer::ConnectionSettings& sett, SERVER& server, MYSQL** ppConn)
|
Monitor::ping_or_connect_to_db(const MonitorServer::ConnectionSettings& sett, SERVER& server, MYSQL** ppConn)
|
||||||
{
|
{
|
||||||
@ -1381,9 +1378,9 @@ void Monitor::detect_handle_state_changes()
|
|||||||
master_up = true;
|
master_up = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_settings.script.empty() && (event & m_settings.events))
|
if (m_scriptcmd && (event & m_settings.events))
|
||||||
{
|
{
|
||||||
launch_script(ptr);
|
launch_command(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user