Merge branch '2.3' into 2.4

This commit is contained in:
Markus Mäkelä 2019-12-13 11:24:42 +02:00
commit ad323bb837
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
6 changed files with 151 additions and 69 deletions

View File

@ -103,7 +103,14 @@ then
# YUM!
sudo yum clean all
sudo yum update -y
sudo yum install -y --nogpgcheck gcc gcc-c++ ncurses-devel bison glibc-devel \
unset enable_power_tools
yum repolist all | grep PowerTools
if [ $? == 0 ]
then
enable_power_tools="enablerepo=PowerTools"
fi
sudo yum install -y --nogpgcheck ${enable_power_tools} \
gcc gcc-c++ ncurses-devel bison glibc-devel \
libgcc perl make libtool openssl-devel libaio libaio-devel libedit-devel \
libedit-devel systemtap-sdt-devel rpm-sign wget \
gnupg pcre-devel flex rpmdevtools git wget tcl tcl-devel openssl libuuid-devel xz-devel \
@ -131,13 +138,9 @@ then
grep "release 6" /etc/redhat-release
if [ $? -ne 0 ]
then
# EPEL is installed for REST API and MaxCtrl unit tests (docker-compose etc.) and GCOV report generation (lcov)
sudo yum -y install docker epel-release
sudo yum -y install docker-compose lcov
sudo groupadd docker
sudo usermod -a -G docker `whoami`
sudo sed -i 's/--selinux-enabled/--selinux-enabled=false/' /etc/sysconfig/docker
sudo systemctl start docker
# EPEL is installed for GCOV report generation (lcov)
sudo yum -y install epel-release
sudo yum -y install lcov
fi
fi

View File

@ -41,7 +41,6 @@ Table of Contents
* [Failover/switchover fails](#failoverswitchover-fails)
* [Slave detection shows external masters](#slave-detection-shows-external-masters)
* [Using the MariaDB Monitor With Binlogrouter](#using-the-mariadb-monitor-with-binlogrouter)
* [Example 1 - Monitor script](#example-1---monitor-script)
## Overview
@ -888,37 +887,3 @@ binlog server to the list of servers only if _master_id_ identity is set.
For addition information read the
[Replication Proxy](../Tutorials/Replication-Proxy-Binlog-Router-Tutorial.md)
tutorial.
## Example 1 - Monitor script
Here is an example shell script which sends an email to an admin@my.org
when a server goes down.
```
#!/usr/bin/env bash
#This script assumes that the local mail server is configured properly
#The second argument is the event type
event=${$2/.*=/}
server=${$3/.*=/}
message="A server has gone down at `date`."
echo $message|mail -s "The event was $event for server $server." admin@my.org
```
Here is a monitor configuration that only triggers the script when a master
or a slave server goes down.
```
[Database-Monitor]
type=monitor
module=mariadbmon
servers=server1,server2
script=mail_to_admin.sh
events=master_down,slave_down
```
When a master or a slave server goes down, the script is executed, a mail is
sent and the administrator will be immediately notified of any possible
problems. This is just a simple example showing what you can do with MaxScale
and monitor scripts.

View File

@ -2,6 +2,8 @@
This document lists optional parameters that all current monitors support.
[TOC]
## Parameters
### `user`
@ -200,36 +202,45 @@ disk_space_check_interval=10000ms
### `script`
This command will be executed when a server changes its state. The parameter should be an absolute path to a command or the command should be in the executable path. The user which is used to run MaxScale should have execution rights to the file itself and the directory it resides in.
This command will be executed on a server state change. The parameter should
be an absolute path to a command or the command should be in the executable
path. The user running MaxScale should have execution rights to the file itself
and the directory it resides in. The script may have placeholders which
MaxScale will substitute with useful information when launching the script.
The placeholders and their substition results are:
* `$INITIATOR` -> IP and port of the server which initiated the event
* `$EVENT` -> event description, e.g. "server_up"
* `$LIST` -> list of IPs and ports of all servers
* `$NODELIST` -> list of IPs and ports of all running servers
* `$SLAVELIST` -> list of IPs and ports of all slave servers
* `$MASTERLIST` -> list of IPs and ports of all master servers
* `$SYNCEDLIST` -> list of IPs and ports of all synced Galera nodes
* `$PARENT` -> IP and port of the parent of the server which initiated the event.
For master-slave setups, this will be the master if the initiating server is a
slave.
* `$CHILDREN` -> list of IPs and ports of the child nodes of the server who
initiated the event. For master-slave setups, this will be a list of slave
servers if the initiating server is a master.
The expanded variable value can be an empty string if no servers match the
variable's requirements. For example, if no masters are available `$MASTERLIST`
will expand into an empty string. The list-type substitutions will only contain
servers monitored by the current monitor.
```
script=/home/user/myscript.sh initiator=$INITIATOR event=$EVENT live_nodes=$NODELIST
```
The following substitutions will be made to the parameter value:
* `$INITIATOR` will be replaced with the IP and port of the server who initiated the event
* `$EVENT` will be replaced with the name of the event
* `$LIST` will be replaced with a list of server IPs and ports
* `$NODELIST` will be replaced with a list of server IPs and ports that are running
* `$SLAVELIST` will be replaced with a list of server IPs and ports that are slaves
* `$MASTERLIST` will be replaced with a list of server IPs and ports that are masters
* `$SYNCEDLIST` will be replaced with a list of server IPs and ports that are synced Galera nodes
* `$PARENT` will be replaced with the IP and port of the parent node of the server who initiated
the event. For master-slave setups, this will be the master if the initiating server is a slave.
* `$CHILDREN` will be replaced with the IPs and ports of the child nodes of the server who initiated
the event. For master-slave setups, this will be a list of slave servers if the initiating server is a master.
The expanded variable value can be an empty string if no servers match the
variable's requirements. For example, if no masters are available `$MASTERLIST`
will expand into an empty string.
For example, the previous example will be executed as:
The above script could be executed as:
```
/home/user/myscript.sh initiator=[192.168.0.10]:3306 event=master_down live_nodes=[192.168.0.201]:3306,[192.168.0.121]:3306
```
See section [Script example](#script-example) below for an example script.
Any output by the executed script will be logged into the MaxScale log. Each
outputted line will be logged as a separate log message.
@ -238,7 +249,7 @@ messages. If the first word in the output line is one of `alert:`, `error:`,
`warning:`, `notice:`, `info:` or `debug:`, the message will be logged on the
corresponding level. If the message is not prefixed with one of the keywords,
the message will be logged on the notice level. Whitespace before, after or
inbetween the keyword and the colon is ignored and the matching is
between the keyword and the colon is ignored and the matching is
case-insensitive.
### `script_timeout`
@ -310,3 +321,81 @@ name of the monitor section in the configuration file. If MaxScale crashes or is
shut down in an uncontrolled fashion, the journal will be read when MaxScale is
started. To skip the recovery process, manually delete the journal file before
starting MaxScale.
## Script example
Below is an example monitor configuration which launches a script with all
supported substitutions. The example script reads the results and prints it to
file and sends it as email.
```
[MyMonitor]
type=monitor
module=mariadbmon
servers=C1N1,C1N2,C1N3
user=maxscale
password=password
monitor_interval=10000
script=/path/to/maxscale_monitor_alert_script.sh --initiator=$INITIATOR --parent=$PARENT --children=$CHILDREN --event=$EVENT --node_list=$NODELIST --list=$LIST --master_list=$MASTERLIST --slave_list=$SLAVELIST --synced_list=$SYNCEDLIST
```
File "maxscale_monitor_alert_script.sh":
```
#!/usr/bin/env bash
initiator=""
parent=""
children=""
event=""
node_list=""
list=""
master_list=""
slave_list=""
synced_list=""
process_arguments()
{
while [ "$1" != "" ]; do
if [[ "$1" =~ ^--initiator=.* ]]; then
initiator=${1#'--initiator='}
elif [[ "$1" =~ ^--parent.* ]]; then
parent=${1#'--parent='}
elif [[ "$1" =~ ^--children.* ]]; then
children=${1#'--children='}
elif [[ "$1" =~ ^--event.* ]]; then
event=${1#'--event='}
elif [[ "$1" =~ ^--node_list.* ]]; then
node_list=${1#'--node_list='}
elif [[ "$1" =~ ^--list.* ]]; then
list=${1#'--list='}
elif [[ "$1" =~ ^--master_list.* ]]; then
master_list=${1#'--master_list='}
elif [[ "$1" =~ ^--slave_list.* ]]; then
slave_list=${1#'--slave_list='}
elif [[ "$1" =~ ^--synced_list.* ]]; then
synced_list=${1#'--synced_list='}
fi
shift
done
}
process_arguments $@
read -r -d '' MESSAGE << EOM
A server has changed state. The following information was provided:
Initiator: $initiator
Parent: $parent
Children: $children
Event: $event
Node list: $node_list
List: $list
Master list: $master_list
Slave list: $slave_list
Synced list: $synced_list
EOM
# print message to file
echo "$MESSAGE" > /path/to/script_output.txt
# email the message
echo "$MESSAGE" | mail -s "MaxScale received $event event for initiator $initiator." mariadb_admin@domain.com
```

View File

@ -212,6 +212,7 @@ struct DCB : public MXB_POLL_DATA
} thread;
uint32_t n_close = 0; /** How many times dcb_close has been called. */
uint64_t m_uid; /**< Unique identifier for this DCB */
bool is_fake_event = false;
};
/**

View File

@ -1972,7 +1972,9 @@ static void dcb_hangup_foreach_worker(MXB_WORKER* worker, struct SERVER* server)
if (!dcb->dcb_errhandle_called)
{
this_thread.current_dcb = dcb;
dcb->is_fake_event = true;
dcb->func.hangup(dcb);
dcb->is_fake_event = false;
dcb->dcb_errhandle_called = true;
}
}
@ -2801,7 +2803,9 @@ static uint32_t dcb_handler(DCB* dcb, uint32_t events)
events = dcb->fake_event;
dcb->fake_event = 0;
dcb->is_fake_event = true;
rv |= dcb_process_poll_events(dcb, events);
dcb->is_fake_event = false;
}
this_thread.current_dcb = NULL;

View File

@ -27,6 +27,8 @@
// For setting server status through monitor
#include "../../../../core/internal/monitormanager.hh"
#include <sstream>
/*
* MySQL Protocol module for handling the protocol between the gateway
* and the backend MySQL database.
@ -348,8 +350,8 @@ static void handle_error_response(DCB* dcb, GWBUF* buffer)
auto main_worker = mxs::RoutingWorker::get(mxs::RoutingWorker::MAIN);
auto target_server = dcb->server;
main_worker->execute([target_server]() {
MonitorManager::set_server_status(target_server, SERVER_MAINT);
}, mxb::Worker::EXECUTE_AUTO);
MonitorManager::set_server_status(target_server, SERVER_MAINT);
}, mxb::Worker::EXECUTE_AUTO);
MXS_ERROR("Server %s has been put into maintenance mode due to the server blocking connections "
"from MaxScale. Run 'mysqladmin -h %s -P %d flush-hosts' on this server before taking "
@ -590,6 +592,23 @@ static int gw_read_backend_event(DCB* dcb)
return rc;
}
static std::string get_detailed_error(DCB* dcb)
{
std::ostringstream ss;
if (int err = gw_getsockerrno(dcb->fd))
{
ss << " (" << err << ", " << mxs_strerror(err) << ")";
}
else if (dcb->is_fake_event)
{
// Fake events should not have TCP socket errors
ss << " (Generated event)";
}
return ss.str();
}
static void do_handle_error(DCB* dcb, mxs_error_action_t action, const char* errmsg)
{
bool succp = true;
@ -597,7 +616,7 @@ static void do_handle_error(DCB* dcb, mxs_error_action_t action, const char* err
mxb_assert(!dcb->dcb_errhandle_called);
GWBUF* errbuf = mysql_create_custom_error(1, 0, errmsg);
GWBUF* errbuf = mysql_create_custom_error(1, 0, (errmsg + get_detailed_error(dcb)).c_str());
MXS_ROUTER_SESSION* rsession = static_cast<MXS_ROUTER_SESSION*>(session->router_session);
MXS_ROUTER_OBJECT* router = session->service->router;
MXS_ROUTER* router_instance = session->service->router_instance;
@ -1342,7 +1361,7 @@ static int gw_error_backend_event(DCB* dcb)
}
else
{
do_handle_error(dcb, ERRACT_NEW_CONNECTION, "Lost connection to backend server.");
do_handle_error(dcb, ERRACT_NEW_CONNECTION, "Lost connection to backend server: network error");
}
return 1;
@ -1381,7 +1400,8 @@ static int gw_backend_hangup(DCB* dcb)
}
else
{
do_handle_error(dcb, ERRACT_NEW_CONNECTION, "Lost connection to backend server.");
do_handle_error(dcb, ERRACT_NEW_CONNECTION,
"Lost connection to backend server: connection closed by peer");
}
}