From 3f303b907ba55f526a4e15a4c7b29698c37dcf52 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Mon, 21 Jun 2021 16:27:59 +1200 Subject: [PATCH] Always run growvols playbook after provision Just like cli-overcloud-node-network-config.yaml, cli-overcloud-node-growvols.yaml will be run by the "openstack overcloud node provision" directly after provisioning so that whole disk images will have their /var volume grown to 100%. This default growvols behaviour can be overridden by adding an ansible_playbooks entry which sets different arguments: - count: 3 name: Controller ansible_playbooks: - playbook: /usr/share/ansible/tripleo-playbooks/cli-overcloud-node-growvols.yaml extra_vars: growvols_args: /var=50% /srv=50% Other changes in this commit include: - Always call run_role_playbooks and pass network_config as an argument - Full unit test coverage on run_role_playbooks - Fix run_role_playbook using os.path.basename instead of os.path.dirname Change-Id: I085ab9da30e1e1a7d2b9a9f230dd0275bd40480d Blueprint: whole-disk-default Depends-On: I0a847ad4077a02a02ad817dd189a6a31c3637a93 --- tripleoclient/tests/test_utils.py | 215 ++++++++++++++++++ .../overcloud_deploy/test_overcloud_deploy.py | 18 ++ .../v2/overcloud_node/test_overcloud_node.py | 14 +- tripleoclient/utils.py | 27 ++- tripleoclient/v1/overcloud_deploy.py | 5 +- tripleoclient/v2/overcloud_node.py | 6 +- 6 files changed, 272 insertions(+), 13 deletions(-) diff --git a/tripleoclient/tests/test_utils.py b/tripleoclient/tests/test_utils.py index 2628819b2..10d0cb37e 100644 --- a/tripleoclient/tests/test_utils.py +++ b/tripleoclient/tests/test_utils.py @@ -255,6 +255,221 @@ class TestRunAnsiblePlaybook(TestCase): ) +class TestRunRolePlaybooks(TestCase): + def setUp(self): + tmp_dir = utils.TempDirs().dir + self.work_dir = os.path.join(tmp_dir, 'working_dir') + utils.makedirs(self.work_dir) + self.inventory_path = os.path.join( + self.work_dir, 'tripleo-ansible-inventory.yaml') + with open(self.inventory_path, 'w') as f: + f.write('{}') + + self.cmd = mock.Mock() + self.cmd.app.options.debug = False + self.cmd.app_args.verbose_level = 0 + + @mock.patch('tripleoclient.utils.run_ansible_playbook') + def test_network_config(self, mock_run): + roles = [ + {'count': 10, 'name': 'Compute'}, + {'count': 3, 'name': 'Controller'} + ] + utils.run_role_playbooks(self.cmd, self.work_dir, self.work_dir, + roles, True) + + self.assertEqual(3, mock_run.call_count) + mock_run.assert_has_calls([ + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Compute', + extra_vars={} + ), + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Controller', + extra_vars={} + ), + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-network-config.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts=None, + extra_vars={} + ) + ]) + + @mock.patch('tripleoclient.utils.run_ansible_playbook') + def test_no_network_config(self, mock_run): + roles = [ + {'count': 10, 'name': 'Compute'}, + {'count': 3, 'name': 'Controller'} + ] + utils.run_role_playbooks(self.cmd, self.work_dir, self.work_dir, + roles, False) + + self.assertEqual(2, mock_run.call_count) + mock_run.assert_has_calls([ + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Compute', + extra_vars={} + ), + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Controller', + extra_vars={} + ) + ]) + + @mock.patch('tripleoclient.utils.run_ansible_playbook') + def test_override_growvols(self, mock_run): + roles = [ + {'count': 10, 'name': 'Compute'}, + { + 'count': 3, + 'name': 'Controller', + 'ansible_playbooks': [ + { + 'playbook': '/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + 'extra_vars': { + 'growvols_args': '/var=50% /srv=50%' + } + } + ] + } + ] + utils.run_role_playbooks(self.cmd, self.work_dir, self.work_dir, + roles, False) + + self.assertEqual(2, mock_run.call_count) + mock_run.assert_has_calls([ + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Compute', + extra_vars={} + ), + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Controller', + extra_vars={'growvols_args': '/var=50% /srv=50%'} + ) + ]) + + @mock.patch('tripleoclient.utils.run_ansible_playbook') + def test_role_playbooks(self, mock_run): + roles = [ + {'count': 10, 'name': 'Compute'}, + { + 'count': 3, + 'name': 'Controller', + 'ansible_playbooks': [ + { + 'playbook': 'the_thing.yaml' + }, + { + 'playbook': '/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + 'extra_vars': { + 'growvols_args': '/var=50% /srv=50%' + } + }, + { + 'playbook': 'the_other_thing.yaml' + }, + ] + } + ] + utils.run_role_playbooks(self.cmd, self.work_dir, self.work_dir, + roles, True) + + self.assertEqual(5, mock_run.call_count) + mock_run.assert_has_calls([ + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Compute', + extra_vars={} + ), + mock.call( + playbook=os.path.join(self.work_dir, 'the_thing.yaml'), + inventory={}, + workdir=mock.ANY, + playbook_dir=self.work_dir, + verbosity=0, + limit_hosts='Controller', + extra_vars={} + ), + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-growvols.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts='Controller', + extra_vars={'growvols_args': '/var=50% /srv=50%'} + ), + mock.call( + playbook=os.path.join(self.work_dir, 'the_other_thing.yaml'), + inventory={}, + workdir=mock.ANY, + playbook_dir=self.work_dir, + verbosity=0, + limit_hosts='Controller', + extra_vars={} + ), + mock.call( + playbook='/usr/share/ansible/tripleo-playbooks/' + 'cli-overcloud-node-network-config.yaml', + inventory={}, + workdir=mock.ANY, + playbook_dir='/usr/share/ansible/tripleo-playbooks', + verbosity=0, + limit_hosts=None, + extra_vars={} + ) + ]) + + class TestRunCommandAndLog(TestCase): def setUp(self): self.mock_logger = mock.Mock(spec=logging.Logger) diff --git a/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py b/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py index 43ea7b4dd..5e869b2a2 100644 --- a/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py +++ b/tripleoclient/tests/v1/overcloud_deploy/test_overcloud_deploy.py @@ -103,6 +103,14 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): self.mock_playbook = playbook_runner.start() self.addCleanup(playbook_runner.stop) + # Mock role playbooks runner + role_playbooks = mock.patch( + 'tripleoclient.utils.run_role_playbooks', + autospec=True + ) + self.mock_role_playbooks = role_playbooks.start() + self.addCleanup(role_playbooks.stop) + # Mock horizon url return horizon_url = mock.patch( 'tripleoclient.workflows.deployment.get_horizon_url', @@ -1537,6 +1545,16 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud): workdir=mock.ANY ) ]) + self.mock_role_playbooks.assert_called_once_with( + self.cmd, + self.tmp_dir.join('working_dir'), + self.tmp_dir.path, + [ + {'count': 10, 'name': 'Compute'}, + {'count': 3, 'name': 'Controller'} + ], + False + ) def test__provision_networks(self): networks_file_path = self.tmp_dir.join('networks.yaml') diff --git a/tripleoclient/tests/v2/overcloud_node/test_overcloud_node.py b/tripleoclient/tests/v2/overcloud_node/test_overcloud_node.py index d72a3beb4..63a459df2 100644 --- a/tripleoclient/tests/v2/overcloud_node/test_overcloud_node.py +++ b/tripleoclient/tests/v2/overcloud_node/test_overcloud_node.py @@ -315,7 +315,9 @@ class TestProvisionNode(fakes.TestOvercloudNode): @mock.patch('tripleoclient.utils.run_ansible_playbook', autospec=True) - def test_ok(self, mock_playbook): + @mock.patch('tripleoclient.utils.run_role_playbooks', + autospec=True) + def test_ok(self, mock_role_playbooks, mock_playbook): with tempfile.NamedTemporaryFile() as inp: with tempfile.NamedTemporaryFile() as outp: with tempfile.NamedTemporaryFile() as keyf: @@ -361,6 +363,16 @@ class TestProvisionNode(fakes.TestOvercloudNode): verbosity=mock.ANY, workdir=mock.ANY ) + mock_role_playbooks.assert_called_once_with( + self.cmd, + mock.ANY, + '/tmp', + [ + {'name': 'Compute'}, + {'name': 'Controller'} + ], + False + ) class TestUnprovisionNode(fakes.TestOvercloudNode): diff --git a/tripleoclient/utils.py b/tripleoclient/utils.py index 1ca0b4e43..113abb288 100644 --- a/tripleoclient/utils.py +++ b/tripleoclient/utils.py @@ -2851,7 +2851,7 @@ def validate_roles_playbooks(roles_file_dir, roles): def run_role_playbook(self, inventory, relative_dir, playbook, limit_hosts=None, extra_vars=dict()): playbook_path = rel_or_abs_path_role_playbook(relative_dir, playbook) - playbook_dir = os.path.basename(playbook_path) + playbook_dir = os.path.dirname(playbook_path) with TempDirs() as tmp: run_ansible_playbook( @@ -2865,22 +2865,39 @@ def run_role_playbook(self, inventory, relative_dir, playbook, ) -def run_role_playbooks(self, working_dir, roles_file_dir, roles): +def run_role_playbooks(self, working_dir, roles_file_dir, roles, + network_config=True): inventory_file = os.path.join(working_dir, 'tripleo-ansible-inventory.yaml') with open(inventory_file, 'r') as f: inventory = yaml.safe_load(f.read()) + growvols_play = 'cli-overcloud-node-growvols.yaml' + growvols_path = rel_or_abs_path_role_playbook( + constants.ANSIBLE_TRIPLEO_PLAYBOOKS, growvols_play) + # Pre-Network Config for role in roles: + role_playbooks = [] + for x in role.get('ansible_playbooks', []): + role_playbooks.append(x['playbook']) + run_role_playbook(self, inventory, roles_file_dir, x['playbook'], limit_hosts=role['name'], extra_vars=x.get('extra_vars', {})) - # Network Config - run_role_playbook(self, inventory, constants.ANSIBLE_TRIPLEO_PLAYBOOKS, - 'cli-overcloud-node-network-config.yaml') + if growvols_path not in role_playbooks: + # growvols was not run with custom extra_vars, run it with defaults + run_role_playbook(self, inventory, + constants.ANSIBLE_TRIPLEO_PLAYBOOKS, + growvols_play, + limit_hosts=role['name']) + + if network_config: + # Network Config + run_role_playbook(self, inventory, constants.ANSIBLE_TRIPLEO_PLAYBOOKS, + 'cli-overcloud-node-network-config.yaml') def create_archive_dir(self, archive_dir=constants.TRIPLEO_ARCHIVE_DIR): diff --git a/tripleoclient/v1/overcloud_deploy.py b/tripleoclient/v1/overcloud_deploy.py index b87b5387f..9f3975a82 100644 --- a/tripleoclient/v1/overcloud_deploy.py +++ b/tripleoclient/v1/overcloud_deploy.py @@ -465,9 +465,8 @@ class DeployOvercloud(command.Command): verbosity=utils.playbook_verbosity(self=self), extra_vars=extra_vars, ) - if parsed_args.network_config: - utils.run_role_playbooks(self, self.working_dir, roles_file_dir, - roles) + utils.run_role_playbooks(self, self.working_dir, roles_file_dir, + roles, parsed_args.network_config) return [output_path] diff --git a/tripleoclient/v2/overcloud_node.py b/tripleoclient/v2/overcloud_node.py index 6ef38ec28..03a24aaa4 100644 --- a/tripleoclient/v2/overcloud_node.py +++ b/tripleoclient/v2/overcloud_node.py @@ -326,10 +326,8 @@ class ProvisionNode(command.Command): verbosity=oooutils.playbook_verbosity(self=self), extra_vars=extra_vars, ) - - if parsed_args.network_config: - oooutils.run_role_playbooks(self, working_dir, roles_file_dir, - roles) + oooutils.run_role_playbooks(self, working_dir, roles_file_dir, + roles, parsed_args.network_config) print('Nodes deployed successfully, add %s to your deployment ' 'environment' % parsed_args.output)