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