@@ -14,6 +14,13 @@ provisioner: | |||
formula: galera | |||
grains: | |||
noservices: True | |||
dependencies: | |||
- name: mysql | |||
repo: git | |||
source: https://github.com/salt-formulas/salt-formula-mysql.git | |||
- name: linux | |||
repo: git | |||
source: https://github.com/salt-formulas/salt-formula-linux.git | |||
state_top: | |||
base: | |||
"*": | |||
@@ -23,18 +30,29 @@ provisioner: | |||
top.sls: | |||
base: | |||
"*": | |||
- versions | |||
- repos_base | |||
- repos | |||
- galera | |||
- galeracluster_debian_repo | |||
versions.sls: | |||
galera: | |||
version: | |||
mysql: <%= ENV['MYSQL_VER'] || '5.6' %> | |||
galera: <%= ENV['GALERA_VER'] || '3' %> | |||
# NOTE(vsaienko) There is no guarntee that pillars are loaded before pillars-from-file | |||
# as result we cant assume variables defined via pillars: are available when pillars-from-file | |||
# is loaded. Move 'source' definitions of repos to .kitchen.yml as it used ENV variable | |||
repos_base.sls: | |||
linux: | |||
system: | |||
enabled: true | |||
repo: | |||
galeracluster: | |||
source: deb http://releases.galeracluster.com/galera-<%=ENV['GALERA_VER'] || '3'%>/ubuntu {{ grains.get('oscodename') }} main | |||
mysql-wsrep: | |||
source: deb http://releases.galeracluster.com/mysql-wsrep-<%=ENV['MYSQL_VER'] || '5.6'%>/ubuntu {{ grains.get('oscodename') }} main | |||
pillars-from-files: | |||
galeracluster_debian_repo.sls: tests/pillar/repo_galeracluster.sls | |||
dependencies: | |||
- name: mysql | |||
repo: git | |||
source: https://github.com/salt-formulas/salt-formula-mysql.git | |||
dependencies: | |||
- name: linux | |||
repo: git | |||
source: https://github.com/salt-formulas/salt-formula-linux.git | |||
repos.sls: tests/pillar/repo_galeracluster.sls | |||
verifier: | |||
name: inspec |
@@ -17,15 +17,22 @@ install: | |||
- bundle install | |||
env: | |||
- PLATFORM=trevorj/salty-whales:trusty | |||
- PLATFORM=trevorj/salty-whales:xenial | |||
- PLATFORM=trevorj/salty-whales:trusty SUITE=master-cluster MYSQL_VER=5.6 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:xenial SUITE=master-cluster MYSQL_VER=5.6 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:trusty SUITE=slave-cluster MYSQL_VER=5.6 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:xenial SUITE=slave-cluster MYSQL_VER=5.6 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:trusty SUITE=master-cluster MYSQL_VER=5.7 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:xenial SUITE=master-cluster MYSQL_VER=5.7 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:trusty SUITE=slave-cluster MYSQL_VER=5.7 GALERA_VER=3 | |||
- PLATFORM=trevorj/salty-whales:xenial SUITE=slave-cluster MYSQL_VER=5.7 GALERA_VER=3 | |||
before_script: | |||
- set -o pipefail | |||
- make test | tail | |||
script: | |||
- test ! -e .kitchen.yml || bundle exec kitchen test -t tests/integration | |||
- test ! -e .kitchen.yml || bundle exec kitchen converge ${SUITE} || true | |||
- test ! -e .kitchen.yml || bundle exec kitchen verify ${SUITE} -t tests/integration | |||
notifications: | |||
webhooks: |
@@ -13,6 +13,9 @@ Galera cluster master node | |||
.. code-block:: yaml | |||
galera: | |||
version: | |||
mysql: 5.6 | |||
galera: 3 | |||
master: | |||
enabled: true | |||
name: openstack | |||
@@ -56,13 +59,102 @@ Galera cluster slave node | |||
user: root | |||
password: pass | |||
Enable TLS support: | |||
.. code-block:: yaml | |||
galera: | |||
slave or master: | |||
ssl: | |||
enabled: True | |||
# path | |||
cert_file: /etc/mysql/ssl/cert.pem | |||
key_file: /etc/mysql/ssl/key.pem | |||
ca_file: /etc/mysql/ssl/ca.pem | |||
# content (not required if files already exists) | |||
key: << body of key >> | |||
cert: << body of cert >> | |||
cacert_chain: << body of ca certs chain >> | |||
Additional mysql users: | |||
.. code-block:: yaml | |||
mysql: | |||
server: | |||
users: | |||
- name: clustercheck | |||
password: clustercheck | |||
database: '*.*' | |||
grants: PROCESS | |||
- name: inspector | |||
host: 127.0.0.1 | |||
password: password | |||
databases: | |||
mydb: | |||
- database: mydb | |||
- table: mytable | |||
- grant_option: True | |||
- grants: | |||
- all privileges | |||
Additional mysql SSL grants: | |||
.. code-block:: yaml | |||
mysql: | |||
server: | |||
users: | |||
- name: clustercheck | |||
password: clustercheck | |||
database: '*.*' | |||
grants: PROCESS | |||
ssl_option: | |||
- SSL: True | |||
- X509: True | |||
- SUBJECT: <subject> | |||
- ISSUER: <issuer> | |||
- CIPHER: <cipher> | |||
Additional check params: | |||
======================== | |||
.. code-block:: yaml | |||
galera: | |||
clustercheck: | |||
- enabled: True | |||
- user: clustercheck | |||
- password: clustercheck | |||
- available_when_donor: 0 | |||
- available_when_readonly: 1 | |||
- port 9200 | |||
Configurable soft parameters | |||
============================ | |||
- **galera_innodb_buffer_pool_size** - the default value is 3138M | |||
- **galera_max_connections** - the default value is 20000 | |||
Usage: | |||
.. code-block:: yaml | |||
_param: | |||
galera_innodb_buffer_pool_size: 1024M | |||
galera_max_connections: 200 | |||
Usage | |||
===== | |||
MySQL Galera check sripts | |||
.. code-block:: bash | |||
mysql> SHOW STATUS LIKE 'wsrep%'; | |||
mysql> SHOW STATUS LIKE 'wsrep_cluster_size' ;" | |||
@@ -80,15 +172,15 @@ Galera monitoring command, performed from extra server | |||
.. code-block:: bash | |||
Enter current password for root (enter for none): | |||
Enter current password for root (enter for none): | |||
OK, successfully used password, moving on... | |||
Setting the root password ensures that nobody can log into the MySQL | |||
root user without the proper authorisation. | |||
Set root password? [Y/n] y | |||
New password: | |||
Re-enter new password: | |||
New password: | |||
Re-enter new password: | |||
Password updated successfully! | |||
Reloading privilege tables.. | |||
... Success! | |||
@@ -127,7 +219,7 @@ Galera monitoring command, performed from extra server | |||
Cleaning up... | |||
5. service mysql stop | |||
6. uncomment all wsrep* lines except first server, where leave only in my.cnf wsrep_cluster_address='gcomm://'; | |||
6. uncomment all wsrep* lines except first server, where leave only in my.cnf wsrep_cluster_address='gcomm://'; | |||
7. start first node | |||
8. Start third node which is connected to first one | |||
9. Start second node which is connected to third one |
@@ -11,6 +11,6 @@ Vcs-Git: https://github.com/tcpcloud/salt-formula-galera.git | |||
Package: salt-formula-galera | |||
Architecture: all | |||
Depends: ${misc:Depends}, salt-master, reclass, salt-formula-mysql | |||
Depends: ${misc:Depends}, salt-formula-mysql | |||
Description: galera salt formula | |||
Install and configure galera system. |
@@ -0,0 +1,107 @@ | |||
{%- from "galera/map.jinja" import master, slave with context %} | |||
{%- if master.get('enabled', False) %} | |||
{%- set service, role = master, 'master' %} | |||
{%- elif slave.get('enabled', False) %} | |||
{%- set service, role = slave, 'slave' %} | |||
{%- endif %} | |||
{%- if service.get('ssl', {}).get('enabled', False) %} | |||
galera_ssl_dir: | |||
file.directory: | |||
- name: /etc/mysql/ssl | |||
- makedirs: true | |||
- mode: 755 | |||
- require: | |||
- pkg: galera_packages | |||
{%- if service.ssl.cacert_chain is defined %} | |||
mysql_cacertificate: | |||
file.managed: | |||
- name: {{ service.ssl.ca_file }} | |||
- contents_pillar: galera:{{ role }}:ssl:cacert_chain | |||
- mode: 0444 | |||
- makedirs: true | |||
- require_in: | |||
- service: galera_service | |||
- file: galera_config | |||
{%- else %} | |||
mysql_cacertificate_exists: | |||
file.exists: | |||
- name: {{ service.ssl.ca_file }} | |||
mysql_cacertificate: | |||
file.managed: | |||
- name: {{ service.ssl.ca_file }} | |||
- mode: 644 | |||
- create: False | |||
- require: | |||
- file: mysql_cacertificate_exists | |||
- file: galera_ssl_dir | |||
- require_in: | |||
- service: galera_service | |||
- file: galera_config | |||
{%- endif %} | |||
{%- if service.ssl.cert is defined %} | |||
mysql_certificate: | |||
file.managed: | |||
- name: {{ service.ssl.cert_file }} | |||
- contents_pillar: galera:{{ role }}:ssl:cert | |||
- mode: 0444 | |||
- makedirs: true | |||
- require_in: | |||
- service: galera_service | |||
- file: galera_config | |||
{%- else %} | |||
mysql_certificate_exists: | |||
file.exists: | |||
- name: {{ service.ssl.cert_file }} | |||
mysql_certificate: | |||
file.managed: | |||
- name: {{ service.ssl.cert_file }} | |||
- mode: 644 | |||
- create: False | |||
- require: | |||
- file: mysql_certificate_exists | |||
- file: galera_ssl_dir | |||
- require_in: | |||
- service: galera_service | |||
- file: galera_config | |||
{%- endif %} | |||
{%- if service.ssl.key is defined %} | |||
mysql_server_key: | |||
file.managed: | |||
- name: {{ service.ssl.key_file }} | |||
- contents_pillar: galera:{{ role }}:ssl:key | |||
- user: root | |||
- group: mysql | |||
- mode: 0440 | |||
- makedirs: true | |||
- require: | |||
- pkg: galera_packages | |||
- file: galera_ssl_dir | |||
- require_in: | |||
- service: galera_service | |||
- file: galera_config | |||
{%- else %} | |||
mysql_server_key_exists: | |||
file.exists: | |||
- name: {{ service.ssl.key_file }} | |||
mysql_server_key: | |||
file.managed: | |||
- name: {{ service.ssl.key_file }} | |||
- user: root | |||
- group: mysql | |||
- mode: 0440 | |||
- create: False | |||
- require: | |||
- file: mysql_server_key_exists | |||
- pkg: galera_packages | |||
- file: galera_ssl_dir | |||
- require_in: | |||
- service: galera_service | |||
- file: galera_config | |||
{%- endif %} | |||
{%- endif %} |
@@ -0,0 +1,45 @@ | |||
{%- from "galera/map.jinja" import clustercheck with context %} | |||
{%- if clustercheck.get('enabled', False) %} | |||
/usr/local/bin/mysql_clustercheck: | |||
file.managed: | |||
- source: salt://galera/files/clustercheck.sh | |||
- user: root | |||
- group: root | |||
- mode: 755 | |||
- dir_mode: 755 | |||
- makedirs: True | |||
/etc/xinetd.d/mysql_clustercheck: | |||
file.managed: | |||
- source: salt://galera/files/xinet.d.conf | |||
- template: jinja | |||
- makedirs: True | |||
- defaults: | |||
name: mysqlchk | |||
user: nobody | |||
server: '/usr/local/bin/mysql_clustercheck' | |||
server_args: '{{ clustercheck.get('user', 'clustercheck') }} {{ clustercheck.get('password', 'clustercheck') }} available_when_donor={{ clustercheck.get('available_when_donor', 0) }} /dev/null available_when_readonly={{ clustercheck.get('available_when_readonly', 0) }} {{ clustercheck.config }}' | |||
port: {{ clustercheck.get('port', 9200) }} | |||
flags: REUSE | |||
per_source: UNLIMITED | |||
- require: | |||
- file: /usr/local/bin/mysql_clustercheck | |||
{%- if not grains.get('noservices', False) %} | |||
- watch_in: | |||
- galera_xinetd_service | |||
{%- endif %} | |||
galera_xinetd_package: | |||
pkg.installed: | |||
- name: xinetd | |||
{%- if not grains.get('noservices', False) %} | |||
galera_xinetd_service: | |||
service.running: | |||
- name: xinetd | |||
- require: | |||
- pkg: xinetd | |||
{%- endif %} | |||
{%- endif %} | |||
@@ -0,0 +1,138 @@ | |||
#!/bin/bash | |||
# | |||
# Script to make a proxy (ie HAProxy) capable of monitoring MySQL Cluster nodes properly | |||
# | |||
# Author: Olaf van Zandwijk <olaf.vanzandwijk@nedap.com> | |||
# Author: Raghavendra Prabhu <raghavendra.prabhu@percona.com> | |||
# Author: Petr Michalec <pmichalec@mirantis.com> | |||
# | |||
# Documentation and download: https://github.com/epcim/percona-clustercheck | |||
# | |||
# Based on the original script from Unai Rodriguez | |||
# | |||
function httpReply(){ | |||
HTTP_STATUS="${1}" | |||
RESPONSE_CONTENT="${2}" | |||
# https://serverfault.com/questions/504756/curl-failure-when-receiving-data-from-peer-using-percona-xtradb-cluster-check | |||
sleep 0.1 | |||
if [[ "${HTTP_STATUS}" == "503" ]] | |||
then | |||
echo -en "HTTP/1.1 503 Service Unavailable\r\n" | |||
elif [[ "${HTTP_STATUS}" == "404" ]] | |||
then | |||
echo -en "HTTP/1.1 404 Not Found\r\n" | |||
elif [[ "${HTTP_STATUS}" == "401" ]] | |||
then | |||
echo -en "HTTP/1.1 401 Unauthorized\r\n" | |||
elif [[ "${HTTP_STATUS}" == "200" ]] | |||
then | |||
echo -en "HTTP/1.1 200 OK\r\n" | |||
else | |||
echo -en "HTTP/1.1 ${HTTP_STATUS}\r\n" | |||
fi | |||
echo -en "Content-Type: text/plain\r\n" | |||
echo -en "Connection: close\r\n" | |||
echo -en "Content-Length: ${#RESPONSE_CONTENT}\r\n" | |||
echo -en "\r\n" | |||
echo -en "${RESPONSE_CONTENT}" | |||
echo -en "\r\n" | |||
sleep 0.1 | |||
} | |||
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> <timeout>" | |||
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 | |||
httpReply "503" "MySQL Cluster Node is manually disabled.\r\n" | |||
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 | |||
# Default value considers the Galera timeouts | |||
TIMEOUT=${7:-18} | |||
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}; exit ${PIPESTATUS[0]}) | |||
mysql_ret=$? | |||
if [[ $mysql_ret -eq 1 || $mysql_ret -eq 127 ]]; then | |||
# hash or command can be used here, but command is POSIX | |||
command -v "$MYSQL_CMD"; mysql_ret=$? | |||
if [[ $mysql_ret -eq 1 ]]; then | |||
# mysql program not found | |||
# => return HTTP 404 | |||
# Shell return-code is 3 | |||
httpReply "404" "Mysql command not found or service is not running.\r\n" | |||
exit 2 | |||
fi | |||
# Failed mysql login | |||
# => return HTTP 401 | |||
# Shell return-code is 2 | |||
httpReply "401" "Access denied to database.\r\n" | |||
exit 2 | |||
fi | |||
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 | |||
# MySQL 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 | |||
httpReply "503" "MySQL Cluster Node is read-only.\r\n" | |||
exit 1 | |||
fi | |||
fi | |||
# MySQL Cluster node local state is 'Synced' => return HTTP 200 | |||
# Shell return-code is 0 | |||
httpReply "200" "MySQL Cluster Node is synced.\r\n" | |||
exit 0 | |||
else | |||
# MySQL Cluster node local state is not 'Synced' => return HTTP 503 | |||
# Shell return-code is 1 | |||
if [[ -z "${WSREP_STATUS}" ]] | |||
then | |||
httpReply "503" "Received empty reply from MySQL Cluster Node.\r\nMight be a permission issue, check the credentials used by ${0}\r\n" | |||
else | |||
httpReply "503" "MySQL Cluster Node is not synced.\r\n" | |||
fi | |||
exit 1 | |||
fi |
@@ -1,8 +1,8 @@ | |||
{%- if pillar.galera.master is defined %} | |||
{%- if pillar.galera.get('master',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import master with context %} | |||
{%- set service = master %} | |||
{%- endif %} | |||
{%- if pillar.galera.slave is defined %} | |||
{%- if pillar.galera.get('slave',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import slave with context %} | |||
{%- set service = slave %} | |||
{%- endif %} |
@@ -0,0 +1,930 @@ | |||
{ | |||
"annotations": { | |||
"enable": false, | |||
"list": [] | |||
}, | |||
"editable": true, | |||
"gnetId": null, | |||
"graphTooltip": 1, | |||
"hideControls": false, | |||
"id": null, | |||
"links": [], | |||
"refresh": "1m", | |||
"rows": [ | |||
{ | |||
"collapse": false, | |||
"height": 250, | |||
"panels": [ | |||
{ | |||
"cacheTimeout": null, | |||
"colorBackground": false, | |||
"colorValue": false, | |||
"colors": [ | |||
"rgba(245, 54, 54, 0.9)", | |||
"rgba(237, 129, 40, 0.89)", | |||
"rgba(50, 172, 45, 0.97)" | |||
], | |||
"datasource": null, | |||
"description": "Displays the number of nodes in the cluster.", | |||
"format": "none", | |||
"gauge": { | |||
"maxValue": 100, | |||
"minValue": 0, | |||
"show": false, | |||
"thresholdLabels": false, | |||
"thresholdMarkers": true | |||
}, | |||
"id": 32, | |||
"interval": null, | |||
"links": [], | |||
"mappingType": 1, | |||
"mappingTypes": [ | |||
{ | |||
"name": "value to text", | |||
"value": 1 | |||
}, | |||
{ | |||
"name": "range to text", | |||
"value": 2 | |||
} | |||
], | |||
"maxDataPoints": 100, | |||
"nullPointMode": "connected", | |||
"nullText": null, | |||
"postfix": "", | |||
"postfixFontSize": "50%", | |||
"prefix": "", | |||
"prefixFontSize": "50%", | |||
"rangeMaps": [ | |||
{ | |||
"from": "null", | |||
"text": "N/A", | |||
"to": "null" | |||
} | |||
], | |||
"span": 2, | |||
"sparkline": { | |||
"fillColor": "rgba(31, 118, 189, 0.18)", | |||
"full": false, | |||
"lineColor": "rgb(31, 120, 193)", | |||
"show": true | |||
}, | |||
"tableColumn": "", | |||
"targets": [ | |||
{ | |||
"expr": "min(mysql_wsrep_cluster_size)", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "", | |||
"metric": "mysql_wsrep_cluster_size", | |||
"refId": "A", | |||
"step": 60 | |||
} | |||
], | |||
"thresholds": "", | |||
"title": "Cluster size", | |||
"type": "singlestat", | |||
"valueFontSize": "80%", | |||
"valueMaps": [ | |||
{ | |||
"op": "=", | |||
"text": "N/A", | |||
"value": "null" | |||
} | |||
], | |||
"valueName": "current" | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"description": "Displays the average sizes of receive and send queues.", | |||
"fill": 0, | |||
"id": 31, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 5, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "mysql_wsrep_local_recv_queue_avg{host=\"$host\"}", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "receive", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "mysql_wsrep_local_send_queue_avg{host=\"$host\"}", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "send", | |||
"refId": "B", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Queues", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"description": "Displays the rate of flow control events.", | |||
"fill": 0, | |||
"id": 33, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 5, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "irate(mysql_wsrep_flow_control_recv{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "receive", | |||
"metric": "", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_wsrep_flow_control_sent{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "send", | |||
"refId": "B", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Flow control", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "ops", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
} | |||
], | |||
"repeat": null, | |||
"repeatIteration": null, | |||
"repeatRowId": null, | |||
"showTitle": true, | |||
"title": "Replication", | |||
"titleSize": "h6" | |||
}, | |||
{ | |||
"collapse": false, | |||
"height": "250px", | |||
"panels": [ | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"fill": 0, | |||
"id": 26, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 6, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "irate(mysql_bytes_received{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"interval": "", | |||
"intervalFactor": 2, | |||
"legendFormat": "rx", | |||
"metric": "", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_bytes_sent{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"interval": "", | |||
"intervalFactor": 2, | |||
"legendFormat": "tx", | |||
"metric": "", | |||
"refId": "B", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Network I/O", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "Bps", | |||
"label": "", | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"fill": 0, | |||
"id": 27, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 6, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "irate(mysql_table_locks_immediate{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "immediate", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_table_locks_waited{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "waited", | |||
"refId": "B", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Locks", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "ops", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"fill": 0, | |||
"id": 28, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 6, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "mysql_threads_cached{host=\"$host\"}", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "cached", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "mysql_threads_connected{host=\"$host\"}", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "connected", | |||
"refId": "B", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "mysql_threads_running{host=\"$host\"}", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "running", | |||
"refId": "D", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Threads", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"fill": 1, | |||
"id": 34, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 6, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "irate(mysql_queries{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "queries", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_questions{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "questions", | |||
"refId": "B", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Queries", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "ops", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": "", | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"fill": 0, | |||
"id": 29, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 6, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "irate(mysql_commands_commit{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "commit", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_commands_delete{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "delete", | |||
"refId": "B", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_commands_insert{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "insert", | |||
"refId": "C", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_commands_select{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "select", | |||
"refId": "D", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_commands_rollback{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "rollback", | |||
"refId": "E", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_commands_update{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "update", | |||
"refId": "F", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Commands", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "ops", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
}, | |||
{ | |||
"aliasColors": {}, | |||
"bars": false, | |||
"dashLength": 10, | |||
"dashes": false, | |||
"datasource": null, | |||
"fill": 0, | |||
"id": 30, | |||
"legend": { | |||
"avg": false, | |||
"current": false, | |||
"max": false, | |||
"min": false, | |||
"show": true, | |||
"total": false, | |||
"values": false | |||
}, | |||
"lines": true, | |||
"linewidth": 1, | |||
"links": [], | |||
"nullPointMode": "null", | |||
"percentage": false, | |||
"pointradius": 5, | |||
"points": false, | |||
"renderer": "flot", | |||
"seriesOverrides": [], | |||
"spaceLength": 10, | |||
"span": 6, | |||
"stack": false, | |||
"steppedLine": false, | |||
"targets": [ | |||
{ | |||
"expr": "irate(mysql_handler_commit{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "commit", | |||
"refId": "A", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_handler_delete{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "delete", | |||
"refId": "B", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_handler_write{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "write", | |||
"refId": "C", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_handler_rollback{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "rollback", | |||
"refId": "E", | |||
"step": 10 | |||
}, | |||
{ | |||
"expr": "irate(mysql_handler_update{host=\"$host\"}[1m])", | |||
"format": "time_series", | |||
"intervalFactor": 2, | |||
"legendFormat": "update", | |||
"refId": "F", | |||
"step": 10 | |||
} | |||
], | |||
"thresholds": [], | |||
"timeFrom": null, | |||
"timeShift": null, | |||
"title": "Handlers", | |||
"tooltip": { | |||
"shared": true, | |||
"sort": 0, | |||
"value_type": "individual" | |||
}, | |||
"type": "graph", | |||
"xaxis": { | |||
"buckets": null, | |||
"mode": "time", | |||
"name": null, | |||
"show": true, | |||
"values": [] | |||
}, | |||
"yaxes": [ | |||
{ | |||
"format": "ops", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": "0", | |||
"show": true | |||
}, | |||
{ | |||
"format": "short", | |||
"label": null, | |||
"logBase": 1, | |||
"max": null, | |||
"min": null, | |||
"show": true | |||
} | |||
] | |||
} | |||
], | |||
"repeat": null, | |||
"repeatIteration": null, | |||
"repeatRowId": null, | |||
"showTitle": true, | |||
"title": "MySQL", | |||
"titleSize": "h6" | |||
} | |||
], | |||
"schemaVersion": 14, | |||
"sharedCrosshair": true, | |||
"style": "dark", | |||
"tags": [], | |||
"templating": { | |||
"enable": true, | |||
"list": [ | |||
{ | |||
"allFormat": "glob", | |||
"allValue": null, | |||
"current": {}, | |||
"datasource": "prometheus", | |||
"hide": 0, | |||
"includeAll": false, | |||
"label": null, | |||
"multi": false, | |||
"name": "host", | |||
"options": [], | |||
"query": "label_values(mysql_connections,host)", | |||
"refresh": 1, | |||
"refresh_on_load": true, | |||
"regex": "", | |||
"sort": 1, | |||
"tagValuesQuery": "", | |||
"tags": [], | |||
"tagsQuery": "", | |||
"type": "query", | |||
"useTags": false | |||
} | |||
] | |||
}, | |||
"time": { | |||
"from": "now-1h", | |||
"to": "now" | |||
}, | |||
"timepicker": { | |||
"collapse": false, | |||
"enable": true, | |||
"notice": false, | |||
"now": true, | |||
"refresh_intervals": [ | |||
"5s", | |||
"10s", | |||
"30s", | |||
"1m", | |||
"5m", | |||
"15m", | |||
"30m", | |||
"1h", | |||
"2h", | |||
"1d" | |||
], | |||
"status": "Stable", | |||
"time_options": [ | |||
"5m", | |||
"15m", | |||
"1h", | |||
"6h", | |||
"12h", | |||
"24h", | |||
"2d", | |||
"7d", | |||
"30d" | |||
], | |||
"type": "timepicker" | |||
}, | |||
"timezone": "browser", | |||
"title": "MySQL", | |||
"version": 33 | |||
} |
@@ -7,7 +7,7 @@ retries=0 | |||
while [ $counter -gt 0 ] | |||
do | |||
if mysql -u root -e"quit"; then | |||
if mysql -u root -e"quit" || mysql -u {{ service.admin.user }} -p{{ service.admin.password }} -e"quit"; then | |||
echo "Sucessfully connected to the MySQL service ($retries retries)." | |||
exit 0 | |||
fi |
@@ -1,14 +1,22 @@ | |||
# All files in this package is subject to the GPL v2 license | |||
# More information is in the COPYING file in the top directory of this package. | |||
# Copyright (C) 2011 severalnines.com | |||
{%- if pillar.galera.master is defined %} | |||
{%- if pillar.galera.get('master',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import master with context %} | |||
{%- set service = master %} | |||
{%- endif %} | |||
{%- if pillar.galera.slave is defined %} | |||
{%- if pillar.galera.get('slave',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import slave with context %} | |||
{%- set service = slave %} | |||
{%- endif %} | |||
[mysql] | |||
{% if service.get('ssl', {}).get('enabled', False) %} | |||
ssl-ca={{ service.ssl.ca_file }} | |||
ssl-cert={{ service.ssl.cert_file }} | |||
ssl-key={{ service.ssl.key_file }} | |||
{% endif %} | |||
[mysqld_safe] | |||
syslog | |||
@@ -16,7 +24,7 @@ syslog | |||
datadir=/var/lib/mysql | |||
bind-address={{ service.bind.address }} | |||
port=3306 | |||
max_connections={{ service.get('max_connections', 20000) }} | |||
max_connections={{ service.max_connections }} | |||
default-storage-engine=innodb | |||
binlog_format=ROW | |||
collation-server=utf8_general_ci | |||
@@ -26,6 +34,7 @@ default-storage-engine=innodb | |||
#log_error=/var/log/mysql/error.log | |||
skip-external-locking | |||
skip-name-resolve | |||
socket = /var/run/mysqld/mysqld.sock | |||
myisam_sort_buffer_size=64M | |||
wait_timeout=1800 | |||
@@ -38,7 +47,7 @@ query_cache_type=0 | |||
innodb_file_format=Barracuda | |||
innodb_file_per_table=1 | |||
innodb_buffer_pool_size=3138M | |||
innodb_buffer_pool_size={{ service.innodb_buffer_pool_size }} | |||
innodb_log_file_size=627M | |||
innodb_read_io_threads=8 | |||
innodb_write_io_threads=8 | |||
@@ -48,7 +57,6 @@ innodb_flush_method=O_DIRECT | |||
innodb_doublewrite=0 | |||
innodb_autoinc_lock_mode=2 | |||
innodb_locks_unsafe_for_binlog=1 | |||
wsrep_cluster_address="gcomm://{% for member in service.members %}{{ member.host}}:4567{% if not loop.last %},{% endif %}{% endfor %}/?pc.wait_prim=no" | |||
wsrep_provider={{ service.wsrep_provider }} | |||
wsrep_cluster_name="openstack" | |||
@@ -60,6 +68,13 @@ wsrep_node_address={{ service.bind.address }} | |||
wsrep_provider_options="gcache.size = 256M" | |||
wsrep_provider_options="gmcast.listen_addr = tcp://{{ service.bind.address }}:4567" | |||
{% if service.get('ssl', {}).get('enabled', False) %} | |||
wsrep_provider_options="socket.ssl=yes;socket.ssl_key={{ service.ssl.key_file }};socket.ssl_cert={{ service.ssl.cert_file }};socket.ssl_ca={{ service.ssl.ca_file }}" | |||
ssl-ca={{ service.ssl.ca_file }} | |||
ssl-cert={{ service.ssl.cert_file }} | |||
ssl-key={{ service.ssl.key_file }} | |||
{% endif %} | |||
[xtrabackup] | |||
parallel=4 | |||
@@ -1,4 +1,4 @@ | |||
{%- if pillar.galera.master is defined %} | |||
{%- if pillar.galera.get('master',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import master with context %} | |||
{%- set service = master %} | |||
{%- endif %} | |||
@@ -12,7 +12,7 @@ socket=/var/lib/mysql/mysql.sock | |||
pid_file=/var/lib/mysql/mysql.pid | |||
port=3306 | |||
log_warnings=2 | |||
innodb_buffer_pool_size=3138M | |||
innodb_buffer_pool_size={{ service.innodb_buffer_pool_size }} | |||
innodb_flush_log_at_trx_commit=2 | |||
innodb_file_per_table=1 | |||
innodb_data_file_path = ibdata1:100M:autoextend | |||
@@ -45,7 +45,7 @@ character-set-server=utf8 | |||
skip_name_resolve | |||
memlock=0 | |||
sysdate_is_now=1 | |||
max_connections={{ service.get('max_connections', 20000) }} | |||
max_connections={{ service.max_connections }} | |||
thread_cache_size=512 | |||
query_cache_type = 0 | |||
query_cache_size = 0 | |||
@@ -79,4 +79,4 @@ socket=/var/lib/mysql/mysql.sock | |||
[xtrabackup] | |||
parallel=4 | |||
user={{ service.admin.user }} | |||
password={{ service.admin.password }} | |||
password={{ service.admin.password }} |
@@ -1,11 +1,11 @@ | |||
# All files in this package is subject to the GPL v2 license | |||
# More information is in the COPYING file in the top directory of this package. | |||
# Copyright (C) 2011 severalnines.com | |||
{%- if pillar.galera.master is defined %} | |||
{%- if pillar.galera.get('master',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import master with context %} | |||
{%- set service = master %} | |||
{%- endif %} | |||
{%- if pillar.galera.slave is defined %} | |||
{%- if pillar.galera.get('slave',{}).get('enabled', False) %} | |||
{%- from "galera/map.jinja" import slave with context %} | |||
{%- set service = slave %} | |||
{%- endif %} | |||
@@ -15,7 +15,7 @@ syslog | |||
datadir=/var/lib/mysql | |||
bind-address={{ service.bind.address }} | |||
port=3306 | |||
max_connections={{ service.get('max_connections', 20000) }} | |||
max_connections={{ service.max_connections }} | |||
default-storage-engine=innodb | |||
binlog_format=ROW | |||
collation-server=utf8_general_ci | |||
@@ -36,7 +36,7 @@ query_cache_type=0 | |||
innodb_file_format=Barracuda | |||
innodb_file_per_table=1 | |||
innodb_buffer_pool_size=3138M | |||
innodb_buffer_pool_size={{ service.innodb_buffer_pool_size }} | |||
innodb_log_file_size=627M | |||
innodb_read_io_threads=8 | |||
innodb_write_io_threads=8 | |||
@@ -58,6 +58,13 @@ wsrep_node_address={{ service.bind.address }} | |||
wsrep_provider_options="gcache.size = 256M" | |||
wsrep_provider_options="gmcast.listen_addr = tcp://{{ service.bind.address }}:4567" | |||
{% if service.get('ssl', {}).get('enabled', False) %} | |||
wsrep_provider_options="socket.ssl=yes;socket.ssl_key={{ service.ssl.key_file }};socket.ssl_cert={{ service.ssl.cert_file }};socket.ssl_ca={{ service.ssl.ca_file }}" | |||
ssl-ca={{ service.ssl.ca_file }} | |||
ssl-cert={{ service.ssl.cert_file }} | |||
ssl-key={{ service.ssl.key_file }} | |||
{% endif %} | |||
[xtrabackup] | |||
parallel=4 | |||
@@ -0,0 +1,24 @@ | |||
# default: {{ default_state|default('on') }} | |||
# description: {{ name }} | |||
service {{ name }}: | |||
{ | |||
disable = {{ disable|default('no') }} | |||
{%- if flags is defined %} | |||
flags = {{ flags }} | |||
{%- endif %} | |||
socket_type = {{ socket_type|default('stream') }} | |||
port = {{ port }} | |||
wait = {{ wait|default('no') }} | |||
user = {{ user }} | |||
server = {{ server }} | |||
{%- if server_args is defined %} | |||
server_args = {{ server_args }} | |||
{%- endif %} | |||
log_on_failure += {{ log_on_failure|default('USERID') }} | |||
only_from = {{ only_from|default('0.0.0.0/0') }} | |||
type = {{ type|default('UNLISTED') }} | |||
{%- if per_source is defined %} | |||
per_source = {{ per_source }} | |||
{%- endif %} | |||
} |
@@ -7,6 +7,9 @@ include: | |||
{%- if pillar.galera.slave is defined %} | |||
- galera.slave | |||
{%- endif %} | |||
{%- if pillar.galera.clustercheck is defined %} | |||
- galera.clustercheck | |||
{%- endif %} | |||
{%- if pillar.galera.monitor is defined %} | |||
- galera.monitor | |||
{%- endif %} |
@@ -1,57 +1,140 @@ | |||
{% set mysql_version = pillar.galera.get('version', {}).get('mysql', '5.6') %} | |||
{% set galera_version = pillar.galera.get('version', {}).get('galera', '3') %} | |||
{%- set master = salt['grains.filter_by']({ | |||
'Debian': { | |||
'pkgs': ['mysql-wsrep-5.6', 'galera-3', 'rsync', 'python-mysqldb', 'psmisc', 'netcat', 'percona-xtrabackup', 'socat', 'libdbd-mysql', 'python-pymysql'], | |||
'service': 'mysql', | |||
'wsrep_provider': '/usr/lib/galera/libgalera_smm.so', | |||
'log_file': '/var/log/mysql.log', | |||
'socket': '/var/run/mysqld/mysqld.sock', | |||
'config': '/etc/mysql/my.cnf', | |||
}, | |||
'RedHat': { | |||
'pkgs': ['galera', 'mariadb-galera-server', 'mariadb', 'MySQL-python', 'rsync', 'percona-xtrabackup', 'psmisc', 'socat'], | |||
'xtrabackup_repo': 'http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm', | |||
'service': 'mariadb', | |||
'wsrep_provider': '/usr/lib64/galera/libgalera_smm.so', | |||
'log_file': '/var/log/mariadb/mariadb.log', | |||
'socket': '/var/run/mariadb/mysqld.sock', | |||
'config': '/etc/my.cnf', | |||
}, | |||
}, merge=pillar.galera.get('master', {})) %} | |||
{%- load_yaml as master %} | |||
default: | |||
max_connections: 20000 | |||
innodb_buffer_pool_size: '3138M' | |||
Debian: | |||
pkgs: | |||
- mysql-wsrep-{{ mysql_version }} | |||
- galera-{{ galera_version }} | |||
- rsync | |||
- python-mysqldb | |||
- psmisc | |||
- netcat | |||
- percona-xtrabackup | |||
- socat | |||
- libdbd-mysql | |||
- python-pymysql | |||
service: mysql | |||
wsrep_provider: /usr/lib/galera/libgalera_smm.so | |||
log_file: /var/log/mysql.log | |||
socket: /var/run/mysqld/mysqld.sock | |||
config: /etc/mysql/my.cnf | |||
RedHat: | |||
pkgs: | |||
- galera | |||
- mariadb-galera-server | |||
- mariadb | |||
- MySQL-python | |||
- rsync | |||
- percona-xtrabackup | |||
- psmisc | |||
- socat | |||
xtrabackup_repo: http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm | |||
service: mariadb | |||
wsrep_provider: /usr/lib64/galera/libgalera_smm.so | |||
log_file: /var/log/mariadb/mariadb.log | |||
socket: /var/run/mariadb/mysqld.sock | |||
config: /etc/my.cnf | |||
{%- endload %} | |||
{%- set _pillar = pillar.galera.get('master', {}) %} | |||
{%- if _pillar|length > 1 %} | |||
{%- set master = salt['grains.filter_by'](master, merge=_pillar, base='default') %} | |||
{%- else %} | |||
{%- set master = salt['grains.filter_by'](master, base='default') %} | |||
{%- endif %} | |||
{%- load_yaml as slave %} | |||
default: | |||
max_connections: 20000 | |||
innodb_buffer_pool_size: '3138M' | |||
Debian: | |||
pkgs: | |||
- mysql-wsrep-{{ mysql_version }} | |||
- galera-{{ galera_version }} | |||
- rsync | |||
- python-mysqldb | |||
- libmysqlclient18 | |||
- psmisc | |||
- netcat | |||
- percona-xtrabackup | |||
- socat | |||
- libdbd-mysql | |||
- python-pymysql | |||
service: mysql | |||
wsrep_provider: /usr/lib/galera/libgalera_smm.so | |||
log_file: /var/log/mysql.log | |||
socket: /var/run/mysqld/mysqld.sock | |||
config: /etc/mysql/my.cnf | |||
RedHat: | |||
pkgs: | |||
- galera | |||
- mariadb-galera-server | |||
- mariadb | |||
- MySQL-python | |||
- rsync | |||
- percona-xtrabackup | |||
- psmisc | |||
- socat | |||
xtrabackup_repo: http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm | |||
service: mariadb | |||
wsrep_provider: /usr/lib64/galera/libgalera_smm.so | |||
log_file: /var/log/mariadb/mariadb.log | |||
socket: /var/run/mariadb/mysqld.sock | |||
config: /etc/my.cnf | |||
{%- endload %} | |||
{%- load_yaml as slave_oscodename %} | |||
trusty: | |||
pkgs: | |||
- mysql-wsrep-{{ mysql_version }} | |||
- galera-{{ galera_version }} | |||
- rsync | |||
- python-mysqldb | |||
- libmysqlclient18 | |||
- psmisc | |||
- netcat | |||
- percona-xtrabackup | |||
- socat | |||
- libdbd-mysql | |||
- python-pymysql | |||
xenial: | |||
pkgs: | |||
- mysql-wsrep-{{ mysql_version }} | |||
- galera-{{ galera_version }} | |||
- rsync | |||
- python-mysqldb | |||
- libmysqlclient-dev | |||
- psmisc | |||
- netcat | |||
- percona-xtrabackup | |||
- socat | |||
- libdbd-mysql | |||
- python-pymysql | |||
{%- endload %} | |||
{%- set _pillar = pillar.galera.get('slave', {}) %} | |||
{%- if _pillar|length > 1 %} | |||
{%- set _oscodename = salt['grains.filter_by'](slave_oscodename, grain='oscodename', merge=_pillar) %} | |||
{%- else %} | |||
{%- set _oscodename = salt['grains.filter_by'](slave_oscodename, grain='oscodename') %} | |||
{%- endif %} | |||
{%- set slave = salt['grains.filter_by'](slave, merge=_oscodename, base='default') %} | |||
{%- set slave = salt['grains.filter_by']({ | |||
{% set clustercheck = salt['grains.filter_by']({ | |||
'Debian': { | |||
'pkgs': ['mysql-wsrep-5.6', 'galera-3', 'rsync', 'python-mysqldb', 'libmysqlclient18', 'psmisc', 'netcat', 'percona-xtrabackup', 'socat', 'libdbd-mysql', 'python-pymysql'], | |||
'service': 'mysql', | |||
'wsrep_provider': '/usr/lib/galera/libgalera_smm.so', | |||
'log_file': '/var/log/mysql.log', | |||
'socket': '/var/run/mysqld/mysqld.sock', | |||
'config': '/etc/mysql/my.cnf', | |||
}, | |||
'enabled': False, | |||
'user': clustercheck, | |||
'password': clustercheck, | |||
'port': '9200' | |||
}, | |||
'RedHat': { | |||
'pkgs': ['galera', 'mariadb-galera-server', 'mariadb', 'MySQL-python', 'rsync', 'percona-xtrabackup', 'psmisc', 'socat'], | |||
'xtrabackup_repo': 'http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm', | |||
'service': 'mariadb', | |||
'wsrep_provider': '/usr/lib64/galera/libgalera_smm.so', | |||
'log_file': '/var/log/mariadb/mariadb.log', | |||
'socket': '/var/run/mariadb/mysqld.sock', | |||
'config': '/etc/my.cnf', | |||
'enabled': False, | |||
'user': clustercheck, | |||
'password': clustercheck, | |||
'port': '9200' | |||
}, | |||
}, merge=salt['grains.filter_by']({ | |||
'trusty': { | |||
'pkgs': ['mysql-wsrep-5.6', 'galera-3', 'rsync', 'python-mysqldb', 'libmysqlclient18', 'psmisc', 'netcat', 'percona-xtrabackup', 'socat', 'libdbd-mysql', 'python-pymysql'], | |||
'service': 'mysql', | |||
'wsrep_provider': '/usr/lib/galera/libgalera_smm.so', | |||
'log_file': '/var/log/mysql.log', | |||
'socket': '/var/run/mysqld/mysqld.sock', | |||
'config': '/etc/mysql/my.cnf', | |||
}, | |||
'xenial': { | |||
'pkgs': ['mysql-wsrep-5.6', 'galera-3', 'rsync', 'python-mysqldb', 'libmysqlclient-dev', 'psmisc', 'netcat', 'percona-xtrabackup', 'socat', 'libdbd-mysql', 'python-pymysql'], | |||
'service': 'mysql', | |||
'wsrep_provider': '/usr/lib/galera/libgalera_smm.so', | |||
'log_file': '/var/log/mysql.log', | |||
'socket': '/var/run/mysqld/mysqld.sock', | |||
'config': '/etc/mysql/my.cnf', | |||
}, | |||
}, grain='oscodename', merge=pillar.galera.get('slave', {}))) %} | |||
}, merge=pillar.galera.get('clustercheck', {})) %} |
@@ -1,5 +1,10 @@ | |||
{%- from "galera/map.jinja" import master with context %} | |||
{%- if master.enabled %} | |||
{%- if master.get('enabled', False) %} | |||
{%- if master.get('ssl', {}).get('enabled', False) %} | |||
include: | |||
- galera._ssl | |||
{%- endif %} | |||
{%- if grains.os_family == 'RedHat' %} | |||
xtrabackup_repo: | |||
@@ -27,15 +32,16 @@ galera_packages: | |||
- refresh: true | |||
- force_yes: True | |||
galera_log_dir: | |||
galera_dirs: | |||
file.directory: | |||
- name: /var/log/mysql | |||
- names: ['/var/log/mysql', '/etc/mysql'] | |||
- makedirs: true | |||
- mode: 755 | |||
- require: | |||
- pkg: galera_packages | |||
{%- if grains.os_family == 'Debian' %} | |||
galera_run_dir: | |||
file.directory: | |||
- name: /var/run/mysqld | |||
@@ -78,7 +84,7 @@ galera_override_limit_no_file: | |||
file.managed: | |||
- name: /etc/systemd/system/mysql.service.d/override.conf | |||
- contents: | | |||
[service] | |||
[Service] | |||
LimitNOFILE=1024000 | |||
- require: | |||
- pkg: galera_packages | |||
@@ -105,7 +111,7 @@ galera_conf_debian: | |||
- require: | |||
- pkg: galera_packages | |||
{%- endif %} | |||
{%- endif %} | |||
galera_init_script: | |||
file.managed: | |||
@@ -115,6 +121,7 @@ galera_init_script: | |||
- defaults: | |||
service: {{ master|yaml }} | |||
- template: jinja | |||
- timeout: 1800 | |||
galera_bootstrap_script: | |||
file.managed: | |||
@@ -125,7 +132,7 @@ galera_bootstrap_script: | |||
service: {{ master|yaml }} | |||
- template: jinja | |||
{%- if salt['cmd.run']('test -e /var/lib/mysql/.galera_bootstrap; echo $?') != '0' %} | |||
{%- if salt['cmd.shell']('test -e /var/lib/mysql/.galera_bootstrap; echo $?') != '0' %} | |||
# Enforce config before package installation | |||
galera_pre_config: | |||
@@ -138,24 +145,32 @@ galera_pre_config: | |||
- require_in: | |||
- pkg: galera_packages | |||
{%- if not grains.get('noservices', False) %} | |||
galera_init_start_service: | |||
cmd.run: | |||
- name: /usr/local/sbin/galera_init.sh | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- file: galera_run_dir | |||
- file: galera_init_script | |||
- timeout: 1800 | |||
galera_bootstrap_set_root_password: | |||
cmd.run: | |||
- name: mysqladmin password "{{ master.admin.password }}" | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- cmd: galera_init_start_service | |||
mysql_bootstrap_update_maint_password: | |||
cmd.run: | |||
- name: mysql -u root -p{{ master.admin.password }} -e "GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY '{{ master.maintenance_password }}';" | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- cmd: galera_bootstrap_set_root_password | |||
@@ -165,39 +180,34 @@ galera_bootstrap_stop_service: | |||
{%- if not grains.get('noservices', False) %} | |||
- require: | |||
- cmd: mysql_bootstrap_update_maint_password | |||
{%- else %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- endif %} | |||
galera_bootstrap_init_config: | |||
file.managed: | |||
- name: {{ master.config }} | |||
- source: salt://galera/files/my.cnf.init | |||
- mode: 644 | |||
- template: jinja | |||
{%- if not grains.get('noservices', False) %} | |||
- require: | |||
- require: | |||
- service: galera_bootstrap_stop_service | |||
{%- endif %} | |||
{%- if not grains.get('noservices', False) %} | |||
galera_bootstrap_start_service_final: | |||
cmd.run: | |||
- name: /usr/local/sbin/galera_bootstrap.sh | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- file: galera_bootstrap_init_config | |||
- file: galera_bootstrap_script | |||
{%- endif %} | |||
galera_bootstrap_finish_flag: | |||
file.touch: | |||
- name: /var/lib/mysql/.galera_bootstrap | |||
{%- if not grains.get('noservices', False) %} | |||
- require: | |||
- cmd: galera_bootstrap_start_service_final | |||
{%- endif %} | |||
- watch_in: | |||
- file: galera_config | |||
@@ -209,18 +219,16 @@ galera_config: | |||
- source: salt://galera/files/my.cnf | |||
- mode: 644 | |||
- template: jinja | |||
{%- if not grains.get('noservices', False) %} | |||
- require_in: | |||
- require_in: | |||
- service: galera_service | |||
{%- endif %} | |||
{%- if not grains.get('noservices', False) %} | |||
galera_service: | |||
service.running: | |||
- name: {{ master.service }} | |||
- enable: true | |||
- reload: true | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- endif %} | |||
{%- endif %} |
@@ -1,29 +1,25 @@ | |||
{%- if pillar.galera is defined %} | |||
{%- if pillar.galera.master is defined %} | |||
{%- from "galera/map.jinja" import master with context %} | |||
{%- set server = master %} | |||
{%- elif pillar.galera.slave is defined %} | |||
{%- from "galera/map.jinja" import slave with context %} | |||
{%- set server = slave %} | |||
{%- from "galera/map.jinja" import master, slave with context %} | |||
{%- if master.get('enabled', False) %} | |||
{%- set service = master %} | |||
{%- elif slave.get('enabled', False) %} | |||
{%- set service = slave %} | |||
{%- endif %} | |||
{%- endif %} | |||
{%- if server is defined %} | |||
{%- if service is defined %} | |||
local_plugin: | |||
mysql: | |||
template: galera/files/collectd_mysql.conf | |||
socket: {{ server.socket }} | |||
password: {{ server.admin.password }} | |||
username: {{ server.admin.user }} | |||
socket: {{ service.socket }} | |||
password: {{ service.admin.password }} | |||
username: {{ service.admin.user }} | |||
mysql_status: | |||
template: galera/files/collectd_mysql_status.conf | |||
socket: {{ server.socket }} | |||
password: {{ server.admin.password }} | |||
username: {{ server.admin.user }} | |||
socket: {{ service.socket }} | |||
password: {{ service.admin.password }} | |||
username: {{ service.admin.user }} | |||
mysql_check: | |||
plugin: python | |||
template: galera/files/collectd_mysql_check.conf | |||
socket: {{ server.socket }} | |||
password: {{ server.admin.password }} | |||
username: {{ server.admin.user }} | |||
socket: {{ service.socket }} | |||
password: {{ service.admin.password }} | |||
username: {{ service.admin.user }} | |||
{%- endif %} |
@@ -1,8 +1,14 @@ | |||
dashboard: | |||
galera: | |||
galera_prometheus: | |||
datasource: prometheus | |||
format: json | |||
template: galera/files/grafana_dashboards/mysql_prometheus.json | |||
galera_influxdb: | |||
datasource: influxdb | |||
format: json | |||
template: galera/files/grafana_dashboards/mysql_influxdb.json | |||
main: | |||
datasource: influxdb | |||
row: | |||
ost-middleware: | |||
title: Middleware | |||
@@ -17,3 +23,18 @@ dashboard: | |||
cluster_status: | |||
rawQuery: true | |||
query: SELECT last(value) FROM cluster_status WHERE cluster_name = 'mysql' AND environment_label = '$environment' AND $timeFilter GROUP BY time($interval) fill(null) | |||
main_prometheus: | |||
datasource: prometheus | |||
row: | |||
ost-middleware: | |||
title: Middleware | |||
panel: | |||
nova: | |||
title: MySQL | |||
links: | |||
- dashboard: MySQL | |||
title: MySQL | |||
type: dashboard | |||
target: | |||
cluster_status: | |||
expr: avg(mysql_up) by (name) |
@@ -0,0 +1,31 @@ | |||
{% raw %} | |||
server: | |||
alert: | |||
GaleraServiceDown: | |||
if: >- | |||
mysql_up != 1 | |||
labels: | |||
severity: warning | |||
service: mysql | |||
annotations: | |||
summary: 'Galera service down' | |||
description: 'Galera service is down on node {{ $labels.host }}' | |||
GaleraNodeNotReady: | |||
if: 'mysql_wsrep_ready != 1' | |||
for: 1m | |||
labels: | |||
severity: warning | |||
service: mysql | |||
annotations: | |||
summary: 'Galera on {{ $labels.host }} not ready' | |||
description: 'The Galera service on {{ $labels.host }} is not ready to serve queries.' | |||
GaleraNodeNotConnected: | |||
if: 'mysql_wsrep_connected != 1' | |||
for: 1m | |||
labels: | |||
severity: warning | |||
service: mysql | |||
annotations: | |||
summary: 'Galera on {{ $labels.host }} not connected' | |||
description: 'The Galera service on {{ $labels.host }} is not connected to the cluster.' | |||
{% endraw %} |
@@ -0,0 +1,16 @@ | |||
{%- from "galera/map.jinja" import master, slave with context %} | |||
{%- if master.get('enabled', False) %} | |||
{%- set service = master %} | |||
{%- elif slave.get('enabled', False) %} | |||
{%- set service = slave %} | |||
{%- endif %} | |||
{%- if service is defined %} | |||
agent: | |||
input: | |||
mysql: | |||
address: {{ service.socket }} | |||
username: {{ service.admin.user }} | |||
password: {{ service.admin.password }} | |||
tagexclude: [service] | |||
{%- endif %} |
@@ -1,5 +1,5 @@ | |||
{%- if pillar.get('mysql', {}).server is defined %} | |||
{%- from "mysql/map.jinja" import mysql_connection_args as connection with context %} | |||
{%- set server = pillar.mysql.server %} | |||
{%- for database_name, database in server.get('database', {}).iteritems() %} | |||
@@ -7,14 +7,30 @@ | |||
mysql_database_{{ database_name }}: | |||
mysql_database.present: | |||
- name: {{ database_name }} | |||
- character_set: {{ database.get('encoding', 'utf8') }} | |||
#- connection_user: {{ connection.user }} | |||
#- connection_pass: {{ connection.password }} | |||
#- connection_charset: {{ connection.charset }} | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- for user in database.users %} | |||
{%- for user in database.get('users', {}) %} | |||
mysql_user_{{ user.name }}_{{ database_name }}_{{ user.host }}: | |||
mysql_user.present: | |||
- host: '{{ user.host }}' | |||
- name: '{{ user.name }}' | |||
{%- if user.password is defined %} | |||
- password: {{ user.password }} | |||
{%- else %} | |||
- allow_passwordless: true | |||
{%- endif %} | |||
#- connection_user: {{ connection.user }} | |||
#- connection_pass: {{ connection.password }} | |||
#- connection_charset: {{ connection.charset }} | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
mysql_grants_{{ user.name }}_{{ database_name }}_{{ user.host }}: | |||
mysql_grants.present: | |||
@@ -22,14 +38,19 @@ mysql_grants_{{ user.name }}_{{ database_name }}_{{ user.host }}: | |||
- database: '{{ database_name }}.*' | |||
- user: '{{ user.name }}' | |||
- host: '{{ user.host }}' | |||
- ssl_option: {{ user.get('ssl_option', False) }} | |||
#- connection_user: {{ connection.user }} | |||
#- connection_pass: {{ connection.password }} | |||
#- connection_charset: {{ connection.charset }} | |||
- require: | |||
- mysql_user: mysql_user_{{ user.name }}_{{ database_name }}_{{ user.host }} | |||
- mysql_database: mysql_database_{{ database_name }} | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- endfor %} | |||
{%- if database.initial_data is defined %} | |||
/root/mysql/scripts/restore_{{ database_name }}.sh: | |||
file.managed: | |||
- source: salt://mysql/conf/restore.sh | |||
@@ -38,7 +59,7 @@ mysql_grants_{{ user.name }}_{{ database_name }}_{{ user.host }}: | |||
- defaults: | |||
database_name: {{ database_name }} | |||
database: {{ database }} | |||
- require: | |||
- require: | |||
- file: mysql_dirs | |||
- mysql_database: mysql_database_{{ database_name }} | |||
@@ -49,24 +70,75 @@ restore_mysql_database_{{ database_name }}: | |||
- cwd: /root | |||
- require: | |||
- file: /root/mysql/scripts/restore_{{ database_name }}.sh | |||
{%- endif %} | |||
{%- endfor %} | |||
{%- if not grains.get('noservices', False) %} | |||
{%- for user in server.get('users', []) %} | |||
mysql_user_{{ user.name }}_{{ user.host }}: | |||
{%- for host in user.get('hosts', user.get('host', 'localhost'))|sequence %} | |||
mysql_user_{{ user.name }}_{{ host }}: | |||
mysql_user.present: | |||
- host: '{{ user.host }}' | |||
- host: '{{ host }}' | |||
- name: '{{ user.name }}' | |||
{%- if user.password is defined %} | |||
- password: {{ user.password }} | |||
{%- if user['password_hash'] is defined %} | |||
- password_hash: '{{ user.password_hash }}' | |||
{%- elif user['password'] is defined and user['password'] != None %} | |||
- password: '{{ user.password }}' | |||
{%- else %} | |||
- allow_passwordless: True | |||
{%- endif %} | |||
#- connection_user: {{ connection.user }} | |||
#- connection_pass: {{ connection.password }} | |||
#- connection_charset: {{ connection.charset }} | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- if 'grants' in user %} | |||
mysql_user_{{ user.name }}_{{ host }}_grants: | |||
mysql_grants.present: | |||
- name: {{ user.name }} | |||
- grant: {{ user['grants']|sequence|join(",") }} | |||
- database: '{{ user.get('database','*.*') }}' | |||
- grant_option: {{ user['grant_option'] | default(False) }} | |||
- user: {{ user.name }} | |||
- host: '{{ host }}' | |||
- ssl_option: {{ user.get('ssl_option', False) }} | |||
#- connection_user: {{ connection.user }} | |||
#- connection_pass: {{ connection.password }} | |||
#- connection_charset: {{ connection.charset }} | |||
- require: | |||
- mysql_user_{{ user.name }}_{{ host }} | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- endif %} | |||
{%- if 'databases' in user %} | |||
{%- for db in user['databases'] %} | |||
mysql_user_{{ user.name }}_{{ host }}_grants_db_{{ db.database }}_{{ loop.index0 }}: | |||
mysql_grants.present: | |||
- name: {{ user.name ~ '_' ~ db['database'] ~ '_' ~ db['table'] | default('all') }} | |||
- grant: {{ db['grants']|sequence|join(",") }} | |||
- database: '{{ db['database'] }}.{{ db['table'] | default('*') }}' | |||
- grant_option: {{ db['grant_option'] | default(False) }} | |||
- user: {{ user.name }} | |||
- host: '{{ host }}' | |||
- ssl_option: {{ db.get('ssl_option', False) }} | |||
#- connection_user: {{ connection.user }} | |||
#- connection_pass: {{ connection.password }} | |||
#- connection_charset: {{ connection.charset }} | |||
- require: | |||
- mysql_user_{{ user.name }}_{{ host }} | |||
# the following line is not mandatory as database might not be managed by salt formula | |||
#- mysql_database_{{ db.database }} | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- endfor %} | |||
{%- endif %} | |||
{%- endfor %} | |||
{%- endfor %} | |||
{%- endif %} | |||
{%- endif %} |
@@ -1,5 +1,10 @@ | |||
{%- from "galera/map.jinja" import slave with context %} | |||
{%- if slave.enabled %} | |||
{%- if slave.get('enabled', False) %} | |||
{%- if slave.get('ssl', {}).get('enabled', False) %} | |||
include: | |||
- galera._ssl | |||
{%- endif %} | |||
{%- if grains.os_family == 'RedHat' %} | |||
xtrabackup_repo: | |||
@@ -27,9 +32,9 @@ galera_packages: | |||
- refresh: true | |||
- force_yes: True | |||
galera_log_dir: | |||
galera_dirs: | |||
file.directory: | |||
- name: /var/log/mysql | |||
- names: ['/var/log/mysql', '/etc/mysql'] | |||
- makedirs: true | |||
- mode: 755 | |||
- require: | |||
@@ -78,7 +83,7 @@ galera_override_limit_no_file: | |||
file.managed: | |||
- name: /etc/systemd/system/mysql.service.d/override.conf | |||
- contents: | | |||
[service] | |||
[Service] | |||
LimitNOFILE=1024000 | |||
- require: | |||
- pkg: galera_packages | |||
@@ -125,7 +130,7 @@ galera_bootstrap_script: | |||
- source: salt://galera/files/bootstrap.sh | |||
- template: jinja | |||
{%- if salt['cmd.run']('test -e /var/lib/mysql/.galera_bootstrap; echo $?') != '0' %} | |||
{%- if salt['cmd.shell']('test -e /var/lib/mysql/.galera_bootstrap; echo $?') != '0' %} | |||
# Enforce config before package installation | |||
galera_pre_config: | |||
@@ -138,34 +143,44 @@ galera_pre_config: | |||
- require_in: | |||
- pkg: galera_packages | |||
{%- if not grains.get('noservices', False) %} | |||
galera_init_start_service: | |||
cmd.run: | |||
- name: /usr/local/sbin/galera_init.sh | |||
- require: | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- file: galera_run_dir | |||
- file: galera_init_script | |||
- timeout: 1800 | |||
galera_bootstrap_set_root_password: | |||
cmd.run: | |||
- name: mysqladmin password "{{ slave.admin.password }}" | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- cmd: galera_init_start_service | |||
mysql_bootstrap_update_maint_password: | |||
cmd.run: | |||
- name: mysql -u root -p{{ slave.admin.password }} -e "GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY '{{ slave.maintenance_password }}';" | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- cmd: galera_bootstrap_set_root_password | |||
galera_bootstrap_stop_service: | |||
service.dead: | |||
- name: {{ slave.service }} | |||
{%- if not grains.get('noservices', False) %} | |||
- require: | |||
- cmd: mysql_bootstrap_update_maint_password | |||
{%- endif %} | |||
{%- else %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
galera_bootstrap_init_config: | |||
file.managed: | |||
@@ -173,19 +188,19 @@ galera_bootstrap_init_config: | |||
- source: salt://galera/files/my.cnf | |||
- mode: 644 | |||
- template: jinja | |||
{%- if not grains.get('noservices', False) %} | |||
- require: | |||
- require: | |||
- service: galera_bootstrap_stop_service | |||
{%- endif %} | |||
{%- if not grains.get('noservices', False) %} | |||
galera_bootstrap_start_service_final: | |||
cmd.run: | |||
- name: /usr/local/sbin/galera_bootstrap.sh | |||
- require: | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
- require: | |||
- file: galera_bootstrap_init_config | |||
- file: galera_bootstrap_script | |||
- timeout: 1800 | |||
galera_bootstrap_finish_flag: | |||
file.touch: | |||
@@ -196,7 +211,6 @@ galera_bootstrap_finish_flag: | |||
- file: galera_config | |||
{%- endif %} | |||
{%- endif %} | |||
galera_config: | |||
file.managed: | |||
@@ -204,18 +218,17 @@ galera_config: | |||
- source: salt://galera/files/my.cnf | |||
- mode: 644 | |||
- template: jinja | |||
{%- if not grains.get('noservices', False) %} | |||
- require_in: | |||
- require_in: | |||
- service: galera_service | |||
{%- endif %} | |||
{%- if not grains.get('noservices', False) %} | |||
galera_service: | |||
service.running: | |||
- name: {{ slave.service }} | |||
- enable: true | |||
- reload: true | |||
{%- if grains.get('noservices') %} | |||
- onlyif: /bin/false | |||
{%- endif %} | |||
{%- endif %} | |||
{%- endif %} | |||
@@ -8,6 +8,8 @@ parameters: | |||
galera_server_bind_address: ${_param:cluster_local_address} | |||
galera_server_bind_port: 3306 | |||
galera_server_admin_user: root | |||
galera_max_connections: 20000 | |||
galera_innodb_buffer_pool_size: 3138M | |||
galera: | |||
master: | |||
enabled: true | |||
@@ -26,6 +28,8 @@ parameters: | |||
port: 4567 | |||
- host: ${_param:cluster_node03_address} | |||
port: 4567 | |||
max_connections: ${_param:galera_max_connections} | |||
innodb_buffer_pool_size: ${_param:galera_innodb_buffer_pool_size} | |||
mysql: | |||
server: | |||
users: |
@@ -3,6 +3,8 @@ parameters: | |||
galera_server_cluster_name: galeracluster | |||
galera_server_bind_port: 3306 | |||
galera_server_admin_user: root | |||
galera_max_connections: 20000 | |||
galera_innodb_buffer_pool_size: 3138M | |||
kubernetes: | |||
control: | |||
configmap: | |||
@@ -28,6 +30,8 @@ parameters: | |||
port: 4567 | |||
- host: ${_param:mysql_service_host03} | |||
port: 4567 | |||
max_connections: ${_param:galera_max_connections} | |||
innodb_buffer_pool_size: ${_param:galera_innodb_buffer_pool_size} | |||
mysql: | |||
server: | |||
users: |
@@ -8,6 +8,8 @@ parameters: | |||
galera_server_bind_address: ${_param:cluster_local_address} | |||
galera_server_bind_port: 3306 | |||
galera_server_admin_user: root | |||
galera_max_connections: 20000 | |||
galera_innodb_buffer_pool_size: 3138M | |||
galera: | |||
slave: | |||
enabled: true | |||
@@ -26,6 +28,8 @@ parameters: | |||
port: 4567 | |||
- host: ${_param:cluster_node03_address} | |||
port: 4567 | |||
max_connections: ${_param:galera_max_connections} | |||
innodb_buffer_pool_size: ${_param:galera_innodb_buffer_pool_size} | |||
mysql: | |||
server: | |||
users: |
@@ -0,0 +1,21 @@ | |||
# class to enable tls for galera.master and galera.slave | |||
parameters: | |||
_param: | |||
mysql_ssl_key_file: /etc/mysql/ssl/key.pem | |||
mysql_ssl_cert_file: /etc/mysql/ssl/cert.pem | |||
mysql_ssl_ca_file: /etc/mysql/ssl/ca.pem | |||
galera: | |||
master: | |||
ssl: | |||
enabled: True | |||
key_file: ${_param:mysql_ssl_key_file} | |||
cert_file: ${_param:mysql_ssl_cert_file} | |||
ca_file: ${_param:mysql_ssl_ca_file} | |||
slave: | |||
ssl: | |||
enabled: True | |||
key_file: ${_param:mysql_ssl_key_file} | |||
cert_file: ${_param:mysql_ssl_cert_file} | |||
ca_file: ${_param:mysql_ssl_ca_file} |
@@ -13,3 +13,7 @@ parameters: | |||
enabled: true | |||
grafana: | |||
enabled: true | |||
prometheus: | |||
enabled: true | |||
telegraf: | |||
enabled: true |
@@ -0,0 +1,10 @@ | |||
describe file('/etc/xinetd.d/mysql_clustercheck') do | |||
it('should exist') | |||
its('content') { should match /server.*\/usr\/local\/bin\/mysql_clustercheck/ } | |||
its('content') { should match /server_args.*clustercheck password available_when_donor=1 \/dev\/null available_when_readonly=1/ } | |||
end | |||
describe file('/usr/local/bin/mysql_clustercheck') do | |||
it('should exist') | |||
it('should be_executable') | |||
end |
@@ -0,0 +1,10 @@ | |||
describe file('/etc/xinetd.d/mysql_clustercheck') do | |||
it('should exist') | |||
its('content') { should match /server.*\/usr\/local\/bin\/mysql_clustercheck/ } | |||
its('content') { should match /server_args.*clustercheck password available_when_donor=1 \/dev\/null available_when_readonly=1/ } | |||
end | |||
describe file('/usr/local/bin/mysql_clustercheck') do | |||
it('should exist') | |||
it('should be_executable') | |||
end |
@@ -1,27 +1,58 @@ | |||
galera: | |||
master: | |||
enabled: true | |||
name: galeracluster | |||
bind: | |||
address: 127.0.0.1 | |||
port: 3306 | |||
maintenance_password: password | |||
admin: | |||
user: user | |||
password: password | |||
members: | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
mysql: | |||
server: | |||
users: | |||
- name: haproxy | |||
host: localhost | |||
- name: haproxy | |||
host: '%' | |||
- name: haproxy | |||
host: 127.0.0.1 | |||
galera: | |||
master: | |||
enabled: true | |||
name: galeracluster | |||
bind: | |||
address: 127.0.0.1 | |||
port: 3306 | |||
maintenance_password: password | |||
admin: | |||
user: root | |||
password: password | |||
members: | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
clustercheck: | |||
enabled: True | |||
user: clustercheck | |||
password: password | |||
available_when_donor: 1 | |||
available_when_readonly: 1 | |||
port: 9200 | |||
max_connections: 20000 | |||
innodb_buffer_pool_size: 3138M | |||
mysql: | |||
server: | |||
enabled: true | |||
bind: | |||
address: 0.0.0.0 | |||
port: 3306 | |||
protocol: tcp | |||
database: | |||
mydb: | |||
encoding: 'utf8' | |||
users: | |||
- name: haproxy | |||
host: localhost | |||
- name: haproxy | |||
host: '%' | |||
- name: haproxy | |||
host: 127.0.0.1 | |||
- name: clustercheck | |||
#host: localhost | |||
password: password | |||
database: '*.*' | |||
grants: PROCESS | |||
- name: inspector | |||
host: 127.0.0.1 | |||
password: password | |||
databases: | |||
- database: mydb | |||
table: mytable | |||
grant_option: True | |||
grants: | |||
- all privileges |
@@ -3,8 +3,20 @@ linux: | |||
enabled: true | |||
repo: | |||
galeracluster: | |||
source: 'deb http://releases.galeracluster.com/ubuntu {{ grains.get('oscodename') }} main' | |||
key_id: BC19DDBA | |||
key_server: hkp://p80.pool.sks-keyservers.net:80 | |||
pin: | |||
- pin: 'release o=Galera Cluster' | |||
priority: 1001 | |||
package: '*' | |||
mysql-wsrep: | |||
key_id: BC19DDBA | |||
key_server: hkp://p80.pool.sks-keyservers.net:80 | |||
pin: | |||
- pin: 'release o=Galera Cluster' | |||
priority: 1001 | |||
package: '*' | |||
mitaka-staging_PPA: | |||
source: "deb http://ppa.launchpad.net/ubuntu-cloud-archive/mitaka-staging/ubuntu trusty main" | |||
key_id: 8A6844A29F68104E | |||
key_server: hkp://p80.pool.sks-keyservers.net:80 |
@@ -7,7 +7,7 @@ | |||
port: 3306 | |||
maintenance_password: password | |||
admin: | |||
user: user | |||
user: root | |||
password: password | |||
members: | |||
- host: 127.0.0.1 | |||
@@ -16,6 +16,15 @@ | |||
port: 4567 | |||
- host: 127.0.0.1 | |||
port: 4567 | |||
clustercheck: | |||
enabled: True | |||
user: clustercheck | |||
password: password | |||
available_when_donor: 1 | |||
available_when_readonly: 1 | |||
port: 9200 | |||
max_connections: 20000 | |||
innodb_buffer_pool_size: 3138M | |||
mysql: | |||
server: | |||
users: | |||
@@ -24,4 +33,9 @@ | |||
- name: haproxy | |||
host: '%' | |||
- name: haproxy | |||
host: 127.0.0.1 | |||
host: 127.0.0.1 | |||
- name: clustercheck | |||
#host: localhost | |||
password: password | |||
database: '*.*' | |||
grants: PROCESS |
@@ -6,11 +6,13 @@ set -e | |||
CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" | |||
METADATA=${CURDIR}/../metadata.yml | |||
FORMULA_NAME=$(cat $METADATA | python -c "import sys,yaml; print yaml.load(sys.stdin)['name']") | |||
FORMULA_META_DIR=${CURDIR}/../${FORMULA_NAME}/meta | |||
## Overrideable parameters | |||
PILLARDIR=${PILLARDIR:-${CURDIR}/pillar} | |||
BUILDDIR=${BUILDDIR:-${CURDIR}/build} | |||
VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv} | |||
MOCK_BIN_DIR=${MOCK_BIN_DIR:-${CURDIR}/mock_bin} | |||
DEPSDIR=${BUILDDIR}/deps | |||
SALT_FILE_DIR=${SALT_FILE_DIR:-${BUILDDIR}/file_root} | |||
@@ -18,7 +20,7 @@ SALT_PILLAR_DIR=${SALT_PILLAR_DIR:-${BUILDDIR}/pillar_root} | |||
SALT_CONFIG_DIR=${SALT_CONFIG_DIR:-${BUILDDIR}/salt} | |||
SALT_CACHE_DIR=${SALT_CACHE_DIR:-${SALT_CONFIG_DIR}/cache} | |||
SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR}" | |||
SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR} --log-file=/dev/null" | |||
if [ "x${SALT_VERSION}" != "x" ]; then | |||
PIP_SALT_VERSION="==${SALT_VERSION}" | |||
@@ -37,13 +39,23 @@ setup_virtualenv() { | |||
log_info "Setting up Python virtualenv" | |||
virtualenv $VENV_DIR | |||
source ${VENV_DIR}/bin/activate | |||
pip install salt${PIP_SALT_VERSION} | |||
python -m pip install salt${PIP_SALT_VERSION} | |||
} | |||
setup_mock_bin() { | |||
# If some state requires a binary, a lightweight replacement for | |||
# such binary can be put into MOCK_BIN_DIR for test purposes | |||
if [ -d "${MOCK_BIN_DIR}" ]; then | |||
PATH="${MOCK_BIN_DIR}:$PATH" | |||
export PATH | |||
fi | |||
} | |||
setup_pillar() { | |||
[ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR} | |||
echo "base:" > ${SALT_PILLAR_DIR}/top.sls | |||
for pillar in ${PILLARDIR}/*; do | |||
grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue | |||
state_name=$(basename ${pillar%.sls}) | |||
echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls | |||
done | |||
@@ -56,6 +68,7 @@ setup_salt() { | |||
echo "base:" > ${SALT_FILE_DIR}/top.sls | |||
for pillar in ${PILLARDIR}/*.sls; do | |||
grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue | |||
state_name=$(basename ${pillar%.sls}) | |||
echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls | |||
done | |||
@@ -64,6 +77,7 @@ setup_salt() { | |||
file_client: local | |||
cachedir: ${SALT_CACHE_DIR} | |||
verify_env: False | |||
minion_id_caching: False | |||
file_roots: | |||
base: | |||
@@ -110,14 +124,15 @@ clean() { | |||
} | |||
salt_run() { | |||
[ -e ${VEN_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate | |||
salt-call ${SALT_OPTS} $* | |||
[ -e ${VENV_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate | |||
python $(which salt-call) ${SALT_OPTS} $* | |||
} | |||
prepare() { | |||
[ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR} | |||
which salt-call || setup_virtualenv | |||
setup_mock_bin | |||
setup_pillar | |||
setup_salt | |||
install_dependencies | |||
@@ -125,8 +140,28 @@ prepare() { | |||
run() { | |||
for pillar in ${PILLARDIR}/*.sls; do | |||
grep ${FORMULA_NAME}: ${pillar} &>/dev/null || continue | |||
state_name=$(basename ${pillar%.sls}) | |||
salt_run grains.set 'noservices' False force=True | |||
echo "Checking state ${FORMULA_NAME}.${state_name} ..." | |||
salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1) | |||
# Check that all files in 'meta' folder can be rendered using any valid pillar | |||
for meta in `find ${FORMULA_META_DIR} -type f`; do | |||
meta_name=$(basename ${meta}) | |||
echo "Checking meta ${meta_name} ..." | |||
salt_run --out=quiet --id=${state_name} cp.get_template ${meta} ${SALT_CACHE_DIR}/${meta_name} \ | |||
|| (log_err "Failed to render meta ${meta} using pillar ${FORMULA_NAME}.${state_name}"; exit 1) | |||
cat ${SALT_CACHE_DIR}/${meta_name} | |||
done | |||
done | |||
} | |||
real_run() { | |||
for pillar in ${PILLARDIR}/*.sls; do | |||
state_name=$(basename ${pillar%.sls}) | |||
salt_run --id=${state_name} state.sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1) | |||
done | |||
} | |||
@@ -155,6 +190,9 @@ case $1 in | |||
run) | |||
run | |||
;; | |||
real-run) | |||
real_run | |||
;; | |||
*) | |||
prepare | |||
run |