Merge branch 'master' into feature/tunne_bootstrapscrips
diff --git a/.kitchen.yml b/.kitchen.yml
index dbb9474..6bc9957 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -14,6 +14,13 @@
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 @@
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
diff --git a/.travis.yml b/.travis.yml
index 7a77247..e1e6fa9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,15 +17,22 @@
- 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:
diff --git a/README.rst b/README.rst
index e692b69..872aca0 100644
--- a/README.rst
+++ b/README.rst
@@ -13,6 +13,9 @@
.. code-block:: yaml
galera:
+ version:
+ mysql: 5.6
+ galera: 3
master:
enabled: true
name: openstack
@@ -56,13 +59,102 @@
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 @@
.. 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 @@
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
diff --git a/debian/control b/debian/control
index 6d00a4b..a79fa37 100644
--- a/debian/control
+++ b/debian/control
@@ -11,6 +11,6 @@
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.
diff --git a/galera/_ssl.sls b/galera/_ssl.sls
new file mode 100644
index 0000000..e6ddd42
--- /dev/null
+++ b/galera/_ssl.sls
@@ -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 %}
diff --git a/galera/clustercheck.sls b/galera/clustercheck.sls
new file mode 100644
index 0000000..a311a84
--- /dev/null
+++ b/galera/clustercheck.sls
@@ -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 %}
+
diff --git a/galera/files/clustercheck.sh b/galera/files/clustercheck.sh
new file mode 100644
index 0000000..efed950
--- /dev/null
+++ b/galera/files/clustercheck.sh
@@ -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
diff --git a/galera/files/debian.cnf b/galera/files/debian.cnf
index e1b543b..dd1e6fa 100644
--- a/galera/files/debian.cnf
+++ b/galera/files/debian.cnf
@@ -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 %}
diff --git a/galera/files/grafana_dashboards/mysql_prometheus.json b/galera/files/grafana_dashboards/mysql_prometheus.json
new file mode 100644
index 0000000..35ddcb8
--- /dev/null
+++ b/galera/files/grafana_dashboards/mysql_prometheus.json
@@ -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
+}
diff --git a/galera/files/init_bootstrap.sh b/galera/files/init_bootstrap.sh
index 14a4c20..c168915 100644
--- a/galera/files/init_bootstrap.sh
+++ b/galera/files/init_bootstrap.sh
@@ -7,7 +7,7 @@
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
diff --git a/galera/files/my.cnf b/galera/files/my.cnf
index 5ceb376..049d6d6 100644
--- a/galera/files/my.cnf
+++ b/galera/files/my.cnf
@@ -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 @@
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 @@
#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 @@
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_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_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
diff --git a/galera/files/my.cnf.container b/galera/files/my.cnf.container
index ec85ef1..0a2645e 100644
--- a/galera/files/my.cnf.container
+++ b/galera/files/my.cnf.container
@@ -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 @@
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 @@
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 @@
[xtrabackup]
parallel=4
user={{ service.admin.user }}
-password={{ service.admin.password }}
\ No newline at end of file
+password={{ service.admin.password }}
diff --git a/galera/files/my.cnf.init b/galera/files/my.cnf.init
index ea0e0f0..a5ea26d 100644
--- a/galera/files/my.cnf.init
+++ b/galera/files/my.cnf.init
@@ -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 @@
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 @@
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_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
diff --git a/galera/files/xinet.d.conf b/galera/files/xinet.d.conf
new file mode 100644
index 0000000..fd6f321
--- /dev/null
+++ b/galera/files/xinet.d.conf
@@ -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 %}
+}
diff --git a/galera/init.sls b/galera/init.sls
index 94e1414..bc55f36 100644
--- a/galera/init.sls
+++ b/galera/init.sls
@@ -7,6 +7,9 @@
{%- 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 %}
diff --git a/galera/map.jinja b/galera/map.jinja
index 65683f2..c9e21cc 100644
--- a/galera/map.jinja
+++ b/galera/map.jinja
@@ -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 %}
-{%- set slave = salt['grains.filter_by']({
+
+{%- 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 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', {})) %}
diff --git a/galera/master.sls b/galera/master.sls
index fae46ec..a4fa680 100644
--- a/galera/master.sls
+++ b/galera/master.sls
@@ -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 @@
- 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 @@
file.managed:
- name: /etc/systemd/system/mysql.service.d/override.conf
- contents: |
- [service]
+ [Service]
LimitNOFILE=1024000
- require:
- pkg: galera_packages
@@ -105,7 +111,7 @@
- require:
- pkg: galera_packages
-{%- endif %}
+{%- endif %}
galera_init_script:
file.managed:
@@ -115,6 +121,7 @@
- defaults:
service: {{ master|yaml }}
- template: jinja
+ - timeout: 1800
galera_bootstrap_script:
file.managed:
@@ -125,7 +132,7 @@
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 @@
- 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 @@
{%- 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 @@
- 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 %}
diff --git a/galera/meta/collectd.yml b/galera/meta/collectd.yml
index 4533ad0..9aeb35b 100644
--- a/galera/meta/collectd.yml
+++ b/galera/meta/collectd.yml
@@ -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 %}
diff --git a/galera/meta/grafana.yml b/galera/meta/grafana.yml
index 2c701b9..0f2ab4f 100644
--- a/galera/meta/grafana.yml
+++ b/galera/meta/grafana.yml
@@ -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 @@
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)
\ No newline at end of file
diff --git a/galera/meta/prometheus.yml b/galera/meta/prometheus.yml
new file mode 100644
index 0000000..6187ea1
--- /dev/null
+++ b/galera/meta/prometheus.yml
@@ -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 %}
diff --git a/galera/meta/telegraf.yml b/galera/meta/telegraf.yml
new file mode 100644
index 0000000..5869765
--- /dev/null
+++ b/galera/meta/telegraf.yml
@@ -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 %}
diff --git a/galera/server.sls b/galera/server.sls
index a81a7e8..7d070d4 100644
--- a/galera/server.sls
+++ b/galera/server.sls
@@ -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 @@
- 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 @@
- defaults:
database_name: {{ database_name }}
database: {{ database }}
- - require:
+ - require:
- file: mysql_dirs
- mysql_database: mysql_database_{{ database_name }}
@@ -49,24 +70,75 @@
- 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 %}
-{%- endif %}
\ No newline at end of file
+
+{%- endfor %}
+{%- endfor %}
+
+{%- endif %}
diff --git a/galera/slave.sls b/galera/slave.sls
index a8ddf55..2a70672 100644
--- a/galera/slave.sls
+++ b/galera/slave.sls
@@ -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 @@
- 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 @@
file.managed:
- name: /etc/systemd/system/mysql.service.d/override.conf
- contents: |
- [service]
+ [Service]
LimitNOFILE=1024000
- require:
- pkg: galera_packages
@@ -125,7 +130,7 @@
- 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 @@
- 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 @@
- 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 @@
- file: galera_config
{%- endif %}
-{%- endif %}
galera_config:
file.managed:
@@ -204,18 +218,17 @@
- 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 %}
+
diff --git a/metadata/service/master/cluster.yml b/metadata/service/master/cluster.yml
index 7705f6b..05c4c57 100644
--- a/metadata/service/master/cluster.yml
+++ b/metadata/service/master/cluster.yml
@@ -8,6 +8,8 @@
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 @@
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:
diff --git a/metadata/service/master/container.yml b/metadata/service/master/container.yml
index e6ac462..c80beef 100644
--- a/metadata/service/master/container.yml
+++ b/metadata/service/master/container.yml
@@ -3,6 +3,8 @@
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 @@
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:
diff --git a/metadata/service/slave/cluster.yml b/metadata/service/slave/cluster.yml
index 2432da6..de05623 100644
--- a/metadata/service/slave/cluster.yml
+++ b/metadata/service/slave/cluster.yml
@@ -8,6 +8,8 @@
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 @@
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:
diff --git a/metadata/service/ssl.yml b/metadata/service/ssl.yml
new file mode 100644
index 0000000..5b31b31
--- /dev/null
+++ b/metadata/service/ssl.yml
@@ -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}
diff --git a/metadata/service/support.yml b/metadata/service/support.yml
index eb560fa..fb5051f 100644
--- a/metadata/service/support.yml
+++ b/metadata/service/support.yml
@@ -13,3 +13,7 @@
enabled: true
grafana:
enabled: true
+ prometheus:
+ enabled: true
+ telegraf:
+ enabled: true
diff --git a/tests/integration/master_cluster/checks_clustercheck_spec.rb b/tests/integration/master_cluster/checks_clustercheck_spec.rb
new file mode 100644
index 0000000..d10fc19
--- /dev/null
+++ b/tests/integration/master_cluster/checks_clustercheck_spec.rb
@@ -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
diff --git a/tests/integration/slave_cluster/checks_clustercheck_spec.rb b/tests/integration/slave_cluster/checks_clustercheck_spec.rb
new file mode 100644
index 0000000..d10fc19
--- /dev/null
+++ b/tests/integration/slave_cluster/checks_clustercheck_spec.rb
@@ -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
diff --git a/tests/pillar/master_cluster.sls b/tests/pillar/master_cluster.sls
index 7257ce4..3a5d91f 100644
--- a/tests/pillar/master_cluster.sls
+++ b/tests/pillar/master_cluster.sls
@@ -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
diff --git a/tests/pillar/repo_galeracluster.sls b/tests/pillar/repo_galeracluster.sls
index 464a414..9e9c1bf 100644
--- a/tests/pillar/repo_galeracluster.sls
+++ b/tests/pillar/repo_galeracluster.sls
@@ -3,8 +3,20 @@
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
diff --git a/tests/pillar/slave_cluster.sls b/tests/pillar/slave_cluster.sls
index 10dfccb..38c8420 100644
--- a/tests/pillar/slave_cluster.sls
+++ b/tests/pillar/slave_cluster.sls
@@ -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
\ No newline at end of file
+ host: 127.0.0.1
+ - name: clustercheck
+ #host: localhost
+ password: password
+ database: '*.*'
+ grants: PROCESS
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 3f42101..9761585 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -6,11 +6,13 @@
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_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 @@
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 @@
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 @@
file_client: local
cachedir: ${SALT_CACHE_DIR}
verify_env: False
+minion_id_caching: False
file_roots:
base:
@@ -110,14 +124,15 @@
}
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 @@
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 @@
run)
run
;;
+ real-run)
+ real_run
+ ;;
*)
prepare
run