From 1d2547cc7f9bd28a1dde447c93ec7f0ec9dd4af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Jens=C3=A5s?= Date: Tue, 13 Apr 2021 13:59:12 +0200 Subject: [PATCH] Baremetal deploy - user playbook interface Extend the overcloud node provision command to run ansible playbooks defined in the baremetal deployment definition against the provisioned nodes. To ensure the playbook is applied prior to node network configuration set 'pre_network: true'. Additonal ansible vars can be defined as 'extra_vars' for each ansible playbook definition. Implements: blueprint network-data-v2-ports Depends-On: https://review.opendev.org/786045 Change-Id: I67a15f637a62e2cb683e6e160483201f7ba093e9 --- tripleoclient/exceptions.py | 8 +++ tripleoclient/v2/overcloud_node.py | 88 ++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/tripleoclient/exceptions.py b/tripleoclient/exceptions.py index f4af206a5..caa9f63cd 100644 --- a/tripleoclient/exceptions.py +++ b/tripleoclient/exceptions.py @@ -139,3 +139,11 @@ class BannedParameters(Base): class HeatPodMessageQueueException(Base): """Heat messaging queue not created""" + + +class PlaybookNotFound(NotFound): + """Playbook not found""" + + +class InvalidPlaybook(Base): + """Invalid playbook path specified""" diff --git a/tripleoclient/v2/overcloud_node.py b/tripleoclient/v2/overcloud_node.py index 0dd53bce7..74e5477c4 100644 --- a/tripleoclient/v2/overcloud_node.py +++ b/tripleoclient/v2/overcloud_node.py @@ -28,6 +28,7 @@ import yaml from tripleoclient import command from tripleoclient import constants +from tripleoclient import exceptions from tripleoclient import utils as oooutils from tripleoclient.workflows import baremetal @@ -270,6 +271,14 @@ class ProvisionNode(command.Command): return parser + def _validate_playbook(self, playbook_path): + if not os.path.exists(playbook_path): + raise exceptions.PlaybookNotFound( + 'Playbook file {} not found.'.format(playbook_path)) + if not os.path.isfile(playbook_path): + raise exceptions.InvalidPlaybook( + 'Playbook {} is not a file.'.format(playbook_path)) + def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) @@ -280,7 +289,8 @@ class ProvisionNode(command.Command): working_dir = os.path.abspath(parsed_args.working_dir) oooutils.makedirs(working_dir) - with open(parsed_args.input, 'r') as fp: + roles_file_path = os.path.abspath(parsed_args.input) + with open(roles_file_path, 'r') as fp: roles = yaml.safe_load(fp) key = self.get_key_pair(parsed_args) @@ -313,21 +323,77 @@ class ProvisionNode(command.Command): extra_vars=extra_vars, ) - if parsed_args.network_config: + if parsed_args.network_ports or parsed_args.network_config: + roles_file_dir = os.path.dirname(roles_file_path) inventory_file = os.path.join(working_dir, 'tripleo-ansible-inventory.yaml') - with open(inventory_file, 'r') as f: inventory = yaml.safe_load(f.read()) - with oooutils.TempDirs() as tmp: - oooutils.run_ansible_playbook( - playbook='cli-overcloud-node-network-config.yaml', - inventory=inventory, - workdir=tmp, - playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS, - verbosity=oooutils.playbook_verbosity(self=self), - ) + # Pre-Network Config + for role in roles: + for playbook in role.get('ansible_playbooks', []): + if not playbook.get('pre_network'): + continue + + if os.path.isabs(playbook['playbook']): + playbook_path = playbook['playbook'] + else: + # Load for playbook relative to the roles file + playbook_path = os.path.join(roles_file_dir, + playbook['playbook']) + + self._validate_playbook(playbook_path) + playbook_dir = os.path.basename(playbook_path) + + with oooutils.TempDirs() as tmp: + oooutils.run_ansible_playbook( + playbook=playbook_path, + inventory=inventory, + workdir=tmp, + playbook_dir=playbook_dir, + verbosity=oooutils.playbook_verbosity(self=self), + limit_hosts=role['name'], + extra_vars=playbook.get('extra_vars', {}) + ) + + # Network Config + if parsed_args.network_config: + with oooutils.TempDirs() as tmp: + oooutils.run_ansible_playbook( + playbook='cli-overcloud-node-network-config.yaml', + inventory=inventory, + workdir=tmp, + playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS, + verbosity=oooutils.playbook_verbosity(self=self), + ) + + # Post-Network Config + for role in roles: + for playbook in role.get('ansible_playbooks', []): + if playbook.get('pre_network'): + continue + + if os.path.isabs(playbook['playbook']): + playbook_path = playbook['playbook'] + else: + # Load for playbook relative to the roles file + playbook_path = os.path.join(roles_file_dir, + playbook['playbook']) + + self._validate_playbook(playbook_path) + playbook_dir = os.path.basename(playbook_path) + + with oooutils.TempDirs() as tmp: + oooutils.run_ansible_playbook( + playbook=playbook_path, + inventory=inventory, + workdir=tmp, + playbook_dir=playbook_dir, + verbosity=oooutils.playbook_verbosity(self=self), + limit_hosts=role['name'], + extra_vars=playbook.get('extra_vars', {}) + ) print('Nodes deployed successfully, add %s to your deployment ' 'environment' % parsed_args.output)