├── .github └── stale.yml ├── LICENSE.md ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── tasks ├── cluster.yml ├── config.yml ├── debian.yml └── main.yml ├── templates └── etc │ ├── corosync │ ├── authkey.j2 │ ├── corosync.conf.j2 │ └── corosync.conf.j2.orig │ └── default │ └── corosync.j2 └── vars └── main.yml /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Larry Smith Jr. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | - [ansible-pacemaker](#ansible-pacemaker) 6 | - [Requirements](#requirements) 7 | - [Pacemaker cluster](#pacemaker-cluster) 8 | - [Number of Nodes](#number-of-nodes) 9 | - [OS requirements](#os-requirements) 10 | - [macOS](#macos) 11 | - [Role Variables](#role-variables) 12 | - [Dependencies](#dependencies) 13 | - [Example Playbook](#example-playbook) 14 | - [License](#license) 15 | - [Author Information](#author-information) 16 | 17 | 18 | 19 | # ansible-pacemaker 20 | 21 | An [Ansible](https://www.ansible.com) role to install/configure [pacemaker/corosync](http://clusterlabs.org). 22 | 23 | ## Requirements 24 | 25 | ### Pacemaker cluster 26 | 27 | The following requirements are specific requirements for cluster setup. 28 | 29 | #### Number of Nodes 30 | 31 | - Up to 16 nodes per cluster. 32 | - Minimum number of nodes: 3. 33 | - 2 nodes cluster could be configured but is not recommended. 34 | 35 | ### OS requirements 36 | 37 | The following requirements are specific to OS deployments. 38 | 39 | #### macOS 40 | 41 | - [Python passlib module](http://docs.ansible.com/ansible/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module) 42 | 43 | ```bash 44 | pip install passlib 45 | ``` 46 | 47 | ## Role Variables 48 | 49 | ```yaml 50 | --- 51 | # defaults file for ansible-pacemaker 52 | corosync_authkey_file: '/etc/corosync/authkey' 53 | 54 | # Defines interface used for cluster 55 | corosync_bindnet_interface: 'enp0s8' 56 | 57 | corosync_config_file: '/etc/corosync/corosync.conf' 58 | 59 | # Defines the number of nodes to be functional in order to avoid split-brain 60 | # scenarios...ex. 2-nodes = 1, 3-nodes = 2 61 | corosync_expected_votes: "{{ ( groups[pacemaker_cluster_group]|count /2 ) | round (0, 'ceil') | int }}" 62 | 63 | # Corosync itself works without a cluster name, but DLM needs one. 64 | # The cluster name is also written into the VG metadata of newly 65 | # created shared LVM volume groups, if lvmlockd uses DLM locking. 66 | # It is also used for computing mcastaddr, unless overridden below. 67 | corosync_cluster_name: 'debian' 68 | 69 | # Setting corosync_last_man_standing to true enables the Last Man Standing (LMS) feature; 70 | # by default, it is disabled (set to false) 71 | corosync_last_man_standing: true 72 | 73 | # Define multicast address to use for cluster 74 | # this should be unique per cluster 75 | corosync_mcastaddr: 239.255.42.1 76 | 77 | # Define port number to configure as cluster port. 78 | corosync_mcastport: 5405 79 | 80 | # Defines if unicast mode should be used rather than multicast 81 | corosync_unicast_mode: false 82 | 83 | # Means that, When starting up a cluster (all nodes down), the cluster quorum 84 | # is held until all nodes are online and have joined the cluster for the first 85 | # time. This parameter is new in Corosync 2.0. 86 | corosync_wait_for_all: true 87 | 88 | pacemaker_cluster_constraints: [] 89 | # - constraint: 'colocation' 90 | # action: 'add' 91 | # source_resource_id: 'webserver' 92 | # target_resource_id: 'virtual_ip' 93 | # score: 'INFINITY' 94 | # - constraint: 'order' 95 | # order: 96 | # first_resource: 'virtual_ip' 97 | # first_resource_action: 'start' 98 | # second_resource: 'webserver' 99 | # second_resource_action: 'start' 100 | 101 | pacemaker_cluster_group: 'ha_cluster' 102 | 103 | pacemaker_cluster_resources: [] 104 | # - resource_id: 'virtual_ip' 105 | # action: 'create' 106 | # provider: 'ocf:heartbeat:IPaddr2' 107 | # options: 108 | # - 'ip=192.168.250.200' 109 | # - 'cidr_netmask=24' 110 | # op: 'monitor' 111 | # op_options: 112 | # - 'interval=30s' 113 | # - resource_id: 'webserver' 114 | # action: 'create' 115 | # provider: 'ocf:heartbeat:nginx' 116 | # options: 117 | # - 'configfile=/etc/nginx/nginx.conf' 118 | # op: 'monitor' 119 | # op_options: 120 | # - 'timeout=5s' 121 | # - 'interval=5s' 122 | 123 | # NOT RECOMMENDED FOR PRODUCTION!!!!! 124 | # You must have a STONITH device to enable.... 125 | pacemaker_disable_stonith: true 126 | 127 | # Define specific cluster settings to configure 128 | pacemaker_cluster_settings: [] 129 | # - property: 'start-failure-is-fatal' 130 | # value: 'false' 131 | # - property: 'pe-warn-series-max' 132 | # value: 1000 133 | # - property: 'pe-input-series-max' 134 | # value: 1000 135 | # - property: 'pe-error-series-max' 136 | # value: 1000 137 | # - property: 'cluster-recheck-interval' 138 | # value: 5min 139 | 140 | # Define hacluster user password for webUI 141 | # 142 | # Generate new password 143 | # echo "haclusteradmin" | sha512sum 144 | pacemaker_hacluster_password: 'f8d1feb7105dfbd2859a17512c7414f89b70dfef815b177444b897edec19a18724f8e9686f0e2daa41c48eb9b0511bae9e659a756f17c39fedb6d68b9230a53c' 145 | 146 | # Defines if host is considered to be primary 147 | # this should be set in host_vars/hostname as true for only one host 148 | pacemaker_primary_server: '{{ groups[pacemaker_cluster_group][0] }}' 149 | ``` 150 | 151 | ## Dependencies 152 | 153 | None 154 | 155 | ## Example Playbook 156 | 157 | ```yaml 158 | --- 159 | - hosts: ha_cluster 160 | vars: 161 | etc_hosts_add_all_hosts: true 162 | pacemaker_cluster_constraints: 163 | - constraint: 'colocation' 164 | action: 'add' 165 | source_resource_id: 'webserver' 166 | target_resource_id: 'virtual_ip' 167 | score: 'INFINITY' 168 | - constraint: 'order' 169 | order: 170 | first_resource: 'virtual_ip' 171 | first_resource_action: 'start' 172 | second_resource: 'webserver' 173 | second_resource_action: 'start' 174 | pacemaker_cluster_resources: 175 | - resource_id: 'virtual_ip' 176 | action: 'create' 177 | provider: 'ocf:heartbeat:IPaddr2' 178 | options: 179 | - 'ip=192.168.250.200' 180 | - 'cidr_netmask=24' 181 | op: 'monitor' 182 | op_options: 183 | - 'interval=30s' 184 | - resource_id: 'webserver' 185 | action: 'create' 186 | provider: 'ocf:heartbeat:nginx' 187 | options: 188 | - 'configfile=/etc/nginx/nginx.conf' 189 | op: 'monitor' 190 | op_options: 191 | - 'timeout=5s' 192 | - 'interval=5s' 193 | pacemaker_cluster_settings: 194 | - property: 'start-failure-is-fatal' 195 | value: 'false' 196 | - property: 'pe-warn-series-max' 197 | value: 1000 198 | - property: 'pe-input-series-max' 199 | value: 1000 200 | - property: 'pe-error-series-max' 201 | value: 1000 202 | - property: 'cluster-recheck-interval' 203 | value: 5min 204 | pri_domain_name: 'test.vagrant.local' 205 | roles: 206 | - role: ansible-apt-sources 207 | - role: ansible-motd 208 | - role: ansible-ntp 209 | - role: ansible-timezone 210 | become: true 211 | - role: ansible-etc-hosts 212 | - role: ansible-pacemaker 213 | tags: 214 | - pacemaker 215 | - role: ansible-nginx 216 | tasks: 217 | ``` 218 | 219 | ## License 220 | 221 | MIT 222 | 223 | ## Author Information 224 | 225 | Larry Smith Jr. 226 | 227 | - [@mrlesmithjr](https://www.twitter.com/mrlesmithjr) 228 | - [EverythingShouldBeVirtual](http://everythingshouldbevirtual.com) 229 | - mrlesmithjr [at] gmail.com 230 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for ansible-pacemaker 3 | corosync_authkey_file: '/etc/corosync/authkey' 4 | 5 | # Defines interface used for cluster 6 | corosync_bindnet_interface: 'enp0s8' 7 | 8 | corosync_config_file: '/etc/corosync/corosync.conf' 9 | 10 | # Defines the number of nodes to be functional in order to avoid split-brain 11 | # scenarios...ex. 2-nodes = 1, 3-nodes = 2 12 | corosync_expected_votes: "{{ ( groups[pacemaker_cluster_group]|count /2 ) | round (0, 'ceil') | int }}" 13 | 14 | # Corosync itself works without a cluster name, but DLM needs one. 15 | # The cluster name is also written into the VG metadata of newly 16 | # created shared LVM volume groups, if lvmlockd uses DLM locking. 17 | # It is also used for computing mcastaddr, unless overridden below. 18 | corosync_cluster_name: 'debian' 19 | 20 | # Setting corosync_last_man_standing to true enables the Last Man Standing (LMS) feature; 21 | # by default, it is disabled (set to false) 22 | corosync_last_man_standing: true 23 | 24 | # Define multicast address to use for cluster 25 | # this should be unique per cluster 26 | corosync_mcastaddr: 239.255.42.1 27 | 28 | # Define port number to configure as cluster port. 29 | corosync_mcastport: 5405 30 | 31 | # Defines if unicast mode should be used rather than multicast 32 | corosync_unicast_mode: false 33 | 34 | # Means that, When starting up a cluster (all nodes down), the cluster quorum 35 | # is held until all nodes are online and have joined the cluster for the first 36 | # time. This parameter is new in Corosync 2.0. 37 | corosync_wait_for_all: true 38 | 39 | pacemaker_cluster_constraints: [] 40 | # - constraint: 'colocation' 41 | # action: 'add' 42 | # source_resource_id: 'webserver' 43 | # target_resource_id: 'virtual_ip' 44 | # score: 'INFINITY' 45 | # - constraint: 'order' 46 | # order: 47 | # first_resource: 'virtual_ip' 48 | # first_resource_action: 'start' 49 | # second_resource: 'webserver' 50 | # second_resource_action: 'start' 51 | 52 | pacemaker_cluster_group: 'ha_cluster' 53 | 54 | pacemaker_cluster_resources: [] 55 | # - resource_id: 'virtual_ip' 56 | # action: 'create' 57 | # provider: 'ocf:heartbeat:IPaddr2' 58 | # options: 59 | # - 'ip=192.168.250.200' 60 | # - 'cidr_netmask=24' 61 | # op: 'monitor' 62 | # op_options: 63 | # - 'interval=30s' 64 | # - resource_id: 'webserver' 65 | # action: 'create' 66 | # provider: 'ocf:heartbeat:nginx' 67 | # options: 68 | # - 'configfile=/etc/nginx/nginx.conf' 69 | # op: 'monitor' 70 | # op_options: 71 | # - 'timeout=5s' 72 | # - 'interval=5s' 73 | 74 | # NOT RECOMMENDED FOR PRODUCTION!!!!! 75 | # You must have a STONITH device to enable.... 76 | pacemaker_disable_stonith: true 77 | 78 | # Define specific cluster settings to configure 79 | pacemaker_cluster_settings: [] 80 | # - property: 'start-failure-is-fatal' 81 | # value: 'false' 82 | # - property: 'pe-warn-series-max' 83 | # value: 1000 84 | # - property: 'pe-input-series-max' 85 | # value: 1000 86 | # - property: 'pe-error-series-max' 87 | # value: 1000 88 | # - property: 'cluster-recheck-interval' 89 | # value: 5min 90 | 91 | # Define hacluster user password for webUI 92 | # 93 | # Generate new password 94 | # echo "haclusteradmin" | sha512sum 95 | pacemaker_hacluster_password: 'f8d1feb7105dfbd2859a17512c7414f89b70dfef815b177444b897edec19a18724f8e9686f0e2daa41c48eb9b0511bae9e659a756f17c39fedb6d68b9230a53c' 96 | 97 | # Defines if host is considered to be primary 98 | # this should be set in host_vars/hostname as true for only one host 99 | pacemaker_primary_server: '{{ groups[pacemaker_cluster_group][0] }}' 100 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for ansible-pacemaker 3 | #- name: pacemaker commit ###commented out for now...broken in ansible 2.0 4 | # pacemaker: commit 5 | 6 | - name: restart corosync 7 | service: 8 | name: "corosync" 9 | state: "restarted" 10 | become: true 11 | 12 | - name: restart pacemaker 13 | service: 14 | name: "pacemaker" 15 | sleep: 10 16 | state: "restarted" 17 | become: true 18 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Larry Smith Jr. 4 | description: An [Ansible](https://www.ansible.com) role to install/configure [pacemaker/corosync](http://clusterlabs.org). 5 | 6 | license: MIT 7 | 8 | min_ansible_version: 2.0 9 | 10 | platforms: 11 | - name: Ubuntu 12 | versions: 13 | - trusty 14 | - xenial 15 | - name: Debian 16 | versions: 17 | - stretch 18 | 19 | categories: 20 | - clustering 21 | - networking 22 | - system 23 | 24 | dependencies: [] 25 | -------------------------------------------------------------------------------- /tasks/cluster.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: cluster | Capturing Cluster Properties 3 | command: "pcs property show" 4 | become: true 5 | register: "_pcs_property_show" 6 | changed_when: false 7 | 8 | - name: cluster | Capturing Cluster Resources 9 | command: "pcs resource show --full" 10 | become: true 11 | register: "_pcs_resource_show" 12 | changed_when: false 13 | 14 | - name: cluster | Capturing Cluster Constraints 15 | command: "pcs constraint show --full" 16 | become: true 17 | register: "_pcs_constraint_show" 18 | changed_when: false 19 | 20 | - name: cluster | Setting Stonith 21 | command: > 22 | pcs property set stonith-enabled=false 23 | become: true 24 | when: > 25 | pacemaker_disable_stonith and 26 | ('stonith-enabled: false' not in _pcs_property_show['stdout']) and 27 | (inventory_hostname == pacemaker_primary_server) 28 | 29 | - name: cluster | Setting Cluster Settings 30 | command: > 31 | pcs property set {{ item['property'] }}={{ item['value'] }} 32 | become: true 33 | with_items: '{{ pacemaker_cluster_settings }}' 34 | when: > 35 | pacemaker_cluster_settings is defined and 36 | (inventory_hostname == pacemaker_primary_server) and 37 | ("{{ item['property'] }}: {{ item['value'] }}" not in _pcs_property_show['stdout']) 38 | 39 | - name: cluster | Creating Cluster Resources 40 | command: > 41 | pcs resource create {{ item['resource_id'] }} 42 | {{ item['provider'] }} {{ item['options']|join(' ') }} 43 | {% if item['op'] is defined %}op {{ item['op'] }}{% endif %} 44 | {% if item['op_options'] is defined %}{{ item['op_options']|join(' ') }}{% endif %} 45 | become: true 46 | with_items: '{{ pacemaker_cluster_resources }}' 47 | when: > 48 | (pacemaker_cluster_resources is defined and 49 | inventory_hostname == pacemaker_primary_server) and 50 | (item['options'] is defined and 51 | (item['resource_id'] not in _pcs_resource_show['stdout'] and 52 | item['options']|join(' ') not in _pcs_resource_show['stdout'])) and 53 | item['action']|lower == 'create' 54 | 55 | - name: cluster | Creating Cluster Resources 56 | command: > 57 | pcs resource create {{ item['resource_id'] }} 58 | {{ item['provider'] }} 59 | {% if item['op'] is defined %}op {{ item['op'] }}{% endif %} 60 | {% if item['op_options'] is defined %}{{ item['op_options']|join(' ') }}{% endif %} 61 | become: true 62 | with_items: '{{ pacemaker_cluster_resources }}' 63 | when: > 64 | pacemaker_cluster_resources is defined and 65 | (inventory_hostname == pacemaker_primary_server) and 66 | item['options'] is not defined and 67 | (item['resource_id'] not in _pcs_resource_show['stdout'] and 68 | item['action']|lower == 'create') 69 | 70 | - name: cluster | Adding Cluster colocation Constraints 71 | command: > 72 | pcs constraint colocation add 73 | {% if item['source_resource_id'] is defined %} 74 | {{ item['source_resource_id'] }} 75 | {% endif %} 76 | {% if item['target_resource_id'] is defined %} 77 | {{ item['target_resource_id'] }} 78 | {% endif %} 79 | {{ item['score']|default('INFINITY') }} 80 | become: true 81 | with_items: '{{ pacemaker_cluster_constraints }}' 82 | when: > 83 | pacemaker_cluster_constraints is defined and 84 | (inventory_hostname == pacemaker_primary_server) and 85 | (((item['action'] is defined and 86 | item['action']|lower == 'add') and 87 | item['constraint']|lower == 'colocation') and 88 | (item['source_resource_id'] and 89 | item['target_resource_id'] not in _pcs_constraint_show['stdout'])) 90 | 91 | - name: cluster | Cluster order Constraints 92 | command: > 93 | pcs constraint order 94 | {{ item['order']['first_resource_action'] }} 95 | {{ item['order']['first_resource'] }} 96 | then 97 | {% if item['order']['second_resource_action'] is defined %} 98 | {{ item['order']['second_resource_action'] }} 99 | {% endif %} 100 | {{ item['order']['second_resource'] }} 101 | {% if item['op_options'] is defined %}{{ item['op_options']|join(' ') }}{% endif %} 102 | become: true 103 | with_items: '{{ pacemaker_cluster_constraints }}' 104 | when: > 105 | pacemaker_cluster_constraints is defined and 106 | (inventory_hostname == pacemaker_primary_server) and 107 | ((item['constraint']|lower == 'order') and 108 | item['order'] is defined) and 109 | ((item['second_resource_action'] is defined and item['order']['first_resource_action']+" "+item['order']['first_resource']+" then "+item['order']['second_resource_action']+" "+item['order']['second_resource'] not in _pcs_constraint_show['stdout']) or 110 | (item['second_resource_action'] is not defined and item['order']['first_resource_action']+" "+item['order']['first_resource'] and item['order']['second_resource'] not in _pcs_constraint_show['stdout'])) 111 | -------------------------------------------------------------------------------- /tasks/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: config | Setting Facts 3 | set_fact: 4 | corosync_bindnet_addr: "{{ hostvars[inventory_hostname]['ansible_' + corosync_bindnet_interface]['ipv4']['address'] }}" 5 | 6 | - name: config | Setting hacluster password 7 | user: 8 | name: "hacluster" 9 | password: "{{ pacemaker_hacluster_password }}" 10 | become: true 11 | 12 | - name: config | Capturing Corosync Auth Key 13 | slurp: 14 | src: "{{ corosync_authkey_file }}" 15 | become: true 16 | register: "_corosync_authkey_" 17 | no_log: true 18 | changed_when: false 19 | when: (inventory_hostname == pacemaker_primary_server) 20 | 21 | - name: config | Setting Fact For Corosync Auth Key On Non Masters 22 | set_fact: 23 | _corosync_authkey_: "{{ hostvars[pacemaker_primary_server]['_corosync_authkey_'] }}" 24 | no_log: true 25 | when: (inventory_hostname != pacemaker_primary_server) 26 | 27 | - name: config | Configuring Corosync Auth Key On Non Masters 28 | template: 29 | src: "etc/corosync/authkey.j2" 30 | dest: "{{ corosync_authkey_file }}" 31 | owner: "root" 32 | group: "root" 33 | mode: "u=r,g=,o=" 34 | become: true 35 | no_log: true 36 | when: (inventory_hostname != pacemaker_primary_server) 37 | 38 | - name: config | configuring corosync 39 | template: 40 | src: "etc/corosync/corosync.conf.j2" 41 | dest: "{{ corosync_config_file }}" 42 | owner: "root" 43 | group: "root" 44 | mode: "u=rw,g=r,o=r" 45 | become: true 46 | notify: 47 | - restart corosync 48 | - restart pacemaker 49 | register: "_corosync_reconfigured" 50 | 51 | - name: config | configuring corosync service to start 52 | template: 53 | src: "etc/default/corosync.j2" 54 | dest: "/etc/default/corosync" 55 | owner: "root" 56 | group: "root" 57 | mode: "u=rw,g=r,o=r" 58 | become: true 59 | notify: 60 | - restart corosync 61 | - restart pacemaker 62 | 63 | # Flush handlers 64 | - meta: flush_handlers 65 | become: true 66 | 67 | - name: config | Ensuring Service Are Enabled 68 | service: 69 | name: "{{ item }}" 70 | enabled: true 71 | become: true 72 | with_items: 73 | - 'corosync' 74 | - 'pacemaker' 75 | - 'pcsd' 76 | 77 | - name: config | Ensuring PCSD Service Is Started 78 | service: 79 | name: 'pcsd' 80 | state: "started" 81 | become: true 82 | -------------------------------------------------------------------------------- /tasks/debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: debian | Installing Packages 3 | apt: 4 | name: "{{ item }}" 5 | state: "present" 6 | become: true 7 | with_items: 8 | - 'cluster-glue' 9 | - 'corosync' 10 | - 'crmsh' 11 | - 'fence-agents' 12 | - 'pacemaker' 13 | - 'pcs' 14 | - 'resource-agents' 15 | 16 | - name: debian | Checking If {{ corosync_authkey_file }} Exists 17 | stat: 18 | path: "{{ corosync_authkey_file }}" 19 | register: "_corosync_authkey" 20 | 21 | - name: debian | Installing haveged On {{ pacemaker_primary_server }} 22 | apt: 23 | name: "haveged" 24 | state: "present" 25 | become: true 26 | when: > 27 | not _corosync_authkey['stat']['exists'] and 28 | (inventory_hostname == pacemaker_primary_server) 29 | 30 | - name: debian | Generating corosync authkey On {{ pacemaker_primary_server }} 31 | command: corosync-keygen 32 | become: true 33 | register: "_corosync_auth_key_generated" 34 | when: > 35 | not _corosync_authkey['stat']['exists'] and 36 | (inventory_hostname == pacemaker_primary_server) 37 | 38 | - name: debian | Uninstalling haveged On {{ pacemaker_primary_server }} 39 | apt: 40 | name: "haveged" 41 | purge: true 42 | state: "absent" 43 | become: true 44 | when: > 45 | _corosync_auth_key_generated['changed'] and 46 | (inventory_hostname == pacemaker_primary_server) 47 | 48 | - name: debian | Ensuring /etc/corosync/uidgid.d Folder Exists 49 | file: 50 | path: "/etc/corosync/uidgid.d" 51 | state: "directory" 52 | become: true 53 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for ansible-pacemaker 3 | - include: debian.yml 4 | when: ansible_os_family == "Debian" 5 | 6 | - include: config.yml 7 | tags: 8 | - pacemaker_config 9 | 10 | - include: cluster.yml 11 | tags: 12 | - pacemaker_cluster 13 | -------------------------------------------------------------------------------- /templates/etc/corosync/authkey.j2: -------------------------------------------------------------------------------- 1 | {{ _corosync_authkey_ }} 2 | -------------------------------------------------------------------------------- /templates/etc/corosync/corosync.conf.j2: -------------------------------------------------------------------------------- 1 | totem { 2 | version: 2 3 | cluster_name: {{ corosync_cluster_name }} 4 | token: 3000 5 | token_retransmits_before_loss_const: 10 6 | clear_node_high_bit: yes 7 | crypto_cipher: none 8 | crypto_hash: none 9 | interface { 10 | ringnumber: 0 11 | bindnetaddr: {{ corosync_bindnet_addr }} 12 | mcastport: {{ corosync_mcastport }} 13 | ttl: 1 14 | } 15 | {% if corosync_unicast_mode %} 16 | nodelist{ 17 | {% for host in groups[pacemaker_cluster_group] %} 18 | node { 19 | ring0_addr: {{ hostvars[host]['corosync_bindnet_addr'] }} 20 | name: {{ host }} 21 | nodeid: {{ loop.index + 1 }} 22 | } 23 | {% endfor %} 24 | } 25 | {% endif %} 26 | } 27 | 28 | logging { 29 | fileline: off 30 | to_stderr: no 31 | to_logfile: no 32 | to_syslog: yes 33 | syslog_facility: daemon 34 | debug: off 35 | timestamp: on 36 | logger_subsys { 37 | subsys: QUORUM 38 | debug: off 39 | } 40 | } 41 | 42 | quorum { 43 | provider: corosync_votequorum 44 | expected_votes: {{ corosync_expected_votes }} 45 | {% if corosync_wait_for_all is defined and corosync_wait_for_all %} 46 | wait_for_all: 1 47 | {% endif %} 48 | {% if corosync_last_man_standing is defined and corosync_last_man_standing %} 49 | last_man_standing: 1 50 | {% endif %} 51 | } 52 | -------------------------------------------------------------------------------- /templates/etc/corosync/corosync.conf.j2.orig: -------------------------------------------------------------------------------- 1 | # Please read the openais.conf.5 manual page 2 | 3 | totem { 4 | version: 2 5 | 6 | # How long before declaring a token lost (ms) 7 | token: 3000 8 | 9 | # How many token retransmits before forming a new configuration 10 | token_retransmits_before_loss_const: 10 11 | 12 | # How long to wait for join messages in the membership protocol (ms) 13 | join: 60 14 | 15 | # How long to wait for consensus to be achieved before starting a new round of membership configuration (ms) 16 | consensus: 3600 17 | 18 | # Turn off the virtual synchrony filter 19 | vsftype: none 20 | 21 | # Number of messages that may be sent by one processor on receipt of the token 22 | max_messages: 20 23 | 24 | # Limit generated nodeids to 31-bits (positive signed integers) 25 | clear_node_high_bit: yes 26 | 27 | # Disable encryption 28 | secauth: off 29 | 30 | # How many threads to use for encryption/decryption 31 | threads: 0 32 | 33 | # Optionally assign a fixed node id (integer) 34 | # nodeid: 1234 35 | 36 | # This specifies the mode of redundant ring, which may be none, active, or passive. 37 | rrp_mode: none 38 | 39 | # interface { 40 | # # The following values need to be set based on your environment 41 | # ringnumber: 0 42 | # bindnetaddr: 127.0.0.1 43 | # mcastaddr: 226.94.1.1 44 | # mcastport: 5405 45 | # } 46 | interface { 47 | # The following values need to be set based on your environment 48 | ringnumber: 0 49 | bindnetaddr: {{ corosync_bindnet_addr|default ('127.0.0.1') }} 50 | mcastaddr: {{ corosync_mcastaddr|default ('226.94.1.1') }} 51 | mcastport: {{ corosync_mcastport|default ('5405') }} 52 | } 53 | } 54 | 55 | amf { 56 | mode: disabled 57 | } 58 | 59 | quorum { 60 | # Quorum for the Pacemaker Cluster Resource Manager 61 | provider: corosync_votequorum 62 | expected_votes: {{ corosync_expected_votes|default ('1') }} 63 | {% if corosync_wait_for_all is defined and corosync_wait_for_all %} 64 | wait_for_all: 1 65 | {% endif %} 66 | {% if corosync_last_man_standing is defined and corosync_last_man_standing %} 67 | last_man_standing: 1 68 | {% endif %} 69 | } 70 | 71 | aisexec { 72 | user: root 73 | group: root 74 | } 75 | 76 | logging { 77 | fileline: off 78 | to_stderr: yes 79 | to_logfile: no 80 | to_syslog: yes 81 | syslog_facility: daemon 82 | debug: off 83 | timestamp: on 84 | logger_subsys { 85 | subsys: AMF 86 | debug: off 87 | tags: enter|leave|trace1|trace2|trace3|trace4|trace6 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /templates/etc/default/corosync.j2: -------------------------------------------------------------------------------- 1 | # Corosync runtime directory 2 | #COROSYNC_RUN_DIR=/var/lib/corosync 3 | 4 | # Path to corosync.conf 5 | COROSYNC_MAIN_CONFIG_FILE={{ corosync_config_file }} 6 | 7 | # Path to authfile 8 | COROSYNC_TOTEM_AUTHKEY_FILE={{ corosync_authkey_file }} 9 | 10 | # Command line options 11 | #OPTIONS="" 12 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for ansible-pacemaker 3 | --------------------------------------------------------------------------------