aboutsummaryrefslogtreecommitdiff
path: root/ansible/roles/rabbitmq/tasks/precheck.yml
blob: a5c8f6340f6ab45ac98def9905ec64521dd75e69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
---
- name: Precheck rabbitmq configuration
  ansible.builtin.import_role:
    name: service-precheck
  vars:
    service_precheck_services: "{{ rabbitmq_services }}"
    service_name: "{{ project_name }}"

- name: Get container facts
  become: true
  kolla_container_facts:
    action: get_containers
    container_engine: "{{ kolla_container_engine }}"
    name:
      - rabbitmq
  check_mode: false
  register: container_facts

- name: Checking free port for RabbitMQ
  ansible.builtin.wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ rabbitmq_port }}"
    connect_timeout: 1
    timeout: 1
    state: stopped
  when:
    - container_facts.containers['rabbitmq'] is not defined
    - inventory_hostname in groups['rabbitmq']

- name: Checking free port for RabbitMQ Management
  ansible.builtin.wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ rabbitmq_management_port }}"
    connect_timeout: 1
    timeout: 1
    state: stopped
  when:
    - container_facts.containers['rabbitmq'] is not defined
    - inventory_hostname in groups['rabbitmq']

- name: Checking free port for RabbitMQ Cluster
  ansible.builtin.wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ rabbitmq_cluster_port }}"
    connect_timeout: 1
    timeout: 1
    state: stopped
  when:
    - container_facts.containers['rabbitmq'] is not defined
    - inventory_hostname in groups['rabbitmq']

- name: Checking free port for RabbitMQ EPMD
  ansible.builtin.wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ rabbitmq_epmd_port }}"
    connect_timeout: 1
    timeout: 1
    state: stopped
  when:
    - container_facts.containers['rabbitmq'] is not defined
    - inventory_hostname in groups['rabbitmq']

- name: Check if all rabbit hostnames are resolvable
  vars:
    nss_database: "{{ 'ahostsv4' if api_address_family == 'ipv4' else 'ahostsv6' }}"
  ansible.builtin.command: "getent {{ nss_database }} {{ hostvars[item].ansible_facts.hostname }}"
  changed_when: false
  check_mode: false
  register: rabbitmq_hostnames
  with_items: "{{ groups['rabbitmq'] }}"

- name: Check if each rabbit hostname resolves uniquely to the proper IP address
  ansible.builtin.fail:
    msg: Hostname has to resolve uniquely to the IP address of api_interface
  with_subelements:
    - "{{ rabbitmq_hostnames.results }}"
    - stdout_lines
  when:
    - not item.1 is match('^'+('api' | kolla_address(item.0.item))+'\\b')

- name: Check if TLS certificate exists for RabbitMQ
  ansible.builtin.assert:
    that: cert | length > 0
    fail_msg: No TLS certificate provided for RabbitMQ.
  vars:
    cert: "{{ query('first_found', paths, errors='ignore') }}"
    paths:
      - "{{ kolla_certificates_dir }}/{{ inventory_hostname }}/rabbitmq-cert.pem"
      - "{{ kolla_certificates_dir }}/{{ inventory_hostname }}-cert.pem"
      - "{{ kolla_certificates_dir }}/rabbitmq-cert.pem"
  when:
    - not kolla_externally_managed_cert | bool
    - rabbitmq_enable_tls | bool

- name: Check if TLS key exists for RabbitMQ
  ansible.builtin.assert:
    that: key | length > 0
    fail_msg: No TLS key provided for RabbitMQ.
  vars:
    key: "{{ query('first_found', paths, errors='ignore') }}"
    paths:
      - "{{ kolla_certificates_dir }}/{{ inventory_hostname }}/rabbitmq-key.pem"
      - "{{ kolla_certificates_dir }}/{{ inventory_hostname }}-key.pem"
      - "{{ kolla_certificates_dir }}/rabbitmq-key.pem"
  when:
    - not kolla_externally_managed_cert | bool
    - rabbitmq_enable_tls | bool

- name: Check RabbitMQ HA compatibility
  run_once: true
  when:
    - container_facts.containers['rabbitmq'] is defined
  tags: rabbitmq-ha-precheck
  block:
    - name: List RabbitMQ queues
      become: true
      ansible.builtin.command: "{{ kolla_container_engine }} exec rabbitmq rabbitmqctl list_queues --silent name type --formatter json"
      register: rabbitmq_queues
      changed_when: false
      check_mode: false

    - name: Check if RabbitMQ quorum queues need to be configured
      ansible.builtin.assert:
        that: "{{ item.type == 'quorum' }}"
        fail_msg: >
          {{ item.name }} is a non-quorum queue.
          Currently the procedure to migrate to quorum queues is manual.
          Please follow the process described here: https://docs.openstack.org/kolla-ansible/latest/reference/message-queues/rabbitmq.html#high-availability.
          Note that this process may take several hours on larger systems, and may cause a degradation in performance at large scale.
      loop: "{{ (rabbitmq_queues.stdout | from_json) if rabbitmq_queues is not skipped else [] }}"
      loop_control:
        label: "{{ item.name }}"
      when: not (item.name is search('reply_') or item.name is search('_fanout'))

    - name: Check if RabbitMQ quorum queues for transient queues need to be configured
      ansible.builtin.assert:
        that: "{{ item.type == 'quorum' }}"
        fail_msg: >
          {{ item.name }} is a non-quorum queue.
          Currently the procedure to migrate to quorum queues is manual.
          Please follow the process described here: https://docs.openstack.org/kolla-ansible/latest/reference/message-queues/rabbitmq.html#high-availability.
          Note that this process may take several hours on larger systems, and may cause a degradation in performance at large scale.
      loop: "{{ (rabbitmq_queues.stdout | from_json) if rabbitmq_queues is not skipped else [] }}"
      loop_control:
        label: "{{ item.name }}"
      when:
        - item.name is search('reply_') or (item.name is search('_fanout') and not om_enable_rabbitmq_stream_fanout | bool)

    - name: Check if RabbitMQ streams need to be configured
      ansible.builtin.assert:
        that: "{{ item.type == 'stream' }}"
        fail_msg: >
          om_enable_rabbitmq_stream_fanout is True but {{ item.name }} is not a stream.
          Currently the procedure to migrate to streams is manual.
          Please follow the process described here: https://docs.openstack.org/kolla-ansible/latest/reference/message-queues/rabbitmq.html#high-availability.
          Note that this process may take several hours on larger systems.
          If you do not wish to enable this feature, set om_enable_rabbitmq_stream_fanout to False.
      loop: "{{ (rabbitmq_queues.stdout | from_json) if rabbitmq_queues is not skipped else [] }}"
      loop_control:
        label: "{{ item.name }}"
      when:
        - item.name is search('_fanout')
        - om_enable_rabbitmq_stream_fanout | bool

- name: Check if RabbitMQ stream queue policy variables are valid
  when: om_enable_rabbitmq_stream_fanout | bool
  block:
    - name: Check if the value of rabbitmq_stream_max_segment_size_bytes is valid
      ansible.builtin.assert:
        that:
          - rabbitmq_stream_max_segment_size_bytes is integer
          - rabbitmq_stream_max_segment_size_bytes > 0
        fail_msg: >
          rabbitmq_stream_max_segment_size_bytes needs to be a positive integer.
          Please check its value again.

    - name: Check if the value of rabbitmq_stream_segment_max_age is valid
      ansible.builtin.assert:
        that:
          - rabbitmq_stream_segment_max_age is string
          - 'rabbitmq_stream_segment_max_age is regex("^[0-9]+[YMDhms]$")'
        fail_msg: >
          rabbitmq_stream_segment_max_age needs to have numeric string that ends with one of the units in [Y, M, D, h, m, s].
          Please check its value again.