diff --git a/ansible-role-requirements.yml b/ansible-role-requirements.yml
index 03009eee6c..31af421eb9 100644
--- a/ansible-role-requirements.yml
+++ b/ansible-role-requirements.yml
@@ -347,3 +347,10 @@
version: master
trackbranch: master
shallow_since: '2022-06-19'
+- name: zookeeper
+ src: https://opendev.org/openstack/ansible-role-zookeeper
+ scm: git
+ version: master
+ trackbranch: master
+ shallow_since: '2022-06-19'
+
diff --git a/doc/source/contributor/role-maturity-matrix.html b/doc/source/contributor/role-maturity-matrix.html
index 546314c12f..036a4b4d2b 100644
--- a/doc/source/contributor/role-maturity-matrix.html
+++ b/doc/source/contributor/role-maturity-matrix.html
@@ -320,6 +320,14 @@
✔ |
✔ |
+
+ pki |
+ Wallaby |
+ Complete |
+ ✔ |
+ ✔ |
+ ✔ |
+
plugins |
Mitaka |
@@ -344,6 +352,22 @@
✔ |
✔ |
+
+ uwsgi |
+ Train |
+ Complete |
+ ✔ |
+ ✔ |
+ ✔ |
+
+
+ zookeeper |
+ Zed |
+ Complete |
+ ✔ |
+ ✔ |
+ ✔ |
+
Retired roles
diff --git a/etc/openstack_deploy/openstack_user_config.yml.aio.j2 b/etc/openstack_deploy/openstack_user_config.yml.aio.j2
index d01e98feff..6230377bea 100644
--- a/etc/openstack_deploy/openstack_user_config.yml.aio.j2
+++ b/etc/openstack_deploy/openstack_user_config.yml.aio.j2
@@ -242,3 +242,13 @@ repo-infra_hosts:
repo_container: 3
{% endif %}
ip: 172.29.236.100
+
+{% if 'zookeeper' in bootstrap_host_scenarios_expanded %}
+coordination_hosts:
+ aio1:
+ ip: 172.29.236.100
+{% if 'infra' in bootstrap_host_scenarios_expanded %}
+ affinity:
+ zookeeper_container: 3
+{% endif %}
+{% endif %}
diff --git a/etc/openstack_deploy/openstack_user_config.yml.example b/etc/openstack_deploy/openstack_user_config.yml.example
index 1e6405c38e..98c1d51b82 100644
--- a/etc/openstack_deploy/openstack_user_config.yml.example
+++ b/etc/openstack_deploy/openstack_user_config.yml.example
@@ -351,6 +351,25 @@
#
# --------
#
+# Level: coordination_hosts (optional)
+# Some services, like cinder , octavia, gnocchi or designate require
+# coordination service to be present for some use-cases. As such service
+# Zookeeper is being used.
+#
+# Example:
+#
+# Define three hosts for zookeeper cluster:
+#
+# coordination_hosts:
+# infra1:
+# ip: 172.29.236.101
+# infra2:
+# ip: 172.29.236.102
+# infra3:
+# ip: 172.29.236.103
+#
+# --------
+#
# Level: os-infra_hosts (required)
# List of target hosts on which to deploy the glance API, nova API, heat API,
# and horizon. Recommend three minimum target hosts for these services.
diff --git a/etc/openstack_deploy/openstack_user_config.yml.prod-ceph.example b/etc/openstack_deploy/openstack_user_config.yml.prod-ceph.example
index 16d1111aa6..fa013b7ffb 100644
--- a/etc/openstack_deploy/openstack_user_config.yml.prod-ceph.example
+++ b/etc/openstack_deploy/openstack_user_config.yml.prod-ceph.example
@@ -105,6 +105,9 @@ ceph-osd_hosts:
# galera, memcache, rabbitmq, utility
shared-infra_hosts: *infrastructure_hosts
+# zookeeper
+coordination_hosts: *infrastructure_hosts
+
# ceph-mon containers
ceph-mon_hosts: *infrastructure_hosts
diff --git a/etc/openstack_deploy/openstack_user_config.yml.prod.example b/etc/openstack_deploy/openstack_user_config.yml.prod.example
index 2154a1417e..8eea40a6f2 100644
--- a/etc/openstack_deploy/openstack_user_config.yml.prod.example
+++ b/etc/openstack_deploy/openstack_user_config.yml.prod.example
@@ -84,6 +84,15 @@ shared-infra_hosts:
infra3:
ip: 172.29.236.13
+# zookeeper
+coordination_hosts:
+ infra1:
+ ip: 172.29.236.11
+ infra2:
+ ip: 172.29.236.12
+ infra3:
+ ip: 172.29.236.13
+
# repository (apt cache, python packages, etc)
repo-infra_hosts:
infra1:
diff --git a/inventory/env.d/zookeeper.yml b/inventory/env.d/zookeeper.yml
new file mode 100644
index 0000000000..3f33eb0798
--- /dev/null
+++ b/inventory/env.d/zookeeper.yml
@@ -0,0 +1,21 @@
+---
+
+component_skel:
+ zookeeper:
+ belongs_to:
+ - zookeeper_all
+
+container_skel:
+ zookeeper_container:
+ belongs_to:
+ - coordination_containers
+ contains:
+ - zookeeper
+
+physical_skel:
+ coordination_containers:
+ belongs_to:
+ - all_containers
+ coordination_hosts:
+ belongs_to:
+ - hosts
diff --git a/inventory/group_vars/zookeeper_all.yml b/inventory/group_vars/zookeeper_all.yml
new file mode 100644
index 0000000000..07633fff60
--- /dev/null
+++ b/inventory/group_vars/zookeeper_all.yml
@@ -0,0 +1,18 @@
+---
+# Copyright 2022 City Network International AB
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+zookeeper_container_bind_mounts:
+ - bind_dir_path: "/var/lib/zookeeper"
+ mount_path: "/openstack/{{ inventory_hostname }}"
diff --git a/inventory/inventory.ini b/inventory/inventory.ini
index 5724c8e984..7b6a88a66c 100644
--- a/inventory/inventory.ini
+++ b/inventory/inventory.ini
@@ -257,6 +257,8 @@ swift_remote
[trove_all]
+[zookeeper_all]
+
[zun_all:children]
zun_api
zun_compute
diff --git a/playbooks/healthcheck-infrastructure.yml b/playbooks/healthcheck-infrastructure.yml
index bafe6bdcc4..61098b63ee 100644
--- a/playbooks/healthcheck-infrastructure.yml
+++ b/playbooks/healthcheck-infrastructure.yml
@@ -361,4 +361,39 @@
- healthcheck-rabbitmq-install
- healthcheck-teardown
+# Test zookeeper-install
+
+- name: Ensure coordination is running and accepting connections
+ hosts: utility_all[0]
+ tasks:
+ - name: Probing TCP connection to zookeeper
+ wait_for:
+ host: "{{ hostvars[item]['ansible_host'] }}"
+ port: "{{ coordination_port | default(2181) }}"
+ with_items: "{{ groups[coordination_host_group | default('zookeeper_all')] }}"
+
+- name: Ensure zookeeper is healthy
+ hosts: "zookeeper_all"
+ tasks:
+ - name: Esuring netcat is installed
+ package:
+ name: "{% if ansible_facts['os_family'] | lower == 'redhat' %}nmap-ncat{% else %}netcat-openbsd{% endif %}"
+ state: present
+
+ - name: Gathering zookeeper state
+ shell: "echo ruok | nc localhost {{ coordination_port | default(2181) }}"
+ register: zookeeper_ok
+ changed_when: false
+
+ - name: Gathering zookeeper rw/ro
+ shell: "echo isro | nc localhost {{ coordination_port | default(2181) }}"
+ register: zookeeper_ro
+ changed_when: false
+
+ - name: Check zookeeper results
+ assert:
+ that:
+ - "'imok' in zookeeper_ok.stdout"
+ - "'rw' in zookeeper_ro.stdout"
+
# TODO: Other playbook's tests.
diff --git a/playbooks/setup-infrastructure.yml b/playbooks/setup-infrastructure.yml
index b8e1ae33ea..e31858ec45 100644
--- a/playbooks/setup-infrastructure.yml
+++ b/playbooks/setup-infrastructure.yml
@@ -22,6 +22,7 @@
- import_playbook: rabbitmq-install.yml
- import_playbook: utility-install.yml
- import_playbook: etcd-install.yml
+- import_playbook: zookeeper-install.yml
- import_playbook: ceph-install.yml
- import_playbook: ceph-nfs-install.yml
diff --git a/playbooks/zookeeper-install.yml b/playbooks/zookeeper-install.yml
new file mode 100644
index 0000000000..f7d3583ad0
--- /dev/null
+++ b/playbooks/zookeeper-install.yml
@@ -0,0 +1,42 @@
+---
+# Copyright 2022 City Network International AB
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Gather zookeeper facts
+ hosts: zookeeper_all
+ gather_facts: "{{ osa_gather_facts | default(True) }}"
+ tags:
+ - always
+
+- name: Install zookeeper
+ hosts: zookeeper_all
+ gather_facts: false
+ serial: "{{ zookeeper_serial | default(['1','100%']) }}"
+ user: root
+ environment: "{{ deployment_environment_variables | default({}) }}"
+ pre_tasks:
+ - include_tasks: common-tasks/os-log-dir-setup.yml
+ - include_tasks: "common-tasks/os-{{ container_tech | default('lxc') }}-container-setup.yml"
+ when: not is_metal
+ vars:
+ list_of_bind_mounts: "{{ zookeeper_container_bind_mounts }}"
+ roles:
+ - role: zookeeper
+ tags:
+ - zookeeper
+ - role: "openstack.osa.system_crontab_coordination"
+ tags:
+ - crontab
+ tags:
+ - zookeeper
diff --git a/releasenotes/notes/add_zookeeper-368bb29ffb35b36e.yaml b/releasenotes/notes/add_zookeeper-368bb29ffb35b36e.yaml
new file mode 100644
index 0000000000..b3fabc8f33
--- /dev/null
+++ b/releasenotes/notes/add_zookeeper-368bb29ffb35b36e.yaml
@@ -0,0 +1,30 @@
+---
+
+features:
+ - |
+ Added ``zookepeer`` role which deploys zookeeper cluster that can be used
+ as a coordination driver for services like cinder, designate, octavia, etc.
+ For deployment you need to specify ``coordination_hosts`` in your conf.d
+ or openstack_user_config.yml and run ``zookeeper-install.yml`` playbook.
+ - |
+ Added following variables that are designed to control coordination
+ configuration. Reasonable defaults are set for services to work out of
+ the box.
+
+ * coordination_driver
+ * coordination_group
+ * coordination_client_ssl
+ * coordination_verify_cert
+ * coordination_port
+
+ Also each service that uses coordination have following variables defined:
+
+ * _coordination_enable
+ * _coordination_url
+
+upgrade:
+ - |
+ If you are using cinder in active/active mode (ie with Ceph backend), it's
+ highly recommended to define ``coordination_hosts`` before upgrade to
+ deploy zookeeper coordination cluster which is required for proper work
+ of cinder active/active mode.
diff --git a/scripts/log-collect.sh b/scripts/log-collect.sh
index 3d1e7c513b..b970a0c9b3 100755
--- a/scripts/log-collect.sh
+++ b/scripts/log-collect.sh
@@ -73,6 +73,7 @@ COMMON_ETC_LOG_NAMES="apt \
uwsgi \
yum \
yum.repos.d \
+ zookeeper \
zypp"
COMMON_ETC_LOG_NAMES+=" $(awk -F'os_' '/name.*os_.*/ {print $2}' $(dirname $(readlink -f ${BASH_SOURCE[0]}))/../ansible-role-requirements.yml | tr '\n' ' ')"
diff --git a/tests/roles/bootstrap-host/vars/main.yml b/tests/roles/bootstrap-host/vars/main.yml
index 97ec0f087d..42c3389323 100644
--- a/tests/roles/bootstrap-host/vars/main.yml
+++ b/tests/roles/bootstrap-host/vars/main.yml
@@ -48,6 +48,9 @@ bootstrap_host_scenarios_expanded: |-
{% if 'calico' in bootstrap_host_scenarios %}
{% set _ = scenario_list.extend(['etcd']) %}
{% endif %}
+ {% if 'designate' in bootstrap_host_scenarios %}
+ {% set _ = scenario_list.extend(['zookeeper']) %}
+ {% endif %}
{% if 'ironic' in bootstrap_host_scenarios %}
{% set _ = scenario_list.extend(['swift']) %}
{% endif %}
diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml
index 203c70c4b2..c70ff8e8ca 100644
--- a/zuul.d/jobs.yaml
+++ b/zuul.d/jobs.yaml
@@ -102,6 +102,7 @@
- name: openstack/ansible-role-python_venv_build
- name: openstack/ansible-role-uwsgi
- name: openstack/ansible-role-pki
+ - name: openstack/ansible-role-zookeeper
# OpenStack service repos - listed here to make cached repos available in CI
- name: openstack/requirements
# Murano distro deployment does need access to valid git repo anyway
@@ -187,6 +188,7 @@
- name: openstack/ansible-role-python_venv_build
- name: openstack/ansible-role-uwsgi
- name: openstack/ansible-role-pki
+ - name: openstack/ansible-role-zookeeper
# OpenStack service repos - listed here to make cached repos available in CI
- name: openstack/requirements
- name: openstack/adjutant