Browse Source

Merge "Create tripleo base strategy class" into stable/train

changes/88/739588/2
Zuul 1 month ago
committed by Gerrit Code Review
parent
commit
d276eaf9d7
3 changed files with 179 additions and 207 deletions
  1. +145
    -0
      tripleo_ansible/ansible_plugins/strategy/tripleo_base.py
  2. +17
    -90
      tripleo_ansible/ansible_plugins/strategy/tripleo_free.py
  3. +17
    -117
      tripleo_ansible/ansible_plugins/strategy/tripleo_linear.py

+ 145
- 0
tripleo_ansible/ansible_plugins/strategy/tripleo_base.py View 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

+ 17
- 90
tripleo_ansible/ansible_plugins/strategy/tripleo_free.py View File

@@ -16,17 +16,30 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os
import time

from ansible import constants as C
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.template import Templar
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 = '''
strategy: tripleo_free
short_description: TripleO specific free strategy
@@ -60,33 +73,16 @@ class TripleoFreeContinue(Exception):
pass


class StrategyModule(StrategyBase):
class StrategyModule(BASE.TripleoBase):

# this strategy handles throttling
ALLOW_BASE_THROTTLING = False

def __init__(self, *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._play_context = None
self._strat_results = []
self._workers_free = 0
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):
"""Filter notified hosts"""
@@ -134,15 +130,6 @@ class StrategyModule(StrategyBase):
return True
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):
"""Send task start callback"""
self._debug('_send_task_callback...')
@@ -306,66 +293,6 @@ class StrategyModule(StrategyBase):

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):
"""Run out strategy"""
self._iterator = iterator


+ 17
- 117
tripleo_ansible/ansible_plugins/strategy/tripleo_linear.py View File

@@ -16,22 +16,33 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os
import time

from ansible import constants as C
from ansible.errors import AnsibleAssertionError
from ansible.errors import AnsibleError
from ansible.executor.play_iterator import PlayIterator
from ansible.module_utils._text import to_text
from ansible.module_utils.six import iteritems
from ansible.playbook.block import Block
from ansible.playbook.included_file import IncludedFile
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.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 = '''
strategy: tripleo_linear
short_description: TripleO specific linear strategy
@@ -60,28 +71,10 @@ class TripleoLinearRunOnce(Exception):
pass


class StrategyModule(StrategyBase):
class StrategyModule(BASE.TripleoBase):

def __init__(self, *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):
"""Create noop task"""
@@ -206,35 +199,6 @@ class StrategyModule(StrategyBase):
self.noop_task = self._create_noop_task()
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):
"""Process host task and execute"""
self._debug('process_host_tasks...')
@@ -295,70 +259,6 @@ class StrategyModule(StrategyBase):
self._iterator, max_passes=max_passes))
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):
"""Handle failures"""
self._debug('_process_failures...')


Loading…
Cancel
Save