Quellcode durchsuchen

Merge branch 'master' into feature/tunne_bootstrapscrips

feature/tunne_bootstrapscrips
Petr Michalec vor 6 Jahren
Ursprung
Commit
d73be0e901
Es ist kein Account mit der E-Mail-Adresse des Committers verbunden
34 geänderte Dateien mit 1979 neuen und 201 gelöschten Zeilen
  1. +28
    -10
      .kitchen.yml
  2. +10
    -3
      .travis.yml
  3. +97
    -5
      README.rst
  4. +1
    -1
      debian/control
  5. +107
    -0
      galera/_ssl.sls
  6. +45
    -0
      galera/clustercheck.sls
  7. +138
    -0
      galera/files/clustercheck.sh
  8. +2
    -2
      galera/files/debian.cnf
  9. +930
    -0
      galera/files/grafana_dashboards/mysql_prometheus.json
  10. +1
    -1
      galera/files/init_bootstrap.sh
  11. +20
    -5
      galera/files/my.cnf
  12. +4
    -4
      galera/files/my.cnf.container
  13. +11
    -4
      galera/files/my.cnf.init
  14. +24
    -0
      galera/files/xinet.d.conf
  15. +3
    -0
      galera/init.sls
  16. +133
    -50
      galera/map.jinja
  17. +33
    -25
      galera/master.sls
  18. +15
    -19
      galera/meta/collectd.yml
  19. +22
    -1
      galera/meta/grafana.yml
  20. +31
    -0
      galera/meta/prometheus.yml
  21. +16
    -0
      galera/meta/telegraf.yml
  22. +86
    -14
      galera/server.sls
  23. +36
    -23
      galera/slave.sls
  24. +4
    -0
      metadata/service/master/cluster.yml
  25. +4
    -0
      metadata/service/master/container.yml
  26. +4
    -0
      metadata/service/slave/cluster.yml
  27. +21
    -0
      metadata/service/ssl.yml
  28. +4
    -0
      metadata/service/support.yml
  29. +10
    -0
      tests/integration/master_cluster/checks_clustercheck_spec.rb
  30. +10
    -0
      tests/integration/slave_cluster/checks_clustercheck_spec.rb
  31. +58
    -27
      tests/pillar/master_cluster.sls
  32. +13
    -1
      tests/pillar/repo_galeracluster.sls
  33. +16
    -2
      tests/pillar/slave_cluster.sls
  34. +42
    -4
      tests/run_tests.sh

+ 28
- 10
.kitchen.yml Datei anzeigen

@@ -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

+ 10
- 3
.travis.yml Datei anzeigen

@@ -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:

+ 97
- 5
README.rst Datei anzeigen

@@ -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

+ 1
- 1
debian/control Datei anzeigen

@@ -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.

+ 107
- 0
galera/_ssl.sls Datei anzeigen

@@ -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 %}

+ 45
- 0
galera/clustercheck.sls Datei anzeigen

@@ -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 %}


+ 138
- 0
galera/files/clustercheck.sh Datei anzeigen

@@ -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

+ 2
- 2
galera/files/debian.cnf Datei anzeigen

@@ -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 %}

+ 930
- 0
galera/files/grafana_dashboards/mysql_prometheus.json Datei anzeigen

@@ -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
}

+ 1
- 1
galera/files/init_bootstrap.sh Datei anzeigen

@@ -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

+ 20
- 5
galera/files/my.cnf Datei anzeigen

@@ -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


+ 4
- 4
galera/files/my.cnf.container Datei anzeigen

@@ -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 }}

+ 11
- 4
galera/files/my.cnf.init Datei anzeigen

@@ -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


+ 24
- 0
galera/files/xinet.d.conf Datei anzeigen

@@ -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 %}
}

+ 3
- 0
galera/init.sls Datei anzeigen

@@ -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 %}

+ 133
- 50
galera/map.jinja Datei anzeigen

@@ -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', {})) %}

+ 33
- 25
galera/master.sls Datei anzeigen

@@ -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 %}

+ 15
- 19
galera/meta/collectd.yml Datei anzeigen

@@ -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 %}

+ 22
- 1
galera/meta/grafana.yml Datei anzeigen

@@ -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)

+ 31
- 0
galera/meta/prometheus.yml Datei anzeigen

@@ -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 %}

+ 16
- 0
galera/meta/telegraf.yml Datei anzeigen

@@ -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 %}

+ 86
- 14
galera/server.sls Datei anzeigen

@@ -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 %}

+ 36
- 23
galera/slave.sls Datei anzeigen

@@ -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 %}

+ 4
- 0
metadata/service/master/cluster.yml Datei anzeigen

@@ -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:

+ 4
- 0
metadata/service/master/container.yml Datei anzeigen

@@ -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:

+ 4
- 0
metadata/service/slave/cluster.yml Datei anzeigen

@@ -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:

+ 21
- 0
metadata/service/ssl.yml Datei anzeigen

@@ -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}

+ 4
- 0
metadata/service/support.yml Datei anzeigen

@@ -13,3 +13,7 @@ parameters:
enabled: true
grafana:
enabled: true
prometheus:
enabled: true
telegraf:
enabled: true

+ 10
- 0
tests/integration/master_cluster/checks_clustercheck_spec.rb Datei anzeigen

@@ -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

+ 10
- 0
tests/integration/slave_cluster/checks_clustercheck_spec.rb Datei anzeigen

@@ -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

+ 58
- 27
tests/pillar/master_cluster.sls Datei anzeigen

@@ -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

+ 13
- 1
tests/pillar/repo_galeracluster.sls Datei anzeigen

@@ -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

+ 16
- 2
tests/pillar/slave_cluster.sls Datei anzeigen

@@ -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

+ 42
- 4
tests/run_tests.sh Datei anzeigen

@@ -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

Laden…
Abbrechen
Speichern