Create tripleo base strategy class
In order to allow us to share some logic between the linear and free strategies, we need to create a base strategy to use for our shared logic. Change-Id: I593f193f98112dbf1d493ffd22040837597db11c
This commit is contained in:
parent
09da864f8c
commit
e52089e8df
145
tripleo_ansible/ansible_plugins/strategy/tripleo_base.py
Normal file
145
tripleo_ansible/ansible_plugins/strategy/tripleo_base.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# Copyright 2020 Red Hat, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleError
|
||||||
|
from ansible.module_utils._text import to_text
|
||||||
|
from ansible.playbook.included_file import IncludedFile
|
||||||
|
from ansible.plugins.loader import action_loader
|
||||||
|
from ansible.plugins.strategy import StrategyBase
|
||||||
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
strategy: tripleo_base
|
||||||
|
short_description: Base tripleo strategy shared with linear & free
|
||||||
|
description:
|
||||||
|
version_added: "2.9"
|
||||||
|
author: Alex Schultz <aschultz@redhat.com>
|
||||||
|
'''
|
||||||
|
|
||||||
|
display = Display()
|
||||||
|
|
||||||
|
|
||||||
|
class TripleoBase(StrategyBase):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TripleoBase, self).__init__(*args, **kwargs)
|
||||||
|
self._any_errors_fatal = False
|
||||||
|
self._callback_sent = False
|
||||||
|
self._has_work = False
|
||||||
|
self._host_pinned = False
|
||||||
|
self._hosts_left = []
|
||||||
|
self._iterator = None
|
||||||
|
self._play_context = None
|
||||||
|
self._strat_results = []
|
||||||
|
self.noop_task = None
|
||||||
|
# these were defined in 2.9
|
||||||
|
self._has_hosts_cache = False
|
||||||
|
self._has_hosts_cache_all = False
|
||||||
|
|
||||||
|
def _print(self, msg, host=None, level=1):
|
||||||
|
display.verbose(msg, host=host, caplevel=level)
|
||||||
|
|
||||||
|
def _debug(self, msg, host=None):
|
||||||
|
self._print(msg, host, 3)
|
||||||
|
|
||||||
|
def _get_action(self, task):
|
||||||
|
"""Get action based on task"""
|
||||||
|
self._debug('_get_action...')
|
||||||
|
try:
|
||||||
|
action = action_loader.get(task.action, class_only=True)
|
||||||
|
except KeyError:
|
||||||
|
action = None
|
||||||
|
return action
|
||||||
|
|
||||||
|
def _send_task_callback(self, task, templar):
|
||||||
|
"""Send a task callback for task start"""
|
||||||
|
self._debug('_send_task_callback...')
|
||||||
|
if self._callback_sent:
|
||||||
|
return
|
||||||
|
name = task.name
|
||||||
|
try:
|
||||||
|
task.name = to_text(templar.template(task.name,
|
||||||
|
fail_on_undefined=False),
|
||||||
|
nonstring='empty')
|
||||||
|
except Exception:
|
||||||
|
self._debug('templating failed')
|
||||||
|
self._tqm.send_callback('v2_playbook_on_task_start',
|
||||||
|
task,
|
||||||
|
is_conditional=False)
|
||||||
|
task.name = name
|
||||||
|
self._callback_sent = True
|
||||||
|
|
||||||
|
def process_includes(self, host_results, noop=False):
|
||||||
|
"""Handle includes
|
||||||
|
|
||||||
|
This function processes includes and adds them tasks to the hosts.
|
||||||
|
It will return False if there was a failure during the include
|
||||||
|
"""
|
||||||
|
self._debug('process_includes...')
|
||||||
|
include_files = IncludedFile.process_include_results(
|
||||||
|
host_results,
|
||||||
|
iterator=self._iterator,
|
||||||
|
loader=self._loader,
|
||||||
|
variable_manager=self._variable_manager
|
||||||
|
)
|
||||||
|
|
||||||
|
include_success = True
|
||||||
|
if len(include_files) == 0:
|
||||||
|
self._debug('No include files')
|
||||||
|
return include_success
|
||||||
|
|
||||||
|
all_blocks = dict((host, []) for host in self._hosts_left)
|
||||||
|
for include in include_files:
|
||||||
|
self._debug('Adding include...{}'.format(include))
|
||||||
|
try:
|
||||||
|
if include._is_role:
|
||||||
|
ir = self._copy_included_file(include)
|
||||||
|
new_blocks, handler_blocks = ir.get_block_list(
|
||||||
|
play=self._iterator._play,
|
||||||
|
variable_manager=self._variable_manager,
|
||||||
|
loader=self._loader)
|
||||||
|
else:
|
||||||
|
new_blocks = self._load_included_file(
|
||||||
|
include, iterator=self._iterator)
|
||||||
|
for block in new_blocks:
|
||||||
|
vars_params = {'play': self._iterator._play,
|
||||||
|
'task': block._parent}
|
||||||
|
# ansible <2.9 compatibility
|
||||||
|
if self._has_hosts_cache:
|
||||||
|
vars_params['_hosts'] = self._hosts_cache
|
||||||
|
if self._has_hosts_cache_all:
|
||||||
|
vars_params['_hosts_all'] = self._hosts_cache_all
|
||||||
|
|
||||||
|
task_vars = self._variable_manager.get_vars(**vars_params)
|
||||||
|
final_block = block.filter_tagged_tasks(task_vars)
|
||||||
|
|
||||||
|
for host in self._hosts_left:
|
||||||
|
if host in include._hosts:
|
||||||
|
all_blocks[host].append(final_block)
|
||||||
|
except AnsibleError as e:
|
||||||
|
for host in include._hosts:
|
||||||
|
self._tqm._failed_hosts[host.get_name()] = True
|
||||||
|
self._iterator.mark_host_failed(host)
|
||||||
|
display.error(to_text(e), wrap_text=False)
|
||||||
|
include_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
for host in self._hosts_left:
|
||||||
|
self._iterator.add_tasks(host, all_blocks[host])
|
||||||
|
|
||||||
|
return include_success
|
@ -16,17 +16,30 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.playbook.included_file import IncludedFile
|
|
||||||
from ansible.plugins.loader import action_loader
|
|
||||||
from ansible.plugins.strategy import StrategyBase
|
|
||||||
from ansible.template import Templar
|
from ansible.template import Templar
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
|
try:
|
||||||
|
import importlib.util
|
||||||
|
BASESPEC = importlib.util.spec_from_file_location(
|
||||||
|
'tripleo_base',
|
||||||
|
os.path.join(os.path.dirname(__file__), 'tripleo_base.py')
|
||||||
|
)
|
||||||
|
BASE = importlib.util.module_from_spec(BASESPEC)
|
||||||
|
BASESPEC.loader.exec_module(BASE)
|
||||||
|
except ImportError:
|
||||||
|
import imp
|
||||||
|
BASE = imp.load_source(
|
||||||
|
'tripleo_base',
|
||||||
|
os.path.join(os.path.dirname(__file__), 'tripleo_base.py')
|
||||||
|
)
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
strategy: tripleo_free
|
strategy: tripleo_free
|
||||||
short_description: TripleO specific free strategy
|
short_description: TripleO specific free strategy
|
||||||
@ -60,33 +73,16 @@ class TripleoFreeContinue(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class StrategyModule(StrategyBase):
|
class StrategyModule(BASE.TripleoBase):
|
||||||
|
|
||||||
# this strategy handles throttling
|
# this strategy handles throttling
|
||||||
ALLOW_BASE_THROTTLING = False
|
ALLOW_BASE_THROTTLING = False
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(StrategyModule, self).__init__(*args, **kwargs)
|
super(StrategyModule, self).__init__(*args, **kwargs)
|
||||||
self._any_errors_fatal = False
|
|
||||||
self._callback_sent = False
|
|
||||||
self._has_work = False
|
|
||||||
self._host_pinned = False
|
|
||||||
self._hosts_left = []
|
|
||||||
self._iterator = None
|
|
||||||
self._last_host = 0
|
self._last_host = 0
|
||||||
self._play_context = None
|
|
||||||
self._strat_results = []
|
|
||||||
self._workers_free = 0
|
self._workers_free = 0
|
||||||
self._run_once_tasks = set()
|
self._run_once_tasks = set()
|
||||||
# these were defined in 2.9
|
|
||||||
self._has_hosts_cache = False
|
|
||||||
self._has_hosts_cache_all = False
|
|
||||||
|
|
||||||
def _print(self, msg, host=None, level=1):
|
|
||||||
display.verbose(msg, host=host, caplevel=level)
|
|
||||||
|
|
||||||
def _debug(self, msg, host=None):
|
|
||||||
self._print(msg, host, 3)
|
|
||||||
|
|
||||||
def _filter_notified_hosts(self, notified_hosts):
|
def _filter_notified_hosts(self, notified_hosts):
|
||||||
"""Filter notified hosts"""
|
"""Filter notified hosts"""
|
||||||
@ -134,15 +130,6 @@ class StrategyModule(StrategyBase):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_action(self, task):
|
|
||||||
"""Get action based on task"""
|
|
||||||
self._debug('_get_action...')
|
|
||||||
try:
|
|
||||||
action = action_loader.get(task.action, class_only=True)
|
|
||||||
except KeyError:
|
|
||||||
action = None
|
|
||||||
return action
|
|
||||||
|
|
||||||
def _send_task_callback(self, task, templar):
|
def _send_task_callback(self, task, templar):
|
||||||
"""Send task start callback"""
|
"""Send task start callback"""
|
||||||
self._debug('_send_task_callback...')
|
self._debug('_send_task_callback...')
|
||||||
@ -306,66 +293,6 @@ class StrategyModule(StrategyBase):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def process_includes(self, host_results, noop=False):
|
|
||||||
"""Handle includes
|
|
||||||
|
|
||||||
This function processes includes and adds them tasks to the hosts.
|
|
||||||
It will return False if there was a failure during the include
|
|
||||||
"""
|
|
||||||
self._debug('process_includes...')
|
|
||||||
include_files = IncludedFile.process_include_results(
|
|
||||||
host_results,
|
|
||||||
iterator=self._iterator,
|
|
||||||
loader=self._loader,
|
|
||||||
variable_manager=self._variable_manager
|
|
||||||
)
|
|
||||||
|
|
||||||
include_success = True
|
|
||||||
if len(include_files) == 0:
|
|
||||||
self._debug('No include files')
|
|
||||||
return include_success
|
|
||||||
|
|
||||||
all_blocks = dict((host, []) for host in self._hosts_left)
|
|
||||||
for include in include_files:
|
|
||||||
self._debug('Adding include...{}'.format(include))
|
|
||||||
try:
|
|
||||||
if include._is_role:
|
|
||||||
ir = self._copy_included_file(include)
|
|
||||||
new_blocks, handler_blocks = ir.get_block_list(
|
|
||||||
play=self._iterator._play,
|
|
||||||
variable_manager=self._variable_manager,
|
|
||||||
loader=self._loader)
|
|
||||||
else:
|
|
||||||
new_blocks = self._load_included_file(
|
|
||||||
include, iterator=self._iterator)
|
|
||||||
for block in new_blocks:
|
|
||||||
vars_params = {'play': self._iterator._play,
|
|
||||||
'task': block._parent}
|
|
||||||
# ansible <2.9 compatibility
|
|
||||||
if self._has_hosts_cache:
|
|
||||||
vars_params['_hosts'] = self._hosts_cache
|
|
||||||
if self._has_hosts_cache_all:
|
|
||||||
vars_params['_hosts_all'] = self._hosts_cache_all
|
|
||||||
|
|
||||||
task_vars = self._variable_manager.get_vars(**vars_params)
|
|
||||||
final_block = block.filter_tagged_tasks(task_vars)
|
|
||||||
|
|
||||||
for host in self._hosts_left:
|
|
||||||
if host in include._hosts:
|
|
||||||
all_blocks[host].append(final_block)
|
|
||||||
except AnsibleError as e:
|
|
||||||
for host in include._hosts:
|
|
||||||
self._tqm._failed_hosts[host.get_name()] = True
|
|
||||||
self._iterator.mark_host_failed(host)
|
|
||||||
display.error(to_text(e), wrap_text=False)
|
|
||||||
include_success = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
for host in self._hosts_left:
|
|
||||||
self._iterator.add_tasks(host, all_blocks[host])
|
|
||||||
|
|
||||||
return include_success
|
|
||||||
|
|
||||||
def run(self, iterator, play_context):
|
def run(self, iterator, play_context):
|
||||||
"""Run out strategy"""
|
"""Run out strategy"""
|
||||||
self._iterator = iterator
|
self._iterator = iterator
|
||||||
|
@ -16,22 +16,33 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.errors import AnsibleAssertionError
|
from ansible.errors import AnsibleAssertionError
|
||||||
from ansible.errors import AnsibleError
|
|
||||||
from ansible.executor.play_iterator import PlayIterator
|
from ansible.executor.play_iterator import PlayIterator
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.six import iteritems
|
from ansible.module_utils.six import iteritems
|
||||||
from ansible.playbook.block import Block
|
from ansible.playbook.block import Block
|
||||||
from ansible.playbook.included_file import IncludedFile
|
|
||||||
from ansible.playbook.task import Task
|
from ansible.playbook.task import Task
|
||||||
from ansible.plugins.loader import action_loader
|
|
||||||
from ansible.plugins.strategy import StrategyBase
|
|
||||||
from ansible.template import Templar
|
from ansible.template import Templar
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
|
try:
|
||||||
|
import importlib.util
|
||||||
|
BASESPEC = importlib.util.spec_from_file_location(
|
||||||
|
'tripleo_base',
|
||||||
|
os.path.join(os.path.dirname(__file__), 'tripleo_base.py')
|
||||||
|
)
|
||||||
|
BASE = importlib.util.module_from_spec(BASESPEC)
|
||||||
|
BASESPEC.loader.exec_module(BASE)
|
||||||
|
except ImportError:
|
||||||
|
import imp
|
||||||
|
BASE = imp.load_source(
|
||||||
|
'tripleo_base',
|
||||||
|
os.path.join(os.path.dirname(__file__), 'tripleo_base.py')
|
||||||
|
)
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
strategy: tripleo_linear
|
strategy: tripleo_linear
|
||||||
short_description: TripleO specific linear strategy
|
short_description: TripleO specific linear strategy
|
||||||
@ -60,28 +71,10 @@ class TripleoLinearRunOnce(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class StrategyModule(StrategyBase):
|
class StrategyModule(BASE.TripleoBase):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(StrategyModule, self).__init__(*args, **kwargs)
|
super(StrategyModule, self).__init__(*args, **kwargs)
|
||||||
self._any_errors_fatal = False
|
|
||||||
self._callback_sent = False
|
|
||||||
self._has_work = False
|
|
||||||
self._host_pinned = True
|
|
||||||
self._hosts_left = []
|
|
||||||
self._iterator = None
|
|
||||||
self._play_context = None
|
|
||||||
self._strat_results = []
|
|
||||||
self.noop_task = None
|
|
||||||
# these were defined in 2.9
|
|
||||||
self._has_hosts_cache = False
|
|
||||||
self._has_hosts_cache_all = False
|
|
||||||
|
|
||||||
def _print(self, msg, host=None, level=1):
|
|
||||||
display.verbose(msg, host=host, caplevel=level)
|
|
||||||
|
|
||||||
def _debug(self, msg, host=None):
|
|
||||||
self._print(msg, host, 3)
|
|
||||||
|
|
||||||
def _create_noop_task(self):
|
def _create_noop_task(self):
|
||||||
"""Create noop task"""
|
"""Create noop task"""
|
||||||
@ -206,35 +199,6 @@ class StrategyModule(StrategyBase):
|
|||||||
self.noop_task = self._create_noop_task()
|
self.noop_task = self._create_noop_task()
|
||||||
return self._create_noop_block_from(original_block, parent)
|
return self._create_noop_block_from(original_block, parent)
|
||||||
|
|
||||||
def _get_action(self, task):
|
|
||||||
"""Get action from task"""
|
|
||||||
# TODO(mwhahaha): move to base task
|
|
||||||
self._debug('_get_action...')
|
|
||||||
try:
|
|
||||||
action = action_loader.get(task.action, class_only=True)
|
|
||||||
except KeyError:
|
|
||||||
action = None
|
|
||||||
return action
|
|
||||||
|
|
||||||
def _send_task_callback(self, task, templar):
|
|
||||||
"""Send a task callback for task start"""
|
|
||||||
# TODO(mwhahaha): do we need the bool? can we move to base class?
|
|
||||||
self._debug('_send_task_callback...')
|
|
||||||
if self._callback_sent:
|
|
||||||
return
|
|
||||||
name = task.name
|
|
||||||
try:
|
|
||||||
task.name = to_text(templar.template(task.name,
|
|
||||||
fail_on_undefined=False),
|
|
||||||
nonstring='empty')
|
|
||||||
except Exception:
|
|
||||||
display.debug('templating failed')
|
|
||||||
self._tqm.send_callback('v2_playbook_on_task_start',
|
|
||||||
task,
|
|
||||||
is_conditional=False)
|
|
||||||
task.name = name
|
|
||||||
self._callback_sent = True
|
|
||||||
|
|
||||||
def _process_host_tasks(self, host, task):
|
def _process_host_tasks(self, host, task):
|
||||||
"""Process host task and execute"""
|
"""Process host task and execute"""
|
||||||
self._debug('process_host_tasks...')
|
self._debug('process_host_tasks...')
|
||||||
@ -295,70 +259,6 @@ class StrategyModule(StrategyBase):
|
|||||||
self._iterator, max_passes=max_passes))
|
self._iterator, max_passes=max_passes))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def process_includes(self, host_results, noop=False):
|
|
||||||
"""Process our includes"""
|
|
||||||
# TODO(mwhahaha): move to a base class
|
|
||||||
self._debug('process_includes...')
|
|
||||||
include_files = IncludedFile.process_include_results(
|
|
||||||
host_results,
|
|
||||||
iterator=self._iterator,
|
|
||||||
loader=self._loader,
|
|
||||||
variable_manager=self._variable_manager
|
|
||||||
)
|
|
||||||
# TODO(mwhahaha): fix include_failure uage
|
|
||||||
include_success = True
|
|
||||||
if len(include_files) == 0:
|
|
||||||
self._debug('No include files')
|
|
||||||
return include_success
|
|
||||||
|
|
||||||
all_blocks = dict((host, []) for host in self._hosts_left)
|
|
||||||
for include in include_files:
|
|
||||||
self._debug('Adding include...{}'.format(include))
|
|
||||||
try:
|
|
||||||
if include._is_role:
|
|
||||||
ir = self._copy_included_file(include)
|
|
||||||
new_blocks, handler_blocks = ir.get_block_list(
|
|
||||||
play=self._iterator._play,
|
|
||||||
variable_manager=self._variable_manager,
|
|
||||||
loader=self._loader)
|
|
||||||
else:
|
|
||||||
new_blocks = self._load_included_file(
|
|
||||||
include, iterator=self._iterator)
|
|
||||||
for block in new_blocks:
|
|
||||||
vars_params = {'play': self._iterator._play,
|
|
||||||
'task': block._parent}
|
|
||||||
# ansible <2.9 compatibility
|
|
||||||
if self._has_hosts_cache:
|
|
||||||
vars_params['_hosts'] = self._hosts_cache
|
|
||||||
if self._has_hosts_cache_all:
|
|
||||||
vars_params['_hosts_all'] = self._hosts_cache_all
|
|
||||||
|
|
||||||
task_vars = self._variable_manager.get_vars(**vars_params)
|
|
||||||
final_block = block.filter_tagged_tasks(task_vars)
|
|
||||||
|
|
||||||
# TODO(mwhahaha): noop is used for linear not free
|
|
||||||
if noop:
|
|
||||||
noop_block = self._prepare_and_create_noop_block_from(
|
|
||||||
final_block, block._parent)
|
|
||||||
|
|
||||||
for host in self._hosts_left:
|
|
||||||
if host in include._hosts:
|
|
||||||
all_blocks[host].append(final_block)
|
|
||||||
elif noop:
|
|
||||||
all_blocks[host].append(noop_block)
|
|
||||||
except AnsibleError as e:
|
|
||||||
for host in include._hosts:
|
|
||||||
self._tqm._failed_hosts[host.get_name()] = True
|
|
||||||
self._iterator.mark_host_failed(host)
|
|
||||||
display.error(to_text(e), wrap_text=False)
|
|
||||||
include_success = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
for host in self._hosts_left:
|
|
||||||
self._iterator.add_tasks(host, all_blocks[host])
|
|
||||||
|
|
||||||
return include_success
|
|
||||||
|
|
||||||
def _process_failures(self):
|
def _process_failures(self):
|
||||||
"""Handle failures"""
|
"""Handle failures"""
|
||||||
self._debug('_process_failures...')
|
self._debug('_process_failures...')
|
||||||
|
Loading…
Reference in New Issue
Block a user