From 039cc2be509f447721daa3fb80cdcaa5b439723e Mon Sep 17 00:00:00 2001
From: Mark Goddard <mark@stackhpc.com>
Date: Mon, 23 Sep 2019 15:05:40 +0100
Subject: [PATCH] Add service-rabbitmq role

This role can be used by other roles to register RabbitMQ resources.
Currently support is provided for creating virtual hosts and users.

Change-Id: Ie1774a10b4d629508584af679b8aa9e372847804
Partially Implements: blueprint support-nova-cells
Depends-On: https://review.opendev.org/684742
---
 ansible/library/kolla_toolbox.py              | 13 +++++-
 ansible/roles/common/tasks/config.yml         | 10 +++++
 .../common/templates/kolla-toolbox.json.j2    |  9 +++-
 .../roles/service-rabbitmq/defaults/main.yml  | 25 +++++++++++
 ansible/roles/service-rabbitmq/tasks/main.yml | 42 +++++++++++++++++++
 5 files changed, 96 insertions(+), 3 deletions(-)
 create mode 100644 ansible/roles/service-rabbitmq/defaults/main.yml
 create mode 100644 ansible/roles/service-rabbitmq/tasks/main.yml

diff --git a/ansible/library/kolla_toolbox.py b/ansible/library/kolla_toolbox.py
index 4d9dd1c02f..276661df29 100644
--- a/ansible/library/kolla_toolbox.py
+++ b/ansible/library/kolla_toolbox.py
@@ -45,6 +45,11 @@ options:
       - The extra variables used by the module
     required: False
     type: str or dict
+  user:
+    description:
+      - The user to execute Ansible inside kolla_toolbox with
+    required: False
+    type: str
   api_version:
     description:
       - The version of the API for docker-py to use when contacting Docker
@@ -132,6 +137,7 @@ def main():
         module_extra_vars=dict(type='json'),
         api_version=dict(required=False, type='str', default='auto'),
         timeout=dict(required=False, type='int', default=180),
+        user=dict(required=False, type='str'),
     )
     module = AnsibleModule(argument_spec=specs, bypass_checks=True)
     client = get_docker_client()(
@@ -144,6 +150,9 @@ def main():
         module.fail_json(msg='kolla_toolbox container is not running.')
 
     kolla_toolbox = kolla_toolbox[0]
+    kwargs = {}
+    if 'user' in module.params:
+        kwargs['user'] = module.params['user']
 
     # NOTE(mgoddard): Docker 1.12 has API version 1.24, and was installed by
     # kolla-ansible bootstrap-servers on Rocky and earlier releases. This API
@@ -158,7 +167,7 @@ def main():
         environment = {"ANSIBLE_STDOUT_CALLBACK": "json",
                        "ANSIBLE_LOAD_CALLBACK_PLUGINS": "True"}
         job = client.exec_create(kolla_toolbox, command_line,
-                                 environment=environment)
+                                 environment=environment, **kwargs)
         json_output = client.exec_start(job)
 
         try:
@@ -192,7 +201,7 @@ def main():
         # Remove Ansible's internal variables from returned fields.
         ret.pop('_ansible_no_log', None)
     else:
-        job = client.exec_create(kolla_toolbox, command_line)
+        job = client.exec_create(kolla_toolbox, command_line, **kwargs)
         output = client.exec_start(job)
 
         for exp in [JSON_REG, NON_JSON_REG]:
diff --git a/ansible/roles/common/tasks/config.yml b/ansible/roles/common/tasks/config.yml
index 96a2b26a88..2da793ba33 100644
--- a/ansible/roles/common/tasks/config.yml
+++ b/ansible/roles/common/tasks/config.yml
@@ -340,6 +340,16 @@
   notify:
     - Restart cron container
 
+- name: Ensure RabbitMQ Erlang cookie exists
+  become: true
+  copy:
+    content: "{{ rabbitmq_cluster_cookie }}"
+    dest: "{{ node_config_directory }}/kolla-toolbox/rabbitmq-erlang.cookie"
+    mode: "0660"
+  when: enable_rabbitmq | bool
+  notify:
+    - Restart kolla-toolbox container
+
 - name: Ensuring config directories have correct owner and permission
   become: true
   file:
diff --git a/ansible/roles/common/templates/kolla-toolbox.json.j2 b/ansible/roles/common/templates/kolla-toolbox.json.j2
index 7f0dc05193..1f7a56a9f1 100644
--- a/ansible/roles/common/templates/kolla-toolbox.json.j2
+++ b/ansible/roles/common/templates/kolla-toolbox.json.j2
@@ -1,6 +1,13 @@
 {
     "command": "sleep infinity",
-    "config_files": [],
+    "config_files": [
+        {% if enable_rabbitmq | bool %}{
+            "source": "{{ container_config_directory }}/rabbitmq-erlang.cookie",
+            "dest": "/var/lib/rabbitmq/.erlang.cookie",
+            "owner": "rabbitmq",
+            "perm": "0600"
+        }{% endif %}
+    ],
     "permissions": [
         {
             "path": "/var/log/kolla/ansible.log",
diff --git a/ansible/roles/service-rabbitmq/defaults/main.yml b/ansible/roles/service-rabbitmq/defaults/main.yml
new file mode 100644
index 0000000000..df99fac879
--- /dev/null
+++ b/ansible/roles/service-rabbitmq/defaults/main.yml
@@ -0,0 +1,25 @@
+---
+# Role to ensure RabbitMQ configuration exists for a service.
+
+# Host to delegate task execution to.
+service_rabbitmq_delegate_host: "{{ inventory_hostname }}"
+
+# Whether to run the task on only one host.
+service_rabbitmq_run_once: true
+
+# Condition on which to run the task.
+service_rabbitmq_when: true
+
+# Number of retries for each task.
+service_rabbitmq_retries: 5
+
+# Delay between task retries.
+service_rabbitmq_delay: 10
+
+# List of RabbitMQ users to create. Each item should contain the following
+# fields:
+# 'user'
+# 'password'
+# 'vhost'
+# Virtual hosts in this list will also be created.
+service_rabbitmq_users: []
diff --git a/ansible/roles/service-rabbitmq/tasks/main.yml b/ansible/roles/service-rabbitmq/tasks/main.yml
new file mode 100644
index 0000000000..d429537e4e
--- /dev/null
+++ b/ansible/roles/service-rabbitmq/tasks/main.yml
@@ -0,0 +1,42 @@
+---
+- block:
+    - name: "{{ project_name }} | Ensure RabbitMQ vhosts exist"
+      kolla_toolbox:
+        module_name: rabbitmq_vhost
+        module_args:
+          name: "{{ item }}"
+        user: rabbitmq
+      loop: "{{ service_rabbitmq_users | map(attribute='vhost') | unique | reject('equalto', '/') | list }}"
+      register: service_rabbitmq_result
+      until: service_rabbitmq_result is success
+      retries: "{{ service_rabbitmq_retries }}"
+      delay: "{{ service_rabbitmq_delay }}"
+
+    - name: "{{ project_name }} | Ensure RabbitMQ users exist"
+      kolla_toolbox:
+        module_name: rabbitmq_user
+        module_args:
+          user: "{{ item.user }}"
+          password: "{{ item.password }}"
+          update_password: always
+          vhost: "{{ item.vhost }}"
+          configure_priv: ".*"
+          read_priv: ".*"
+          write_priv: ".*"
+        user: rabbitmq
+      loop: "{{ service_rabbitmq_users }}"
+      loop_control:
+        label:
+          user: "{{ item.user }}"
+          vhost: "{{ item.vhost }}"
+      register: service_rabbitmq_result
+      until: service_rabbitmq_result is success
+      retries: "{{ service_rabbitmq_retries }}"
+      delay: "{{ service_rabbitmq_delay }}"
+
+  become: true
+  when: service_rabbitmq_when | bool
+  delegate_to: "{{ service_rabbitmq_delegate_host }}"
+  run_once: "{{ service_rabbitmq_run_once }}"
+  tags:
+    - service-rabbitmq