diff --git a/ansible/group_vars/all/kolla b/ansible/group_vars/all/kolla index e1fb3e6b7..8279fb80b 100644 --- a/ansible/group_vars/all/kolla +++ b/ansible/group_vars/all/kolla @@ -337,6 +337,10 @@ kolla_ansible_group: kolla # Ansible. kolla_ansible_become: false +# Whether to create a user account, configure passwordless sudo and authorise +# an SSH key for Kolla Ansible. Default is 'true'. +kolla_ansible_create_user: true + ############################################################################### # Kolla feature flag configuration. @@ -402,8 +406,7 @@ kolla_ansible_default_custom_passwords: bifrost_ssh_key: private_key: "{{ lookup('file', ssh_private_key_path) }}" public_key: "{{ lookup('file', ssh_public_key_path) }}" - # SSH key authorized by kolla user on Kolla hosts during - # kolla-ansible bootstrap-servers. + # SSH key authorized by kolla user on Kolla hosts. kolla_ssh_key: private_key: "{{ lookup('file', ssh_private_key_path) }}" public_key: "{{ lookup('file', ssh_public_key_path) }}" diff --git a/ansible/kolla-ansible-user.yml b/ansible/kolla-ansible-user.yml new file mode 100644 index 000000000..e9802d872 --- /dev/null +++ b/ansible/kolla-ansible-user.yml @@ -0,0 +1,47 @@ +--- +- name: Ensure the Kolla Ansible user account exists + hosts: seed:overcloud + gather_facts: false + tags: + - kolla-ansible + - kolla-ansible-user + vars: + # kolla_overcloud_inventory_top_level_group_map looks like: + # kolla_overcloud_inventory_top_level_group_map: + # control: + # groups: + # - controllers + hosts_in_kolla_inventory: >- + {{ kolla_overcloud_inventory_top_level_group_map.values() | + map(attribute='groups') | flatten | unique | union(['seed']) | join(':') }} + tasks: + - block: + - name: Ensure the Kolla Ansible user account exists + include_role: + name: singleplatform-eng.users + apply: + become: True + vars: + groups_to_create: + - name: docker + - name: "{{ kolla_ansible_group }}" + - name: sudo + users: + - username: "{{ kolla_ansible_user }}" + group: "{{ kolla_ansible_group }}" + groups: + - docker + - sudo + append: True + ssh_key: + - "{{ kolla_ansible_custom_passwords.kolla_ssh_key.public_key }}" + + - name: Ensure the Kolla Ansible user has passwordless sudo + copy: + content: "{{ kolla_ansible_user }} ALL=(ALL) NOPASSWD: ALL" + dest: "/etc/sudoers.d/kolla-ansible-users" + mode: 0640 + become: True + when: + - inventory_hostname in query('inventory_hostnames', hosts_in_kolla_inventory) + - kolla_ansible_create_user | bool diff --git a/ansible/kolla-pip.yml b/ansible/kolla-pip.yml new file mode 100644 index 000000000..54c08bdd3 --- /dev/null +++ b/ansible/kolla-pip.yml @@ -0,0 +1,26 @@ +--- +- name: Configure local PyPi mirror for Kolla Ansible + hosts: seed:overcloud + gather_facts: false + tags: + - kolla-ansible + - kolla-pip + - pip + vars: + # kolla_overcloud_inventory_top_level_group_map looks like: + # kolla_overcloud_inventory_top_level_group_map: + # control: + # groups: + # - controllers + hosts_in_kolla_inventory: >- + {{ kolla_overcloud_inventory_top_level_group_map.values() | + map(attribute='groups') | flatten | unique | union(['seed']) | join(':') }} + ansible_python_interpreter: /usr/libexec/platform-python + tasks: + - import_role: + name: pip + vars: + pip_applicable_users: + - "{{ kolla_ansible_user }}" + when: + - inventory_hostname in query('inventory_hostnames', hosts_in_kolla_inventory) diff --git a/ansible/roles/kolla-ansible/templates/globals.yml.j2 b/ansible/roles/kolla-ansible/templates/globals.yml.j2 index 6bc96d479..ad02b68be 100644 --- a/ansible/roles/kolla-ansible/templates/globals.yml.j2 +++ b/ansible/roles/kolla-ansible/templates/globals.yml.j2 @@ -48,12 +48,6 @@ kolla_external_vip_address: "{{ kolla_external_vip_address }}" # kolla_external_vip_address. kolla_external_fqdn: "{{ kolla_external_fqdn }}" -# User account to use for Kolla SSH access. -kolla_user: "{{ kolla_ansible_user }}" - -# Primary group of Kolla SSH user. -kolla_group: "{{ kolla_ansible_group }}" - ################ # Docker options ################ @@ -549,6 +543,10 @@ bifrost_install_type: source grafana_admin_username: "{{ grafana_local_admin_user_name }}" {% endif %} +######################################### +# Bootstrap-servers - Host Configuration +######################################### + {% if kolla_selinux_state is not none %} selinux_state: {{ kolla_selinux_state }} {% endif %} @@ -559,6 +557,20 @@ install_epel: {{ kolla_ansible_install_epel | bool }} enable_host_ntp: {{ kolla_enable_host_ntp | bool }} {% endif %} +# Kayobe performs creation of the Kolla Ansible user account, so there is no +# need for Kolla Ansible to repeat this. +create_kolla_user: false + +# User account to use for Kolla SSH access. +kolla_user: "{{ kolla_ansible_user }}" + +# Primary group of Kolla SSH user. +kolla_group: "{{ kolla_ansible_group }}" + +{% if kolla_ansible_target_venv %} +virtualenv: {{ kolla_ansible_target_venv }} +{% endif %} + {% if kolla_extra_globals %} ####################### # Extra configuration diff --git a/doc/source/configuration/hosts.rst b/doc/source/configuration/hosts.rst index 08ea2158e..b0be9fd36 100644 --- a/doc/source/configuration/hosts.rst +++ b/doc/source/configuration/hosts.rst @@ -720,16 +720,18 @@ Kolla-Ansible bootstrap-servers =============================== Kolla Ansible provides some host configuration functionality via the -``bootstrap-servers`` command, which may be leveraged by Kayobe. Due to the -bootstrapping nature of the command, Kayobe uses ``kayobe_ansible_user`` to -execute it, and uses the Kayobe remote Python virtual environment (or the -system Python interpreter if no virtual environment is in use). +``bootstrap-servers`` command, which may be leveraged by Kayobe. See the :kolla-ansible-doc:`Kolla Ansible documentation ` for more information on the functions performed by this command, and how to configure it. +Note that from the Ussuri release, Kayobe creates a user account for Kolla +Ansible rather than this being done by Kolla Ansible during +``bootstrap-servers``. See :ref:`configuration-kolla-ansible-user-creation` for +details. + Kolla-Ansible Remote Virtual Environment ======================================== *tags:* diff --git a/doc/source/configuration/kolla-ansible.rst b/doc/source/configuration/kolla-ansible.rst index 6e235b211..23e0a3ab9 100644 --- a/doc/source/configuration/kolla-ansible.rst +++ b/doc/source/configuration/kolla-ansible.rst @@ -174,6 +174,23 @@ The variable ``kolla_ansible_target_venv`` configures the use of a virtual environment on the remote hosts. The default configuration should work in most cases. +.. _configuration-kolla-ansible-user-creation: + +User account creation +--------------------- + +Since the Ussuri release, Kayobe creates a user account for Kolla Ansible +rather than this being done during Kolla Ansible's ``bootstrap-servers`` +command. This workflow is more compatible with `Ansible fact caching +`__, +but does mean that Kolla Ansible's ``create_kolla_user`` variable cannot be +used to disable creation of the user account. Instead, set +``kolla_ansible_create_user`` to ``false``. + +``kolla_ansible_create_user`` + Whether to create a user account, configure passwordless sudo and authorise + an SSH key for Kolla Ansible. Default is ``true``. + OpenStack Logging ----------------- diff --git a/etc/kayobe/kolla.yml b/etc/kayobe/kolla.yml index f5eb9a999..56327aa51 100644 --- a/etc/kayobe/kolla.yml +++ b/etc/kayobe/kolla.yml @@ -172,6 +172,10 @@ # Ansible. Default is 'false'. #kolla_ansible_become: +# Whether to create a user account, configure passwordless sudo and authorise +# an SSH key for Kolla Ansible. Default is 'true'. +#kolla_ansible_create_user: + ############################################################################### # Kolla feature flag configuration. diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 751234a7a..42e35d7ad 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -516,23 +516,6 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, def take_action(self, parsed_args): self.app.LOG.debug("Configuring seed host OS") - # Query some kayobe ansible variables. - # Explicitly request the dump-config tag to ensure this play runs even - # if the user specified tags. - hostvars = self.run_kayobe_config_dump(parsed_args, hosts="seed", - tags="dump-config") - if not hostvars: - self.app.LOG.error("No hosts in the seed group") - sys.exit(1) - hostvars = list(hostvars.values())[0] - ansible_user = hostvars.get("kayobe_ansible_user") - if not ansible_user: - self.app.LOG.error("Could not determine kayobe_ansible_user " - "variable for seed host") - sys.exit(1) - python_interpreter = hostvars.get("ansible_python_interpreter") - kolla_target_venv = hostvars.get("kolla_ansible_target_venv") - # Allocate IP addresses. playbooks = _build_playbook_list("ip-allocation") self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed") @@ -546,38 +529,19 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, playbooks += _build_playbook_list( "users", "yum", "dnf", "dev-tools", "disable-selinux", "network", "sysctl", "ip-routing", "snat", "disable-glean", "ntp", "mdadm", - "lvm", "docker-devicemapper") + "lvm", "docker-devicemapper", "kolla-ansible-user", "kolla-pip", + "kolla-target-venv") self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed") self.generate_kolla_ansible_config(parsed_args, service_config=False) # Run kolla-ansible bootstrap-servers. - # This command should be run as the kayobe ansible user because at this - # point the kolla user may not exist. - extra_vars = {"ansible_user": ansible_user} - if python_interpreter: - # Use the kayobe virtualenv, as this is the executing user. - extra_vars["ansible_python_interpreter"] = python_interpreter - elif kolla_target_venv: - # Override the kolla-ansible virtualenv, use the system python - # instead. - extra_vars["ansible_python_interpreter"] = "/usr/bin/python" - if kolla_target_venv: - # Specify a virtualenv in which to install python packages. - extra_vars["virtualenv"] = kolla_target_venv - self.run_kolla_ansible_seed(parsed_args, "bootstrap-servers", - extra_vars=extra_vars) - - # Re-run the Pip role after we've bootstrapped the Kolla user - extra_vars = {} - kolla_ansible_user = hostvars.get("kolla_ansible_user") - extra_vars["pip_applicable_users"] = [kolla_ansible_user] + self.run_kolla_ansible_seed(parsed_args, "bootstrap-servers") # Run final kayobe playbooks. playbooks = _build_playbook_list( - "pip", "kolla-target-venv", "kolla-host", "docker") - self.run_kayobe_playbooks(parsed_args, playbooks, - extra_vars=extra_vars, limit="seed") + "kolla-host", "docker") + self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed") # Optionally, deploy a Docker Registry. playbooks = _build_playbook_list("docker-registry") @@ -916,23 +880,6 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, def take_action(self, parsed_args): self.app.LOG.debug("Configuring overcloud host OS") - # Query some kayobe ansible variables. - # Explicitly request the dump-config tag to ensure this play runs even - # if the user specified tags. - hostvars = self.run_kayobe_config_dump(parsed_args, hosts="overcloud", - tags="dump-config") - if not hostvars: - self.app.LOG.error("No hosts in the overcloud group") - sys.exit(1) - hostvars = list(hostvars.values())[0] - ansible_user = hostvars.get("kayobe_ansible_user") - if not ansible_user: - self.app.LOG.error("Could not determine kayobe_ansible_user " - "variable for overcloud hosts") - sys.exit(1) - python_interpreter = hostvars.get("ansible_python_interpreter") - kolla_target_venv = hostvars.get("kolla_ansible_target_venv") - # Allocate IP addresses. playbooks = _build_playbook_list("ip-allocation") self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud") @@ -946,40 +893,19 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, playbooks += _build_playbook_list( "users", "yum", "dnf", "dev-tools", "disable-selinux", "network", "sysctl", "disable-glean", "disable-cloud-init", "ntp", "mdadm", - "lvm", "docker-devicemapper") + "lvm", "docker-devicemapper", "kolla-ansible-user", "kolla-pip", + "kolla-target-venv") self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud") self.generate_kolla_ansible_config(parsed_args, service_config=False) # Kolla-ansible bootstrap-servers. - # The kolla-ansible bootstrap-servers command should be run as the - # kayobe ansible user because at this point the kolla user may not - # exist. - extra_vars = {"ansible_user": ansible_user} - if python_interpreter: - # Use the kayobe virtualenv, as this is the executing user. - extra_vars["ansible_python_interpreter"] = python_interpreter - elif kolla_target_venv: - # Override the kolla-ansible virtualenv, use the system python - # instead. - extra_vars["ansible_python_interpreter"] = "/usr/bin/python" - if kolla_target_venv: - # Specify a virtualenv in which to install python packages. - extra_vars["virtualenv"] = kolla_target_venv - self.run_kolla_ansible_overcloud(parsed_args, "bootstrap-servers", - extra_vars=extra_vars) - - # Re-run the Pip role after we've bootstrapped the Kolla user - extra_vars = {} - kolla_ansible_user = hostvars.get("kolla_ansible_user") - extra_vars["pip_applicable_users"] = [kolla_ansible_user] + self.run_kolla_ansible_overcloud(parsed_args, "bootstrap-servers") # Further kayobe playbooks. playbooks = _build_playbook_list( - "pip", "kolla-target-venv", "kolla-host", - "docker", "swift-block-devices") - self.run_kayobe_playbooks(parsed_args, playbooks, - extra_vars=extra_vars, limit="overcloud") + "kolla-host", "docker", "swift-block-devices") + self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud") class OvercloudHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command): diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py index 1242b17c9..93fce7853 100644 --- a/kayobe/tests/unit/cli/test_commands.py +++ b/kayobe/tests/unit/cli/test_commands.py @@ -461,28 +461,18 @@ class TestCase(unittest.TestCase): ] self.assertEqual(expected_calls, mock_run.call_args_list) - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") @mock.patch.object(commands.KollaAnsibleMixin, "run_kolla_ansible_seed") - def test_seed_host_configure(self, mock_kolla_run, mock_run, mock_dump): + def test_seed_host_configure(self, mock_kolla_run, mock_run): command = commands.SeedHostConfigure(TestApp(), []) parser = command.get_parser("test") parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "seed": {"kayobe_ansible_user": "stack"} - } result = command.run(parsed_args) self.assertEqual(0, result) - expected_calls = [ - mock.call(mock.ANY, hosts="seed", tags="dump-config") - ] - self.assertEqual(expected_calls, mock_dump.call_args_list) - expected_calls = [ mock.call( mock.ANY, @@ -514,6 +504,11 @@ class TestCase(unittest.TestCase): utils.get_data_files_path("ansible", "lvm.yml"), utils.get_data_files_path("ansible", "docker-devicemapper.yml"), + utils.get_data_files_path( + "ansible", "kolla-ansible-user.yml"), + utils.get_data_files_path("ansible", "kolla-pip.yml"), + utils.get_data_files_path( + "ansible", "kolla-target-venv.yml"), ], limit="seed", ), @@ -526,14 +521,10 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [ - utils.get_data_files_path("ansible", "pip.yml"), - utils.get_data_files_path( - "ansible", "kolla-target-venv.yml"), utils.get_data_files_path("ansible", "kolla-host.yml"), utils.get_data_files_path("ansible", "docker.yml"), ], limit="seed", - extra_vars={'pip_applicable_users': [None]}, ), mock.call( mock.ANY, @@ -551,109 +542,6 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, "bootstrap-servers", - extra_vars={"ansible_user": "stack"}, - ), - ] - self.assertEqual(expected_calls, mock_kolla_run.call_args_list) - - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbooks") - @mock.patch.object(commands.KollaAnsibleMixin, - "run_kolla_ansible_seed") - def test_seed_host_configure_kayobe_venv(self, mock_kolla_run, mock_run, - mock_dump): - command = commands.SeedHostConfigure(TestApp(), []) - parser = command.get_parser("test") - parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "seed": { - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "kayobe_ansible_user": "stack", - } - } - - result = command.run(parsed_args) - self.assertEqual(0, result) - - expected_calls = [ - mock.call( - mock.ANY, - "bootstrap-servers", - extra_vars={ - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "ansible_user": "stack", - }, - ), - ] - self.assertEqual(expected_calls, mock_kolla_run.call_args_list) - - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbooks") - @mock.patch.object(commands.KollaAnsibleMixin, - "run_kolla_ansible_seed") - def test_seed_host_configure_kolla_venv(self, mock_kolla_run, mock_run, - mock_dump): - command = commands.SeedHostConfigure(TestApp(), []) - parser = command.get_parser("test") - parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "seed": { - "kayobe_ansible_user": "stack", - "kolla_ansible_target_venv": "/kolla/venv/bin/python", - } - } - - result = command.run(parsed_args) - self.assertEqual(0, result) - - expected_calls = [ - mock.call( - mock.ANY, - "bootstrap-servers", - extra_vars={ - "ansible_python_interpreter": "/usr/bin/python", - "ansible_user": "stack", - "virtualenv": "/kolla/venv/bin/python", - }, - ), - ] - self.assertEqual(expected_calls, mock_kolla_run.call_args_list) - - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbooks") - @mock.patch.object(commands.KollaAnsibleMixin, - "run_kolla_ansible_seed") - def test_seed_host_configure_both_venvs(self, mock_kolla_run, mock_run, - mock_dump): - command = commands.SeedHostConfigure(TestApp(), []) - parser = command.get_parser("test") - parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "seed": { - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "kayobe_ansible_user": "stack", - "kolla_ansible_target_venv": "/kolla/venv/bin/python", - } - } - - result = command.run(parsed_args) - self.assertEqual(0, result) - - expected_calls = [ - mock.call( - mock.ANY, - "bootstrap-servers", - extra_vars={ - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "ansible_user": "stack", - "virtualenv": "/kolla/venv/bin/python", - }, ), ] self.assertEqual(expected_calls, mock_kolla_run.call_args_list) @@ -1088,29 +976,18 @@ class TestCase(unittest.TestCase): ] self.assertEqual(expected_calls, mock_run.call_args_list) - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") @mock.patch.object(commands.KollaAnsibleMixin, "run_kolla_ansible_overcloud") - def test_overcloud_host_configure(self, mock_kolla_run, mock_run, - mock_dump): + def test_overcloud_host_configure(self, mock_kolla_run, mock_run): command = commands.OvercloudHostConfigure(TestApp(), []) parser = command.get_parser("test") parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "controller0": {"kayobe_ansible_user": "stack"} - } result = command.run(parsed_args) self.assertEqual(0, result) - expected_calls = [ - mock.call(mock.ANY, hosts="overcloud", tags="dump-config") - ] - self.assertEqual(expected_calls, mock_dump.call_args_list) - expected_calls = [ mock.call( mock.ANY, @@ -1142,6 +1019,11 @@ class TestCase(unittest.TestCase): utils.get_data_files_path("ansible", "lvm.yml"), utils.get_data_files_path("ansible", "docker-devicemapper.yml"), + utils.get_data_files_path( + "ansible", "kolla-ansible-user.yml"), + utils.get_data_files_path("ansible", "kolla-pip.yml"), + utils.get_data_files_path( + "ansible", "kolla-target-venv.yml"), ], limit="overcloud", ), @@ -1154,16 +1036,12 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [ - utils.get_data_files_path("ansible", "pip.yml"), - utils.get_data_files_path( - "ansible", "kolla-target-venv.yml"), utils.get_data_files_path("ansible", "kolla-host.yml"), utils.get_data_files_path("ansible", "docker.yml"), utils.get_data_files_path( "ansible", "swift-block-devices.yml"), ], limit="overcloud", - extra_vars={"pip_applicable_users": [None]}, ), ] self.assertEqual(expected_calls, mock_run.call_args_list) @@ -1172,109 +1050,6 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, "bootstrap-servers", - extra_vars={"ansible_user": "stack"}, - ), - ] - self.assertEqual(expected_calls, mock_kolla_run.call_args_list) - - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbooks") - @mock.patch.object(commands.KollaAnsibleMixin, - "run_kolla_ansible_overcloud") - def test_overcloud_host_configure_kayobe_venv(self, mock_kolla_run, - mock_run, mock_dump): - command = commands.OvercloudHostConfigure(TestApp(), []) - parser = command.get_parser("test") - parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "controller0": { - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "kayobe_ansible_user": "stack", - } - } - - result = command.run(parsed_args) - self.assertEqual(0, result) - - expected_calls = [ - mock.call( - mock.ANY, - "bootstrap-servers", - extra_vars={ - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "ansible_user": "stack", - } - ), - ] - self.assertEqual(expected_calls, mock_kolla_run.call_args_list) - - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbooks") - @mock.patch.object(commands.KollaAnsibleMixin, - "run_kolla_ansible_overcloud") - def test_overcloud_host_configure_kolla_venv(self, mock_kolla_run, - mock_run, mock_dump): - command = commands.OvercloudHostConfigure(TestApp(), []) - parser = command.get_parser("test") - parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "controller0": { - "kayobe_ansible_user": "stack", - "kolla_ansible_target_venv": "/kolla/venv/bin/python", - } - } - - result = command.run(parsed_args) - self.assertEqual(0, result) - - expected_calls = [ - mock.call( - mock.ANY, - "bootstrap-servers", - extra_vars={ - "ansible_python_interpreter": "/usr/bin/python", - "ansible_user": "stack", - "virtualenv": "/kolla/venv/bin/python", - } - ), - ] - self.assertEqual(expected_calls, mock_kolla_run.call_args_list) - - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_config_dump") - @mock.patch.object(commands.KayobeAnsibleMixin, - "run_kayobe_playbooks") - @mock.patch.object(commands.KollaAnsibleMixin, - "run_kolla_ansible_overcloud") - def test_overcloud_host_configure_both_venvs(self, mock_kolla_run, - mock_run, mock_dump): - command = commands.OvercloudHostConfigure(TestApp(), []) - parser = command.get_parser("test") - parsed_args = parser.parse_args([]) - mock_dump.return_value = { - "controller0": { - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "kayobe_ansible_user": "stack", - "kolla_ansible_target_venv": "/kolla/venv/bin/python", - } - } - - result = command.run(parsed_args) - self.assertEqual(0, result) - - expected_calls = [ - mock.call( - mock.ANY, - "bootstrap-servers", - extra_vars={ - "ansible_python_interpreter": "/kayobe/venv/bin/python", - "ansible_user": "stack", - "virtualenv": "/kolla/venv/bin/python", - } ), ] self.assertEqual(expected_calls, mock_kolla_run.call_args_list) diff --git a/releasenotes/notes/bootstrap-servers-user-8cb5114de1dd10ec.yaml b/releasenotes/notes/bootstrap-servers-user-8cb5114de1dd10ec.yaml new file mode 100644 index 000000000..db32c9a75 --- /dev/null +++ b/releasenotes/notes/bootstrap-servers-user-8cb5114de1dd10ec.yaml @@ -0,0 +1,20 @@ +--- +upgrade: + - | + The ``kolla-ansible bootstrap-servers`` command is used by Kayobe during + the ``kayobe seed host configure`` and ``kayobe overcloud host configure`` + tasks. In previous releases it was executed as the Kayobe Ansible user + (``kayobe_ansible_user``) and using the remote Kayobe Python interpreter + (``ansible_python_interpreter``) since it was responsible for creation of + the Kolla Ansible user account (``kolla_ansible_user``) and Python virtual + environment (``kolla_ansible_target_venv``). This mix of environments + causes problems for Ansible fact caching. To avoid this issue, Kayobe is + now responsible for creation of the Kolla Ansible user and Python virtual + environment, and ``kolla-ansible bootstrap-servers`` is run using the + normal Kolla Ansible user and remote Python interpreter. + + Previously it was possible to avoid creation of the user account during + ``kolla-ansible bootstrap-servers`` by setting ``create_kolla_user`` to + ``false`` in ``${KAYOBE_CONFIG_PATH}/kolla/globals.yml``. The same may now + be achieved by setting ``kolla_ansible_create_user`` to ``false`` in + ``${KAYOBE_CONFIG_PATH}/kolla.yml``.