From 790bf336d5e082c5c079bfb681f9509188eae72f Mon Sep 17 00:00:00 2001
From: Hui Kang <kangh@us.ibm.com>
Date: Sat, 7 Nov 2015 15:11:40 -0500
Subject: [PATCH] Fix bootstrap for services

The bootstrap tasks could be started on any node listed in the
site.yml

The issue is that all the tasks must run on the same node, and the
only node that all the tasks can run on is the 'api' node due to
needing to start the bootstrap container which binds in the configs.

delegate_to is required to ensure that the proper node gets the task.

Co-Authored-By: Sam Yaple <sam@yaple.net>
Change-Id: Ica04ab366777a571a92212ac22c482f1881d4ecd
Closes-Bug: #1513598
Related-Bug: #1513439
---
 ansible/roles/cinder/tasks/bootstrap.yml   | 13 +++++++------
 ansible/roles/cinder/tasks/main.yml        | 10 ++--------
 ansible/roles/glance/tasks/bootstrap.yml   | 13 +++++++------
 ansible/roles/glance/tasks/main.yml        |  6 ++----
 ansible/roles/heat/tasks/bootstrap.yml     | 13 +++++++------
 ansible/roles/heat/tasks/main.yml          |  8 ++------
 ansible/roles/ironic/tasks/bootstrap.yml   | 13 +++++++------
 ansible/roles/ironic/tasks/main.yml        | 10 ++--------
 ansible/roles/keystone/tasks/bootstrap.yml |  5 +++++
 ansible/roles/keystone/tasks/main.yml      |  3 +++
 ansible/roles/magnum/tasks/bootstrap.yml   |  5 +++++
 ansible/roles/magnum/tasks/main.yml        |  6 ++++++
 ansible/roles/murano/tasks/bootstrap.yml   | 13 +++++++------
 ansible/roles/murano/tasks/main.yml        |  6 ++----
 ansible/roles/neutron/tasks/bootstrap.yml  | 13 +++++++------
 ansible/roles/neutron/tasks/main.yml       |  8 ++------
 ansible/roles/nova/tasks/bootstrap.yml     | 13 +++++++------
 ansible/roles/nova/tasks/main.yml          | 14 ++------------
 18 files changed, 82 insertions(+), 90 deletions(-)

diff --git a/ansible/roles/cinder/tasks/bootstrap.yml b/ansible/roles/cinder/tasks/bootstrap.yml
index 1c0790048..b3ef61139 100644
--- a/ansible/roles/cinder/tasks/bootstrap.yml
+++ b/ansible/roles/cinder/tasks/bootstrap.yml
@@ -10,6 +10,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['cinder-api'][0] }}"
 
 - name: Creating Cinder database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -26,6 +27,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['cinder-api'][0] }}"
 
 - name: Starting Cinder bootstrap container
   docker:
@@ -46,9 +48,8 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['cinder-api']
+  delegate_to: "{{ groups['cinder-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for bootstrap container to exit
@@ -56,9 +57,8 @@
   failed_when: bootstrap_result.stdout != "0"
   register: bootstrap_result
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['cinder-api']
+  delegate_to: "{{ groups['cinder-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Cinder bootstrap container
   docker:
@@ -66,4 +66,5 @@
     name: bootstrap_cinder
     image: "{{ cinder_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['cinder-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/cinder/tasks/main.yml b/ansible/roles/cinder/tasks/main.yml
index 184b97a27..06909bd22 100644
--- a/ansible/roles/cinder/tasks/main.yml
+++ b/ansible/roles/cinder/tasks/main.yml
@@ -9,10 +9,7 @@
         inventory_hostname in groups['cinder-backup']
 
 - include: register.yml
-  when: inventory_hostname in groups['cinder-api'] or
-        inventory_hostname in groups['cinder-volume'] or
-        inventory_hostname in groups['cinder-scheduler'] or
-        inventory_hostname in groups['cinder-backup']
+  when: inventory_hostname in groups['cinder-api']
 
 - include: config.yml
   when: inventory_hostname in groups['cinder-api'] or
@@ -21,10 +18,7 @@
         inventory_hostname in groups['cinder-backup']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['cinder-api'] or
-        inventory_hostname in groups['cinder-volume'] or
-        inventory_hostname in groups['cinder-scheduler'] or
-        inventory_hostname in groups['cinder-backup']
+  when: inventory_hostname in groups['cinder-api']
 
 - include: start.yml
   when: inventory_hostname in groups['cinder-api'] or
diff --git a/ansible/roles/glance/tasks/bootstrap.yml b/ansible/roles/glance/tasks/bootstrap.yml
index 663e93f6f..f080d13ef 100644
--- a/ansible/roles/glance/tasks/bootstrap.yml
+++ b/ansible/roles/glance/tasks/bootstrap.yml
@@ -11,6 +11,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['glance-api'][0] }}"
 
 - name: Creating Glance database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -27,6 +28,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['glance-api'][0] }}"
 
 - name: Starting Glance bootstrap container
   docker:
@@ -47,19 +49,17 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['glance-api']
+  delegate_to: "{{ groups['glance-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for bootstrap container to exit
   command: docker wait bootstrap_glance
   register: bootstrap_result
   run_once: True
+  delegate_to: "{{ groups['glance-api'][0] }}"
   failed_when: bootstrap_result.stdout != "0"
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['glance-api']
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Glance bootstrap container
   docker:
@@ -67,4 +67,5 @@
     name: bootstrap_glance
     image: "{{ glance_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['glance-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/glance/tasks/main.yml b/ansible/roles/glance/tasks/main.yml
index 3370da4c1..f3b739a0f 100644
--- a/ansible/roles/glance/tasks/main.yml
+++ b/ansible/roles/glance/tasks/main.yml
@@ -7,16 +7,14 @@
         inventory_hostname in groups['glance-registry']
 
 - include: register.yml
-  when: inventory_hostname in groups['glance-api'] or
-        inventory_hostname in groups['glance-registry']
+  when: inventory_hostname in groups['glance-api']
 
 - include: config.yml
   when: inventory_hostname in groups['glance-api'] or
         inventory_hostname in groups['glance-registry']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['glance-api'] or
-        inventory_hostname in groups['glance-registry']
+  when: inventory_hostname in groups['glance-api']
 
 - include: start.yml
   when: inventory_hostname in groups['glance-api'] or
diff --git a/ansible/roles/heat/tasks/bootstrap.yml b/ansible/roles/heat/tasks/bootstrap.yml
index 7a00dd931..b14ce94db 100644
--- a/ansible/roles/heat/tasks/bootstrap.yml
+++ b/ansible/roles/heat/tasks/bootstrap.yml
@@ -10,6 +10,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['heat-api'][0] }}"
 
 - name: Creating Heat database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -26,6 +27,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['heat-api'][0] }}"
 
 - name: Starting Heat bootstrap container
   docker:
@@ -52,9 +54,8 @@
       OS_PROJECT_NAME: "{{ openstack_auth.project_name }}"
       HEAT_DOMAIN_ADMIN_PASSWORD: "{{ heat_domain_admin_password }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['heat-api']
+  delegate_to: "{{ groups['heat-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for bootstrap container to exit
@@ -62,9 +63,8 @@
   register: bootstrap_result
   run_once: True
   failed_when: bootstrap_result.stdout != "0"
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['heat-api']
+  delegate_to: "{{ groups['heat-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Heat boostrap container
   docker:
@@ -72,4 +72,5 @@
     name: bootstrap_heat
     image: "{{ heat_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['heat-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/heat/tasks/main.yml b/ansible/roles/heat/tasks/main.yml
index 52e4eef7e..a27fbf2cc 100644
--- a/ansible/roles/heat/tasks/main.yml
+++ b/ansible/roles/heat/tasks/main.yml
@@ -1,8 +1,6 @@
 ---
 - include: register.yml
-  when: inventory_hostname in groups['heat-api'] or
-        inventory_hostname in groups['heat-api-cfn'] or
-        inventory_hostname in groups['heat-engine']
+  when: inventory_hostname in groups['heat-api']
 
 - include: config.yml
   when: inventory_hostname in groups['heat-api'] or
@@ -10,9 +8,7 @@
         inventory_hostname in groups['heat-engine']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['heat-api'] or
-        inventory_hostname in groups['heat-api-cfn'] or
-        inventory_hostname in groups['heat-engine']
+  when: inventory_hostname in groups['heat-api']
 
 - include: start.yml
   when: inventory_hostname in groups['heat-api'] or
diff --git a/ansible/roles/ironic/tasks/bootstrap.yml b/ansible/roles/ironic/tasks/bootstrap.yml
index 1e63a1a37..afac4facb 100644
--- a/ansible/roles/ironic/tasks/bootstrap.yml
+++ b/ansible/roles/ironic/tasks/bootstrap.yml
@@ -11,6 +11,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['ironic-api'][0] }}"
 
 - name: Creating Ironic database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -28,6 +29,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['ironic-api'][0] }}"
 
 - name: Starting Ironic bootstrap container
   docker:
@@ -48,17 +50,15 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['ironic-api']
+  delegate_to: "{{ groups['ironic-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for Ironic bootstrap container to exit
   command: docker wait bootstrap_ironic
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['ironic-api']
+  delegate_to: "{{ groups['ironic-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up boostrap container
   docker:
@@ -66,4 +66,5 @@
     name: bootstrap_ironic
     image: "{{ ironic_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['ironic-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/ironic/tasks/main.yml b/ansible/roles/ironic/tasks/main.yml
index 4bc964125..e32778aee 100644
--- a/ansible/roles/ironic/tasks/main.yml
+++ b/ansible/roles/ironic/tasks/main.yml
@@ -1,9 +1,6 @@
 ---
 - include: register.yml
-  when: inventory_hostname in groups['ironic-api'] or
-        inventory_hostname in groups['ironic-conductor'] or
-        inventory_hostname in groups['ironic-discoverd'] or
-        inventory_hostname in groups['ironic-pxe']
+  when: inventory_hostname in groups['ironic-api']
 
 - include: config.yml
   when: inventory_hostname in groups['ironic-api'] or
@@ -12,10 +9,7 @@
         inventory_hostname in groups['ironic-pxe']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['ironic-api'] or
-        inventory_hostname in groups['ironic-conductor'] or
-        inventory_hostname in groups['ironic-discoverd'] or
-        inventory_hostname in groups['ironic-pxe']
+  when: inventory_hostname in groups['ironic-api']
 
 - include: start.yml
   when: inventory_hostname in groups['ironic-api'] or
diff --git a/ansible/roles/keystone/tasks/bootstrap.yml b/ansible/roles/keystone/tasks/bootstrap.yml
index 8056796ab..c42f4120c 100644
--- a/ansible/roles/keystone/tasks/bootstrap.yml
+++ b/ansible/roles/keystone/tasks/bootstrap.yml
@@ -11,6 +11,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['keystone'][0] }}"
 
 - name: Creating Keystone database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -28,6 +29,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['keystone'][0] }}"
 
 - name: Starting Keystone bootstrap container
   docker:
@@ -55,6 +57,7 @@
       OS_TOKEN: "{{ keystone_admin_token }}"
       OS_URL: "http://{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}:{{ keystone_admin_port }}/v2.0"
   run_once: True
+  delegate_to: "{{ groups['keystone'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
@@ -63,6 +66,7 @@
   register: bootstrap_result
   run_once: True
   failed_when: bootstrap_result.stdout != "0"
+  delegate_to: "{{ groups['keystone'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Keystone bootstrap container
@@ -71,4 +75,5 @@
     name: bootstrap_keystone
     image: "{{ keystone_image_full }}"
     state: absent
+  delegate_to: "{{ groups['keystone'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/keystone/tasks/main.yml b/ansible/roles/keystone/tasks/main.yml
index 98daa4021..f00b4f0e6 100644
--- a/ansible/roles/keystone/tasks/main.yml
+++ b/ansible/roles/keystone/tasks/main.yml
@@ -1,6 +1,9 @@
 ---
 - include: config.yml
+  when: inventory_hostname in groups['keystone']
 
 - include: bootstrap.yml
+  when: inventory_hostname in groups['keystone']
 
 - include: start.yml
+  when: inventory_hostname in groups['keystone']
diff --git a/ansible/roles/magnum/tasks/bootstrap.yml b/ansible/roles/magnum/tasks/bootstrap.yml
index bd6e526ad..facda5d1f 100644
--- a/ansible/roles/magnum/tasks/bootstrap.yml
+++ b/ansible/roles/magnum/tasks/bootstrap.yml
@@ -10,6 +10,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['magnum-api'][0] }}"
 
 - name: Creating Magnum database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -26,6 +27,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['magnum-api'][0] }}"
 
 - name: Starting Magnum bootstrap container
   docker:
@@ -46,6 +48,7 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
+  delegate_to: "{{ groups['magnum-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
@@ -54,6 +57,7 @@
   register: bootstrap_result
   run_once: True
   failed_when: bootstrap_result.stdout != "0"
+  delegate_to: "{{ groups['magnum-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Magnum boostrap container
@@ -62,4 +66,5 @@
     name: bootstrap_magnum
     image: "{{ magnum_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['magnum-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/magnum/tasks/main.yml b/ansible/roles/magnum/tasks/main.yml
index 5c48120b7..50e56814a 100644
--- a/ansible/roles/magnum/tasks/main.yml
+++ b/ansible/roles/magnum/tasks/main.yml
@@ -1,8 +1,14 @@
 ---
 - include: register.yml
+  when: inventory_hostname in groups['magnum-api']
 
 - include: config.yml
+  when: inventory_hostname in groups['magnum-api'] or
+        inventory_hostname in groups['magnum-conductor']
 
 - include: bootstrap.yml
+  when: inventory_hostname in groups['magnum-api']
 
 - include: start.yml
+  when: inventory_hostname in groups['magnum-api'] or
+        inventory_hostname in groups['magnum-conductor']
diff --git a/ansible/roles/murano/tasks/bootstrap.yml b/ansible/roles/murano/tasks/bootstrap.yml
index a6c08baa8..25d6e52ea 100644
--- a/ansible/roles/murano/tasks/bootstrap.yml
+++ b/ansible/roles/murano/tasks/bootstrap.yml
@@ -11,6 +11,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['murano-api'][0] }}"
 
 - name: Creating Murano database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -27,6 +28,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['murano-api'][0] }}"
 
 - name: Starting Murano bootstrap container
   docker:
@@ -47,17 +49,15 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['murano-api']
+  delegate_to: "{{ groups['murano-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for bootstrap container to exit
   command: docker wait bootstrap_murano
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['murano-api']
+  delegate_to: "{{ groups['murano-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Murano boostrap container
   docker:
@@ -65,4 +65,5 @@
     name: bootstrap_murano
     image: "{{ murano_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['murano-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/murano/tasks/main.yml b/ansible/roles/murano/tasks/main.yml
index a76d0866d..13d644732 100644
--- a/ansible/roles/murano/tasks/main.yml
+++ b/ansible/roles/murano/tasks/main.yml
@@ -1,15 +1,13 @@
 ---
 - include: register.yml
-  when: inventory_hostname in groups['murano-api'] or
-        inventory_hostname in groups['murano-engine']
+  when: inventory_hostname in groups['murano-api']
 
 - include: config.yml
   when: inventory_hostname in groups['murano-api'] or
         inventory_hostname in groups['murano-engine']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['murano-api'] or
-        inventory_hostname in groups['murano-engine']
+  when: inventory_hostname in groups['murano-api']
 
 - include: start.yml
   when: inventory_hostname in groups['murano-api'] or
diff --git a/ansible/roles/neutron/tasks/bootstrap.yml b/ansible/roles/neutron/tasks/bootstrap.yml
index ebb6cab5d..b11abe5f9 100644
--- a/ansible/roles/neutron/tasks/bootstrap.yml
+++ b/ansible/roles/neutron/tasks/bootstrap.yml
@@ -10,6 +10,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['neutron-server'][0] }}"
 
 - name: Creating Neutron database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -26,6 +27,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['neutron-server'][0] }}"
 
 - name: Starting Neutron bootstrap container
   docker:
@@ -46,9 +48,8 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['neutron-server']
+  delegate_to: "{{ groups['neutron-server'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for bootstrap container to exit
@@ -56,9 +57,8 @@
   register: bootstrap_result
   run_once: True
   failed_when: bootstrap_result.stdout != "0"
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['neutron-server']
+  delegate_to: "{{ groups['neutron-server'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Neutron bootstrap container
   docker:
@@ -66,4 +66,5 @@
     name: bootstrap_neutron
     image: "{{ neutron_server_image_full }}"
     state: absent
+  delegate_to: "{{ groups['neutron-server'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/neutron/tasks/main.yml b/ansible/roles/neutron/tasks/main.yml
index f8eff9ba9..82132ce49 100644
--- a/ansible/roles/neutron/tasks/main.yml
+++ b/ansible/roles/neutron/tasks/main.yml
@@ -3,9 +3,7 @@
 - include: ironic-check.yml
 
 - include: register.yml
-  when: inventory_hostname in groups['compute'] or
-        inventory_hostname in groups['neutron-agents'] or
-        inventory_hostname in groups['neutron-server']
+  when: inventory_hostname in groups['neutron-server']
 
 - include: config.yml
   when: inventory_hostname in groups['compute'] or
@@ -13,9 +11,7 @@
         inventory_hostname in groups['neutron-server']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['compute'] or
-        inventory_hostname in groups['neutron-agents'] or
-        inventory_hostname in groups['neutron-server']
+  when: inventory_hostname in groups['neutron-server']
 
 - include: start.yml
   when: inventory_hostname in groups['compute'] or
diff --git a/ansible/roles/nova/tasks/bootstrap.yml b/ansible/roles/nova/tasks/bootstrap.yml
index b96f04584..30a17dfef 100644
--- a/ansible/roles/nova/tasks/bootstrap.yml
+++ b/ansible/roles/nova/tasks/bootstrap.yml
@@ -10,6 +10,7 @@
   changed_when: "{{ database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['nova-api'][0] }}"
 
 - name: Creating Nova database user and setting permissions
   command: docker exec -t kolla_ansible /usr/bin/ansible localhost
@@ -26,6 +27,7 @@
   changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
   failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
   run_once: True
+  delegate_to: "{{ groups['nova-api'][0] }}"
 
 - name: Starting Nova bootstrap container
   docker:
@@ -46,9 +48,8 @@
       KOLLA_BOOTSTRAP:
       KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
   run_once: True
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['nova-api']
+  delegate_to: "{{ groups['nova-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 # https://github.com/ansible/ansible-modules-core/pull/1031
 - name: Waiting for bootstrap container to exit
@@ -56,9 +57,8 @@
   register: bootstrap_result
   run_once: True
   failed_when: bootstrap_result.stdout != "0"
-  when:
-    - database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
-    - inventory_hostname in groups['nova-api']
+  delegate_to: "{{ groups['nova-api'][0] }}"
+  when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
 
 - name: Cleaning up Nova bootstrap container
   docker:
@@ -66,4 +66,5 @@
     name: bootstrap_nova
     image: "{{ nova_api_image_full }}"
     state: absent
+  delegate_to: "{{ groups['nova-api'][0] }}"
   when: database.stdout.find('localhost | SUCCESS => ') != -1 and (database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed
diff --git a/ansible/roles/nova/tasks/main.yml b/ansible/roles/nova/tasks/main.yml
index 869235f35..748a19f84 100644
--- a/ansible/roles/nova/tasks/main.yml
+++ b/ansible/roles/nova/tasks/main.yml
@@ -11,12 +11,7 @@
         inventory_hostname in groups['nova-scheduler']
 
 - include: register.yml
-  when: inventory_hostname in groups['compute'] or
-        inventory_hostname in groups['nova-api'] or
-        inventory_hostname in groups['nova-conductor'] or
-        inventory_hostname in groups['nova-consoleauth'] or
-        inventory_hostname in groups['nova-novncproxy'] or
-        inventory_hostname in groups['nova-scheduler']
+  when: inventory_hostname in groups['nova-api']
 
 - include: config.yml
   when: inventory_hostname in groups['compute'] or
@@ -27,12 +22,7 @@
         inventory_hostname in groups['nova-scheduler']
 
 - include: bootstrap.yml
-  when: inventory_hostname in groups['compute'] or
-        inventory_hostname in groups['nova-api'] or
-        inventory_hostname in groups['nova-conductor'] or
-        inventory_hostname in groups['nova-consoleauth'] or
-        inventory_hostname in groups['nova-novncproxy'] or
-        inventory_hostname in groups['nova-scheduler']
+  when: inventory_hostname in groups['nova-api']
 
 - include: start.yml
   when: inventory_hostname in groups['compute'] or
-- 
GitLab