From cb48f7e5d26618029f36a543b60922a907f902a9 Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Tue, 9 Nov 2021 15:19:55 +0000 Subject: [PATCH] Refactor host configure commands to use a single playbook Ansible failure handling is different when executing multiple top-level playbooks (CLI arguments) vs. multiple plays within a top-level playbook. If any hosts have failed or are unreachable at the end of a top-level playbook, then ansible-playbook exits non-zero. In contrast, execution will continue at the end of a mid-playbook play if there are hosts that have not failed or become unreachable. This is documented in [1]. Currently, Kayobe executes multiple top-level playbooks, most notably in the host configure commands where there is a long list of them. This has implications when working at scale, where failures are more common. If a host fails at any point, then execution of the command will stop at the end of the current playbook. This means that the command must be run again for all hosts. Additionally, if any hosts are unreachable, then the command is unable to progress at all without removing them from the inventory. This change refactors the host configure and host upgrade commands to use a single top-level playbook. [1] https://github.com/markgoddard/ansible-experiments/tree/master/14-error-handling Story: 2009854 Task: 44482 Change-Id: Ia63d66097b10b6ddda30ad693636143f8b1a85e0 --- ansible/infra-vm-host-configure.yml | 24 ++ ansible/overcloud-host-configure.yml | 26 ++ ansible/overcloud-host-upgrade.yml | 5 + ansible/seed-host-configure.yml | 27 ++ ansible/seed-host-upgrade.yml | 3 + ansible/seed-hypervisor-host-configure.yml | 22 ++ ansible/wipe-disks.yml | 17 +- kayobe/cli/commands.py | 64 ++-- kayobe/tests/unit/cli/test_commands.py | 296 +++++++++++------- ...gure-single-playbook-060e9fd96e0aebb5.yaml | 9 + 10 files changed, 327 insertions(+), 166 deletions(-) create mode 100644 ansible/infra-vm-host-configure.yml create mode 100644 ansible/overcloud-host-configure.yml create mode 100644 ansible/overcloud-host-upgrade.yml create mode 100644 ansible/seed-host-configure.yml create mode 100644 ansible/seed-host-upgrade.yml create mode 100644 ansible/seed-hypervisor-host-configure.yml create mode 100644 releasenotes/notes/host-configure-single-playbook-060e9fd96e0aebb5.yaml diff --git a/ansible/infra-vm-host-configure.yml b/ansible/infra-vm-host-configure.yml new file mode 100644 index 000000000..ce7b25c8e --- /dev/null +++ b/ansible/infra-vm-host-configure.yml @@ -0,0 +1,24 @@ +--- +- import_playbook: "ssh-known-host.yml" +- import_playbook: "kayobe-ansible-user.yml" +- import_playbook: "proxy.yml" +- import_playbook: "apt.yml" +- import_playbook: "dnf.yml" +- import_playbook: "pip.yml" +- import_playbook: "kayobe-target-venv.yml" +- import_playbook: "wipe-disks.yml" +- import_playbook: "users.yml" +- import_playbook: "dev-tools.yml" +- import_playbook: "disable-selinux.yml" +- import_playbook: "network.yml" +- import_playbook: "firewall.yml" +- import_playbook: "tuned.yml" +- import_playbook: "sysctl.yml" +- import_playbook: "disable-glean.yml" +- import_playbook: "disable-cloud-init.yml" +- import_playbook: "time.yml" +- import_playbook: "mdadm.yml" +- import_playbook: "luks.yml" +- import_playbook: "lvm.yml" +- import_playbook: "docker-devicemapper.yml" +- import_playbook: "docker.yml" diff --git a/ansible/overcloud-host-configure.yml b/ansible/overcloud-host-configure.yml new file mode 100644 index 000000000..31587891b --- /dev/null +++ b/ansible/overcloud-host-configure.yml @@ -0,0 +1,26 @@ +--- +- import_playbook: "ssh-known-host.yml" +- import_playbook: "kayobe-ansible-user.yml" +- import_playbook: "proxy.yml" +- import_playbook: "apt.yml" +- import_playbook: "dnf.yml" +- import_playbook: "pip.yml" +- import_playbook: "kayobe-target-venv.yml" +- import_playbook: "wipe-disks.yml" +- import_playbook: "users.yml" +- import_playbook: "dev-tools.yml" +- import_playbook: "disable-selinux.yml" +- import_playbook: "network.yml" +- import_playbook: "firewall.yml" +- import_playbook: "tuned.yml" +- import_playbook: "sysctl.yml" +- import_playbook: "disable-glean.yml" +- import_playbook: "disable-cloud-init.yml" +- import_playbook: "time.yml" +- import_playbook: "mdadm.yml" +- import_playbook: "luks.yml" +- import_playbook: "lvm.yml" +- import_playbook: "docker-devicemapper.yml" +- import_playbook: "kolla-ansible-user.yml" +- import_playbook: "kolla-pip.yml" +- import_playbook: "kolla-target-venv.yml" diff --git a/ansible/overcloud-host-upgrade.yml b/ansible/overcloud-host-upgrade.yml new file mode 100644 index 000000000..4564abec6 --- /dev/null +++ b/ansible/overcloud-host-upgrade.yml @@ -0,0 +1,5 @@ +--- +- import_playbook: "kayobe-target-venv.yml" +- import_playbook: "kolla-target-venv.yml" +- import_playbook: "overcloud-docker-sdk-upgrade.yml" +- import_playbook: "overcloud-etc-hosts-fixup.yml" diff --git a/ansible/seed-host-configure.yml b/ansible/seed-host-configure.yml new file mode 100644 index 000000000..4a89f4f09 --- /dev/null +++ b/ansible/seed-host-configure.yml @@ -0,0 +1,27 @@ +--- +- import_playbook: "ssh-known-host.yml" +- import_playbook: "kayobe-ansible-user.yml" +- import_playbook: "proxy.yml" +- import_playbook: "apt.yml" +- import_playbook: "dnf.yml" +- import_playbook: "pip.yml" +- import_playbook: "kayobe-target-venv.yml" +- import_playbook: "wipe-disks.yml" +- import_playbook: "users.yml" +- import_playbook: "dev-tools.yml" +- import_playbook: "disable-selinux.yml" +- import_playbook: "network.yml" +- import_playbook: "firewall.yml" +- import_playbook: "tuned.yml" +- import_playbook: "sysctl.yml" +- import_playbook: "ip-routing.yml" +- import_playbook: "snat.yml" +- import_playbook: "disable-glean.yml" +- import_playbook: "time.yml" +- import_playbook: "mdadm.yml" +- import_playbook: "luks.yml" +- import_playbook: "lvm.yml" +- import_playbook: "docker-devicemapper.yml" +- import_playbook: "kolla-ansible-user.yml" +- import_playbook: "kolla-pip.yml" +- import_playbook: "kolla-target-venv.yml" diff --git a/ansible/seed-host-upgrade.yml b/ansible/seed-host-upgrade.yml new file mode 100644 index 000000000..d803c397e --- /dev/null +++ b/ansible/seed-host-upgrade.yml @@ -0,0 +1,3 @@ +--- +- import_playbook: "kayobe-target-venv.yml" +- import_playbook: "kolla-target-venv.yml" diff --git a/ansible/seed-hypervisor-host-configure.yml b/ansible/seed-hypervisor-host-configure.yml new file mode 100644 index 000000000..86c70623b --- /dev/null +++ b/ansible/seed-hypervisor-host-configure.yml @@ -0,0 +1,22 @@ +--- +- import_playbook: "ssh-known-host.yml" +- import_playbook: "kayobe-ansible-user.yml" +- import_playbook: "proxy.yml" +- import_playbook: "apt.yml" +- import_playbook: "dnf.yml" +- import_playbook: "pip.yml" +- import_playbook: "kayobe-target-venv.yml" +- import_playbook: "wipe-disks.yml" +- import_playbook: "users.yml" +- import_playbook: "dev-tools.yml" +- import_playbook: "network.yml" +- import_playbook: "firewall.yml" +- import_playbook: "tuned.yml" +- import_playbook: "sysctl.yml" +- import_playbook: "ip-routing.yml" +- import_playbook: "snat.yml" +- import_playbook: "time.yml" +- import_playbook: "mdadm.yml" +- import_playbook: "luks.yml" +- import_playbook: "lvm.yml" +- import_playbook: "seed-hypervisor-libvirt-host.yml" diff --git a/ansible/wipe-disks.yml b/ansible/wipe-disks.yml index 8ade2328e..a833f3c17 100644 --- a/ansible/wipe-disks.yml +++ b/ansible/wipe-disks.yml @@ -11,8 +11,15 @@ hosts: seed-hypervisor:seed:overcloud:infra-vms tags: - wipe-disks - roles: - - role: stackhpc.luks - vars: - luks_action: teardown-unmounted - - role: wipe-disks + tasks: + - block: + - name: Tear down unmounted LUKS devices + include_role: + name: stackhpc.luks + vars: + luks_action: teardown-unmounted + + - name: Wipe disks + include_role: + name: wipe-disks + when: wipe_disks | default(false) | bool diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 0ba90f2aa..788d493b5 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -442,17 +442,12 @@ class SeedHypervisorHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed-hypervisor") - playbooks = _build_playbook_list( - "ssh-known-host", "kayobe-ansible-user", "proxy", - "apt", "dnf", "pip", "kayobe-target-venv") + kwargs = {} if parsed_args.wipe_disks: - playbooks += _build_playbook_list("wipe-disks") - playbooks += _build_playbook_list( - "users", "dev-tools", "network", "firewall", "tuned", "sysctl", - "ip-routing", "snat", "time", "mdadm", "luks", "lvm", - "seed-hypervisor-libvirt-host") + kwargs["extra_vars"] = {"wipe_disks": True} + playbooks = _build_playbook_list("seed-hypervisor-host-configure") self.run_kayobe_playbooks(parsed_args, playbooks, - limit="seed-hypervisor") + limit="seed-hypervisor", **kwargs) class SeedHypervisorHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command): @@ -600,17 +595,12 @@ class SeedHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed") # Run kayobe playbooks. - playbooks = _build_playbook_list( - "ssh-known-host", "kayobe-ansible-user", "proxy", - "apt", "dnf", "pip", "kayobe-target-venv") + kwargs = {} if parsed_args.wipe_disks: - playbooks += _build_playbook_list("wipe-disks") - playbooks += _build_playbook_list( - "users", "dev-tools", "disable-selinux", "network", "firewall", - "tuned", "sysctl", "ip-routing", "snat", "disable-glean", "time", - "mdadm", "luks", "lvm", "docker-devicemapper", - "kolla-ansible-user", "kolla-pip", "kolla-target-venv") - self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed") + kwargs["extra_vars"] = {"wipe_disks": True} + playbooks = _build_playbook_list("seed-host-configure") + self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed", + **kwargs) self.generate_kolla_ansible_config(parsed_args, service_config=False) @@ -685,8 +675,7 @@ class SeedHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, def take_action(self, parsed_args): self.app.LOG.debug("Upgrading seed host services") - playbooks = _build_playbook_list( - "kayobe-target-venv", "kolla-target-venv") + playbooks = _build_playbook_list("seed-host-upgrade") self.run_kayobe_playbooks(parsed_args, playbooks, limit="seed") @@ -906,16 +895,12 @@ class InfraVMHostConfigure(KayobeAnsibleMixin, VaultMixin, self.run_kayobe_playbooks(parsed_args, playbooks, limit="infra-vms") # Kayobe playbooks. - playbooks = _build_playbook_list( - "ssh-known-host", "kayobe-ansible-user", "proxy", - "apt", "dnf", "pip", "kayobe-target-venv") + kwargs = {} if parsed_args.wipe_disks: - playbooks += _build_playbook_list("wipe-disks") - playbooks += _build_playbook_list( - "users", "dev-tools", "disable-selinux", "network", "firewall", - "tuned", "sysctl", "disable-glean", "disable-cloud-init", "time", - "mdadm", "luks", "lvm", "docker-devicemapper", "docker") - self.run_kayobe_playbooks(parsed_args, playbooks, limit="infra-vms") + kwargs["extra_vars"] = {"wipe_disks": True} + playbooks = _build_playbook_list("infra-vm-host-configure") + self.run_kayobe_playbooks(parsed_args, playbooks, limit="infra-vms", + **kwargs) class InfraVMHostPackageUpdate(KayobeAnsibleMixin, VaultMixin, Command): @@ -1159,17 +1144,12 @@ class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud") # Kayobe playbooks. - playbooks = _build_playbook_list( - "ssh-known-host", "kayobe-ansible-user", "proxy", - "apt", "dnf", "pip", "kayobe-target-venv") + kwargs = {} if parsed_args.wipe_disks: - playbooks += _build_playbook_list("wipe-disks") - playbooks += _build_playbook_list( - "users", "dev-tools", "disable-selinux", "network", "firewall", - "tuned", "sysctl", "disable-glean", "disable-cloud-init", "time", - "mdadm", "luks", "lvm", "docker-devicemapper", - "kolla-ansible-user", "kolla-pip", "kolla-target-venv") - self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud") + kwargs["extra_vars"] = {"wipe_disks": True} + playbooks = _build_playbook_list("overcloud-host-configure") + self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud", + **kwargs) self.generate_kolla_ansible_config(parsed_args, service_config=False) @@ -1238,9 +1218,7 @@ class OvercloudHostUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, def take_action(self, parsed_args): self.app.LOG.debug("Upgrading overcloud host services") - playbooks = _build_playbook_list( - "kayobe-target-venv", "kolla-target-venv", - "overcloud-docker-sdk-upgrade", "overcloud-etc-hosts-fixup") + playbooks = _build_playbook_list("overcloud-host-upgrade") self.run_kayobe_playbooks(parsed_args, playbooks, limit="overcloud") diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py index 6ba5aa11d..dbb402e1d 100644 --- a/kayobe/tests/unit/cli/test_commands.py +++ b/kayobe/tests/unit/cli/test_commands.py @@ -316,35 +316,42 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [ - utils.get_data_files_path("ansible", "ssh-known-host.yml"), utils.get_data_files_path( - "ansible", "kayobe-ansible-user.yml"), - utils.get_data_files_path("ansible", "proxy.yml"), - utils.get_data_files_path("ansible", "apt.yml"), - utils.get_data_files_path("ansible", "dnf.yml"), - utils.get_data_files_path("ansible", "pip.yml"), - utils.get_data_files_path( - "ansible", "kayobe-target-venv.yml"), - utils.get_data_files_path("ansible", "users.yml"), - utils.get_data_files_path("ansible", "dev-tools.yml"), - utils.get_data_files_path("ansible", "network.yml"), - utils.get_data_files_path("ansible", "firewall.yml"), - utils.get_data_files_path("ansible", "tuned.yml"), - utils.get_data_files_path("ansible", "sysctl.yml"), - utils.get_data_files_path("ansible", "ip-routing.yml"), - utils.get_data_files_path("ansible", "snat.yml"), - utils.get_data_files_path("ansible", "time.yml"), - utils.get_data_files_path("ansible", "mdadm.yml"), - utils.get_data_files_path("ansible", "luks.yml"), - utils.get_data_files_path("ansible", "lvm.yml"), - utils.get_data_files_path( - "ansible", "seed-hypervisor-libvirt-host.yml"), + "ansible", "seed-hypervisor-host-configure.yml"), ], limit="seed-hypervisor", ), ] self.assertEqual(expected_calls, mock_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, + "run_kayobe_playbooks") + def test_seed_hypervisor_host_configure_wipe_disks(self, mock_run): + command = commands.SeedHypervisorHostConfigure(TestApp(), []) + parser = command.get_parser("test") + parsed_args = parser.parse_args(["--wipe-disks"]) + + result = command.run(parsed_args) + self.assertEqual(0, result) + + expected_calls = [ + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "ip-allocation.yml")], + limit="seed-hypervisor", + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path( + "ansible", "seed-hypervisor-host-configure.yml"), + ], + limit="seed-hypervisor", + extra_vars={"wipe_disks": True}, + ), + ] + self.assertEqual(expected_calls, mock_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") def test_seed_hypervisor_host_command_run(self, mock_run): @@ -492,37 +499,8 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [ - utils.get_data_files_path("ansible", "ssh-known-host.yml"), utils.get_data_files_path( - "ansible", "kayobe-ansible-user.yml"), - utils.get_data_files_path("ansible", "proxy.yml"), - utils.get_data_files_path("ansible", "apt.yml"), - utils.get_data_files_path("ansible", "dnf.yml"), - utils.get_data_files_path("ansible", "pip.yml"), - utils.get_data_files_path( - "ansible", "kayobe-target-venv.yml"), - utils.get_data_files_path("ansible", "users.yml"), - utils.get_data_files_path("ansible", "dev-tools.yml"), - utils.get_data_files_path( - "ansible", "disable-selinux.yml"), - utils.get_data_files_path("ansible", "network.yml"), - utils.get_data_files_path("ansible", "firewall.yml"), - utils.get_data_files_path("ansible", "tuned.yml"), - utils.get_data_files_path("ansible", "sysctl.yml"), - utils.get_data_files_path("ansible", "ip-routing.yml"), - utils.get_data_files_path("ansible", "snat.yml"), - utils.get_data_files_path("ansible", "disable-glean.yml"), - utils.get_data_files_path("ansible", "time.yml"), - utils.get_data_files_path("ansible", "mdadm.yml"), - utils.get_data_files_path("ansible", "luks.yml"), - 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"), + "ansible", "seed-host-configure.yml"), ], limit="seed", ), @@ -559,6 +537,68 @@ class TestCase(unittest.TestCase): ] self.assertEqual(expected_calls, mock_kolla_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, + "run_kayobe_playbooks") + @mock.patch.object(commands.KollaAnsibleMixin, + "run_kolla_ansible_seed") + def test_seed_host_configure_wipe_disks(self, mock_kolla_run, mock_run): + command = commands.SeedHostConfigure(TestApp(), []) + parser = command.get_parser("test") + parsed_args = parser.parse_args(["--wipe-disks"]) + + result = command.run(parsed_args) + self.assertEqual(0, result) + + expected_calls = [ + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "ip-allocation.yml")], + limit="seed", + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path( + "ansible", "seed-host-configure.yml"), + ], + limit="seed", + extra_vars={"wipe_disks": True}, + ), + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "kolla-ansible.yml")], + tags="config", + ignore_limit=True, + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path("ansible", "docker.yml"), + ], + limit="seed", + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path("ansible", + "docker-registry.yml"), + ], + limit="seed", + extra_vars={'kayobe_action': 'deploy'}, + ), + ] + print(expected_calls) + print(mock_run.call_args_list) + self.assertEqual(expected_calls, mock_run.call_args_list) + + expected_calls = [ + mock.call( + mock.ANY, + "bootstrap-servers", + ), + ] + self.assertEqual(expected_calls, mock_kolla_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") def test_seed_host_command_run(self, mock_run): @@ -678,9 +718,7 @@ class TestCase(unittest.TestCase): mock.ANY, [ utils.get_data_files_path( - "ansible", "kayobe-target-venv.yml"), - utils.get_data_files_path( - "ansible", "kolla-target-venv.yml"), + "ansible", "seed-host-upgrade.yml"), ], limit="seed", ), @@ -984,39 +1022,42 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [ - utils.get_data_files_path("ansible", "ssh-known-host.yml"), utils.get_data_files_path( - "ansible", "kayobe-ansible-user.yml"), - utils.get_data_files_path("ansible", "proxy.yml"), - utils.get_data_files_path("ansible", "apt.yml"), - utils.get_data_files_path("ansible", "dnf.yml"), - utils.get_data_files_path("ansible", "pip.yml"), - utils.get_data_files_path( - "ansible", "kayobe-target-venv.yml"), - utils.get_data_files_path("ansible", "users.yml"), - utils.get_data_files_path("ansible", "dev-tools.yml"), - utils.get_data_files_path( - "ansible", "disable-selinux.yml"), - utils.get_data_files_path("ansible", "network.yml"), - utils.get_data_files_path("ansible", "firewall.yml"), - utils.get_data_files_path("ansible", "tuned.yml"), - utils.get_data_files_path("ansible", "sysctl.yml"), - utils.get_data_files_path("ansible", "disable-glean.yml"), - utils.get_data_files_path( - "ansible", "disable-cloud-init.yml"), - utils.get_data_files_path("ansible", "time.yml"), - utils.get_data_files_path("ansible", "mdadm.yml"), - utils.get_data_files_path("ansible", "luks.yml"), - utils.get_data_files_path("ansible", "lvm.yml"), - utils.get_data_files_path("ansible", - "docker-devicemapper.yml"), - utils.get_data_files_path("ansible", "docker.yml"), + "ansible", "infra-vm-host-configure.yml"), ], limit="infra-vms", ), ] self.assertEqual(expected_calls, mock_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, + "run_kayobe_playbooks") + def test_infra_vm_host_configure_wipe_disks(self, mock_run): + command = commands.InfraVMHostConfigure(TestApp(), []) + parser = command.get_parser("test") + parsed_args = parser.parse_args(["--wipe-disks"]) + + result = command.run(parsed_args) + self.assertEqual(0, result) + + expected_calls = [ + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "ip-allocation.yml")], + limit="infra-vms", + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path( + "ansible", "infra-vm-host-configure.yml"), + ], + limit="infra-vms", + extra_vars={"wipe_disks": True}, + ), + ] + self.assertEqual(expected_calls, mock_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") def test_infra_vm_host_upgrade(self, mock_run): @@ -1264,37 +1305,8 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [ - utils.get_data_files_path("ansible", "ssh-known-host.yml"), utils.get_data_files_path( - "ansible", "kayobe-ansible-user.yml"), - utils.get_data_files_path("ansible", "proxy.yml"), - utils.get_data_files_path("ansible", "apt.yml"), - utils.get_data_files_path("ansible", "dnf.yml"), - utils.get_data_files_path("ansible", "pip.yml"), - utils.get_data_files_path( - "ansible", "kayobe-target-venv.yml"), - utils.get_data_files_path("ansible", "users.yml"), - utils.get_data_files_path("ansible", "dev-tools.yml"), - utils.get_data_files_path( - "ansible", "disable-selinux.yml"), - utils.get_data_files_path("ansible", "network.yml"), - utils.get_data_files_path("ansible", "firewall.yml"), - utils.get_data_files_path("ansible", "tuned.yml"), - utils.get_data_files_path("ansible", "sysctl.yml"), - utils.get_data_files_path("ansible", "disable-glean.yml"), - utils.get_data_files_path( - "ansible", "disable-cloud-init.yml"), - utils.get_data_files_path("ansible", "time.yml"), - utils.get_data_files_path("ansible", "mdadm.yml"), - utils.get_data_files_path("ansible", "luks.yml"), - 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"), + "ansible", "overcloud-host-configure.yml"), ], limit="overcloud", ), @@ -1324,6 +1336,60 @@ class TestCase(unittest.TestCase): ] self.assertEqual(expected_calls, mock_kolla_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, + "run_kayobe_playbooks") + @mock.patch.object(commands.KollaAnsibleMixin, + "run_kolla_ansible_overcloud") + def test_overcloud_host_configure_wipe_disks(self, mock_kolla_run, + mock_run): + command = commands.OvercloudHostConfigure(TestApp(), []) + parser = command.get_parser("test") + parsed_args = parser.parse_args(["--wipe-disks"]) + + result = command.run(parsed_args) + self.assertEqual(0, result) + + expected_calls = [ + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "ip-allocation.yml")], + limit="overcloud", + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path( + "ansible", "overcloud-host-configure.yml"), + ], + limit="overcloud", + extra_vars={"wipe_disks": True}, + ), + mock.call( + mock.ANY, + [utils.get_data_files_path("ansible", "kolla-ansible.yml")], + tags="config", + ignore_limit=True, + ), + mock.call( + mock.ANY, + [ + utils.get_data_files_path("ansible", "docker.yml"), + utils.get_data_files_path( + "ansible", "swift-block-devices.yml"), + ], + limit="overcloud", + ), + ] + self.assertEqual(expected_calls, mock_run.call_args_list) + + expected_calls = [ + mock.call( + mock.ANY, + "bootstrap-servers", + ), + ] + self.assertEqual(expected_calls, mock_kolla_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") def test_overcloud_host_command_run(self, mock_run): @@ -1443,13 +1509,7 @@ class TestCase(unittest.TestCase): mock.ANY, [ utils.get_data_files_path( - "ansible", "kayobe-target-venv.yml"), - utils.get_data_files_path( - "ansible", "kolla-target-venv.yml"), - utils.get_data_files_path( - "ansible", "overcloud-docker-sdk-upgrade.yml"), - utils.get_data_files_path( - "ansible", "overcloud-etc-hosts-fixup.yml"), + "ansible", "overcloud-host-upgrade.yml"), ], limit="overcloud", ), diff --git a/releasenotes/notes/host-configure-single-playbook-060e9fd96e0aebb5.yaml b/releasenotes/notes/host-configure-single-playbook-060e9fd96e0aebb5.yaml new file mode 100644 index 000000000..418ebabee --- /dev/null +++ b/releasenotes/notes/host-configure-single-playbook-060e9fd96e0aebb5.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Improves error handling by adding a top-level playbook for the ``kayobe * + host configure`` and ``kayobe * host upgrade`` commands. This ensures that + if a host fails during a host configuration command, other hosts are able + to continue to completion. This is useful at scale, where host failures + occur more frequently. See `story 2009854 + `__ for details.