foundation for vrrp check scripts
diff --git a/README.rst b/README.rst
index e984b98..34d67ac 100644
--- a/README.rst
+++ b/README.rst
@@ -111,7 +111,7 @@
- 192.168.11.1
- 192.168.11.2
interface: eth0
- track_script: haproxy_check
+ track_script: check_haproxy
VIP3:
priority: 100
virtual_router_id: 11
@@ -120,9 +120,30 @@
- 192.168.10.1
- 192.168.10.2
interface: eth0
- track_script: random_check
+ track_script: check_random_exit
vrrp_scripts:
- random_check:
+ check_haproxy:
+ name: check_pidof
+ args:
+ - haproxy
+ check_mysql_port:
+ name: check_port
+ args:
+ - 3306
+ - TCP
+ - 4
+ check_ssh:
+ name: check_port
+ args: "22"
+ check_mysql_cluster:
+ args:
+ # github: olafz/percona-clustercheck
+ # <user> <pass> <available_when_donor=0|1> <log_file> <available_when_readonly=0|1> <defaults_extra_file>
+ - clustercheck
+ - clustercheck
+ - available_when_donor=0
+ - available_when_readonly=0
+ check_random_exit:
interval: 10
content: |
#!/bin/bash
diff --git a/keepalived/cluster.sls b/keepalived/cluster.sls
index 0747411..63bab46 100644
--- a/keepalived/cluster.sls
+++ b/keepalived/cluster.sls
@@ -41,17 +41,19 @@
{% endfor %}
+{%- set _deployed = [] %}
{%- for name, script in cluster.get('vrrp_scripts', {}).iteritems() %}
-keepalived_vrrp_script_{{ name }}:
+{%- if script.get('name', name) not in _deployed %}keepalived_vrrp_script_{{ script.get('name', name) }}:{% else %}{% continue %}{% endif %}
+{%- do _deployed.append(script.get('name', name)) %}
file.managed:
- - name: /usr/local/bin/vrrp_script_{{ name }}.sh
+ - name: /usr/local/bin/vrrp_script_{{ script.get('name', name) }}.sh
- mode: 755
- source:
- - salt://keepalived/files/vrrp_script_{{ name }}.sh
+ - salt://keepalived/files/vrrp_script_{{ script.get('name', name) }}.sh
- salt://keepalived/files/vrrp_script.sh
- template: jinja
- defaults:
- script: {{ script|yaml }}
+ script: {{ script|yaml }}
- require_in:
- service: keepalived_service
{% endfor %}
diff --git a/keepalived/files/keepalived.conf b/keepalived/files/keepalived.conf
index 7767963..cc3c3d5 100644
--- a/keepalived/files/keepalived.conf
+++ b/keepalived/files/keepalived.conf
@@ -4,7 +4,10 @@
{%- for name, script in cluster.get('vrrp_scripts', {}).iteritems() %}
vrrp_script {{ name }} {
- script "/usr/local/bin/vrrp_script_{{ name }}.sh"
+{%- if script.name is defined %}
+{%- set name=script.name %}
+{%- endif %}
+ script "/usr/local/bin/vrrp_script_{{ name }}.sh '{{ "' '".join(script.get('args', [])|sequence) }}'"
interval {{ script.get('interval', 2) }} # check every Ns
weight {{ script.get('weight', 2) }}
fall {{ script.get('fall', 2) }} # require N failures for KO
diff --git a/keepalived/files/vrrp_script_check_mysql_cluster.sh b/keepalived/files/vrrp_script_check_mysql_cluster.sh
new file mode 100644
index 0000000..0a57a11
--- /dev/null
+++ b/keepalived/files/vrrp_script_check_mysql_cluster.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+#
+# Script to make a proxy (ie HAProxy) capable of monitoring Percona XtraDB Cluster nodes properly
+#
+# Author: Olaf van Zandwijk <olaf.vanzandwijk@nedap.com>
+# Author: Raghavendra Prabhu <raghavendra.prabhu@percona.com>
+#
+# Documentation and download: https://github.com/olafz/percona-clustercheck
+#
+# Based on the original script from Unai Rodriguez
+#
+
+if [[ $1 == '-h' || $1 == '--help' ]];then
+ echo "Usage: $0 <user> <pass> <available_when_donor=0|1> <log_file> <available_when_readonly=0|1> <defaults_extra_file>"
+ exit
+fi
+
+# if the disabled file is present, return 503. This allows
+# admins to manually remove a node from a cluster easily.
+if [ -e "/var/tmp/clustercheck.disabled" ]; then
+ # Shell return-code is 1
+ echo -en "HTTP/1.1 503 Service Unavailable\r\n"
+ echo -en "Content-Type: text/plain\r\n"
+ echo -en "Connection: close\r\n"
+ echo -en "Content-Length: 51\r\n"
+ echo -en "\r\n"
+ echo -en "Percona XtraDB Cluster Node is manually disabled.\r\n"
+ sleep 0.1
+ exit 1
+fi
+
+MYSQL_USERNAME="${1-clustercheckuser}"
+MYSQL_PASSWORD="${2-clustercheckpassword!}"
+AVAILABLE_WHEN_DONOR=${3:-0}
+ERR_FILE="${4:-/dev/null}"
+AVAILABLE_WHEN_READONLY=${5:-1}
+DEFAULTS_EXTRA_FILE=${6:-/etc/my.cnf}
+
+#Timeout exists for instances where mysqld may be hung
+TIMEOUT=10
+
+EXTRA_ARGS=""
+if [[ -n "$MYSQL_USERNAME" ]]; then
+ EXTRA_ARGS="$EXTRA_ARGS --user=${MYSQL_USERNAME}"
+fi
+if [[ -n "$MYSQL_PASSWORD" ]]; then
+ EXTRA_ARGS="$EXTRA_ARGS --password=${MYSQL_PASSWORD}"
+fi
+if [[ -r $DEFAULTS_EXTRA_FILE ]];then
+ MYSQL_CMDLINE="mysql --defaults-extra-file=$DEFAULTS_EXTRA_FILE -nNE --connect-timeout=$TIMEOUT \
+ ${EXTRA_ARGS}"
+else
+ MYSQL_CMDLINE="mysql -nNE --connect-timeout=$TIMEOUT ${EXTRA_ARGS}"
+fi
+#
+# Perform the query to check the wsrep_local_state
+#
+WSREP_STATUS=$($MYSQL_CMDLINE -e "SHOW STATUS LIKE 'wsrep_local_state';" \
+ 2>${ERR_FILE} | tail -1 2>>${ERR_FILE})
+
+if [[ "${WSREP_STATUS}" == "4" ]] || [[ "${WSREP_STATUS}" == "2" && ${AVAILABLE_WHEN_DONOR} == 1 ]]
+then
+ # Check only when set to 0 to avoid latency in response.
+ if [[ $AVAILABLE_WHEN_READONLY -eq 0 ]];then
+ READ_ONLY=$($MYSQL_CMDLINE -e "SHOW GLOBAL VARIABLES LIKE 'read_only';" \
+ 2>${ERR_FILE} | tail -1 2>>${ERR_FILE})
+
+ if [[ "${READ_ONLY}" == "ON" ]];then
+ # Percona XtraDB Cluster node local state is 'Synced', but it is in
+ # read-only mode. The variable AVAILABLE_WHEN_READONLY is set to 0.
+ # => return HTTP 503
+ # Shell return-code is 1
+ echo -en "HTTP/1.1 503 Service Unavailable\r\n"
+ echo -en "Content-Type: text/plain\r\n"
+ echo -en "Connection: close\r\n"
+ echo -en "Content-Length: 43\r\n"
+ echo -en "\r\n"
+ echo -en "Percona XtraDB Cluster Node is read-only.\r\n"
+ sleep 0.1
+ exit 1
+ fi
+ fi
+ # Percona XtraDB Cluster node local state is 'Synced' => return HTTP 200
+ # Shell return-code is 0
+ echo -en "HTTP/1.1 200 OK\r\n"
+ echo -en "Content-Type: text/plain\r\n"
+ echo -en "Connection: close\r\n"
+ echo -en "Content-Length: 40\r\n"
+ echo -en "\r\n"
+ echo -en "Percona XtraDB Cluster Node is synced.\r\n"
+ sleep 0.1
+ exit 0
+else
+ # Percona XtraDB Cluster node local state is not 'Synced' => return HTTP 503
+ # Shell return-code is 1
+ echo -en "HTTP/1.1 503 Service Unavailable\r\n"
+ echo -en "Content-Type: text/plain\r\n"
+ echo -en "Connection: close\r\n"
+ echo -en "Content-Length: 44\r\n"
+ echo -en "\r\n"
+ echo -en "Percona XtraDB Cluster Node is not synced.\r\n"
+ sleep 0.1
+ exit 1
+fi
diff --git a/keepalived/files/vrrp_script_check_pidof.sh b/keepalived/files/vrrp_script_check_pidof.sh
new file mode 100644
index 0000000..90f2559
--- /dev/null
+++ b/keepalived/files/vrrp_script_check_pidof.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+set -o errexit
+pidof $@
diff --git a/keepalived/files/vrrp_script_check_port.sh b/keepalived/files/vrrp_script_check_port.sh
new file mode 100755
index 0000000..ee610ad
--- /dev/null
+++ b/keepalived/files/vrrp_script_check_port.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $1 PORT
+# $2 [TCP|UDP]
+# $3 inet family [4|6]
+lsof -i${3}${2}:${1} | grep 'LISTEN'
diff --git a/keepalived/map.jinja b/keepalived/map.jinja
index deb2572..2ce637d 100644
--- a/keepalived/map.jinja
+++ b/keepalived/map.jinja
@@ -1,13 +1,13 @@
{% set cluster = salt['grains.filter_by']({
'Debian': {
- 'pkgs': ['keepalived'],
+ 'pkgs': ['keepalived', 'lsof'],
'collectd_pkgs': ['python-pyroute2'],
'service': 'keepalived',
'config': '/etc/keepalived/keepalived.conf',
'instance': {}
},
'RedHat': {
- 'pkgs': ['keepalived'],
+ 'pkgs': ['keepalived', 'lsof'],
'service': 'keepalived',
'config': '/etc/keepalived/keepalived.conf',
'instance': {}
diff --git a/tests/pillar/keepalived_cluster.sls b/tests/pillar/keepalived_cluster.sls
index 8dbb4ae..73de34c 100644
--- a/tests/pillar/keepalived_cluster.sls
+++ b/tests/pillar/keepalived_cluster.sls
@@ -18,9 +18,52 @@
- 192.168.10.1
- 192.168.10.2
interface: eth0
- track_script: random_check
+ track_script: check_random_exit
+ VIP2:
+ priority: 100
+ virtual_router_id: 12
+ password: pass
+ addresses:
+ - 192.168.12.1
+ - 192.168.12.2
+ interface: eth0
+ track_script: check_haproxy
+ VIP3:
+ priority: 100
+ virtual_router_id: 13
+ password: pass
+ addresses:
+ - 192.168.13.1
+ - 192.168.13.2
+ interface: eth0
+ track_script: check_mysql_cluster
+ VIP4:
+ priority: 100
+ virtual_router_id: 14
+ password: pass
+ addresses:
+ - 192.168.14.1
+ - 192.168.14.2
+ interface: eth0
+ track_script: check_ssh_port
vrrp_scripts:
- random_check:
+ check_ssh_port:
+ name: check_port
+ args: "22"
+ check_mysql_cluster:
+ args:
+ - clustercheck
+ - clustercheck
+ - available_when_donor=0
+ - available_when_readonly=0
+ check_haproxy:
+ name: check_pidof
+ args: haproxy
+ check_haproxy2:
+ name: check_pidof
+ args:
+ - haproxy
+ check_random_exit:
interval: 10
content: |
#!/bin/bash