mirror of
https://github.com/openshift/openshift-ansible.git
synced 2026-02-05 06:46:04 +01:00
Merge pull request #11196 from mtnbikenc/rm-installer-checkpoint
Deprecate installer_checkpoint
This commit is contained in:
@@ -2,22 +2,6 @@
|
||||
# l_install_base_packages is passed in via prerequistes.yml.
|
||||
# skip_sanity_checks is passed in via openshift-node/private/image_prep.yml
|
||||
|
||||
- name: Initialization Checkpoint Start
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
roles:
|
||||
- installer_checkpoint
|
||||
tasks:
|
||||
- name: Set install initialization 'In Progress'
|
||||
run_once: true
|
||||
set_stats:
|
||||
data:
|
||||
installer_phase_initialize:
|
||||
title: "Initialization"
|
||||
playbook: ""
|
||||
status: "In Progress"
|
||||
start: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}"
|
||||
|
||||
- import_playbook: evaluate_groups.yml
|
||||
|
||||
- import_playbook: basic_facts.yml
|
||||
@@ -31,15 +15,3 @@
|
||||
when: l_install_base_packages | default(False) | bool
|
||||
|
||||
- import_playbook: version.yml
|
||||
|
||||
- name: Initialization Checkpoint End
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Set install initialization 'Complete'
|
||||
run_once: true
|
||||
set_stats:
|
||||
data:
|
||||
installer_phase_initialize:
|
||||
status: "Complete"
|
||||
end: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}"
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
OpenShift-Ansible Installer Checkpoint
|
||||
======================================
|
||||
|
||||
A complete OpenShift cluster installation is comprised of many different
|
||||
components which can take 30 minutes to several hours to complete. If the
|
||||
installation should fail, it could be confusing to understand at which component
|
||||
the failure occurred. Additionally, it may be desired to re-run only the
|
||||
component which failed instead of starting over from the beginning. Components
|
||||
which came after the failed component would also need to be run individually.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The Installer Checkpoint implements an Ansible callback plugin to allow
|
||||
displaying and logging of the installer status at the end of a playbook run.
|
||||
|
||||
To ensure the callback plugin is loaded, regardless of ansible.cfg file
|
||||
configuration, the plugin has been placed inside the installer_checkpoint role
|
||||
which must be called early in playbook execution. The `init/main.yml` playbook
|
||||
is run first for all entry point playbooks, therefore, the initialization of the
|
||||
checkpoint plugin has been placed at the beginning of that file.
|
||||
|
||||
Playbooks use the [set_stats][set_stats] Ansible module to set a custom stats
|
||||
variable indicating the status of the phase being executed.
|
||||
|
||||
The installer_checkpoint.py callback plugin extends the Ansible
|
||||
`v2_playbook_on_stats` method, which is called at the end of a playbook run, to
|
||||
display the status of each phase which was run. The INSTALLER STATUS report is
|
||||
displayed immediately following the PLAY RECAP.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
In order to indicate the beginning of a component installation, a play must be
|
||||
added to the beginning of the main playbook for the component to set the phase
|
||||
status to "In Progress". Additionally, a play must be added after the last play
|
||||
for that component to set the phase status to "Complete".
|
||||
|
||||
The following example shows the first play of the etcd install using the
|
||||
`set_stats` module for setting the required checkpoint data points.
|
||||
|
||||
* `title` - Name of the component phase
|
||||
* `playbook` - Entry point playbook used to run only this component
|
||||
* `status` - "In Progress" or "Complete"
|
||||
|
||||
```yaml
|
||||
# playbooks/openshift-etcd/private/config.yml
|
||||
---
|
||||
- name: etcd Install Checkpoint Start
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Set etcd install 'In Progress'
|
||||
run_once: true
|
||||
set_stats:
|
||||
data:
|
||||
installer_phase_etcd:
|
||||
title: "etcd Install"
|
||||
playbook: "playbooks/openshift-etcd/config.yml"
|
||||
status: "In Progress"
|
||||
start: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}"
|
||||
|
||||
#...
|
||||
# Various plays here
|
||||
#...
|
||||
|
||||
- name: etcd Install Checkpoint End
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Set etcd install 'Complete'
|
||||
run_once: true
|
||||
set_stats:
|
||||
data:
|
||||
installer_phase_etcd:
|
||||
status: "Complete"
|
||||
end: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}"
|
||||
```
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Example display of a successful playbook run:
|
||||
|
||||
```
|
||||
PLAY RECAP *********************************************************************
|
||||
master01.example.com : ok=158 changed=16 unreachable=0 failed=0
|
||||
node01.example.com : ok=469 changed=74 unreachable=0 failed=0
|
||||
node02.example.com : ok=157 changed=17 unreachable=0 failed=0
|
||||
localhost : ok=24 changed=0 unreachable=0 failed=0
|
||||
|
||||
|
||||
INSTALLER STATUS ***************************************************************
|
||||
Initialization : Complete (0:02:14)
|
||||
Health Check : Complete (0:01:10)
|
||||
etcd Install : Complete (0:02:01)
|
||||
Master Install : Complete (0:11:43)
|
||||
Master Additional Install : Complete (0:00:54)
|
||||
Node Install : Complete (0:14:11)
|
||||
Hosted Install : Complete (0:03:28)
|
||||
```
|
||||
|
||||
Example display if a failure occurs during execution:
|
||||
|
||||
```
|
||||
INSTALLER STATUS ***************************************************************
|
||||
Initialization : Complete (0:02:14)
|
||||
Health Check : Complete (0:01:10)
|
||||
etcd Install : Complete (0:02:58)
|
||||
Master Install : Complete (0:09:20)
|
||||
Master Additional Install : In Progress (0:20:04)
|
||||
This phase can be restarted by running: playbooks/openshift-master/additional_config.yml
|
||||
```
|
||||
|
||||
[set_stats]: http://docs.ansible.com/ansible/latest/set_stats_module.html
|
||||
@@ -1,91 +0,0 @@
|
||||
"""Ansible callback plugin to print a summary completion status of installation
|
||||
phases.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
from ansible import constants as C
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
"""This callback summarizes installation phase status."""
|
||||
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_NAME = 'installer_checkpoint'
|
||||
CALLBACK_NEEDS_WHITELIST = False
|
||||
|
||||
def __init__(self):
|
||||
super(CallbackModule, self).__init__()
|
||||
|
||||
def v2_playbook_on_stats(self, stats):
|
||||
|
||||
# Return if there are no custom stats to process
|
||||
if stats.custom == {}:
|
||||
return
|
||||
|
||||
phases = stats.custom['_run']
|
||||
|
||||
# Find the longest phase title
|
||||
max_column = 0
|
||||
for phase in phases:
|
||||
max_column = max(max_column, len(phases[phase].get('title', '')))
|
||||
|
||||
# Sort the phases by start time
|
||||
ordered_phases = sorted(phases, key=lambda x: (phases[x].get('start', 0)))
|
||||
|
||||
self._display.banner('INSTALLER STATUS')
|
||||
# Display status information for each phase
|
||||
for phase in ordered_phases:
|
||||
phase_title = phases[phase].get('title', '')
|
||||
padding = max_column - len(phase_title) + 2
|
||||
phase_status = phases[phase]['status']
|
||||
phase_time = phase_time_delta(phases[phase])
|
||||
if phase_title:
|
||||
self._display.display(
|
||||
'{}{}: {} ({})'.format(phase_title, ' ' * padding, phase_status, phase_time),
|
||||
color=self.phase_color(phase_status))
|
||||
# If the phase is not complete, tell the user what playbook to rerun
|
||||
if phase_status == 'In Progress' and phase != 'installer_phase_initialize':
|
||||
self._display.display(
|
||||
'\tThis phase can be restarted by running: {}'.format(
|
||||
phases[phase]['playbook']))
|
||||
# Display any extra messages stored during the phase
|
||||
if 'message' in phases[phase]:
|
||||
self._display.display(
|
||||
'\t{}'.format(
|
||||
phases[phase]['message']))
|
||||
|
||||
def phase_color(self, status):
|
||||
""" Return color code for installer phase"""
|
||||
valid_status = [
|
||||
'In Progress',
|
||||
'Complete',
|
||||
]
|
||||
|
||||
if status not in valid_status:
|
||||
self._display.warning('Invalid phase status defined: {}'.format(status))
|
||||
|
||||
if status == 'Complete':
|
||||
phase_color = C.COLOR_OK
|
||||
elif status == 'In Progress':
|
||||
phase_color = C.COLOR_ERROR
|
||||
else:
|
||||
phase_color = C.COLOR_WARN
|
||||
|
||||
return phase_color
|
||||
|
||||
|
||||
def phase_time_delta(phase):
|
||||
""" Calculate the difference between phase start and end times """
|
||||
if not phase.get('start'):
|
||||
return ''
|
||||
time_format = '%Y%m%d%H%M%SZ'
|
||||
phase_start = datetime.strptime(phase['start'], time_format)
|
||||
if 'end' not in phase:
|
||||
# The phase failed so set the end time to now
|
||||
phase_end = datetime.now()
|
||||
else:
|
||||
phase_end = datetime.strptime(phase['end'], time_format)
|
||||
delta = str(phase_end - phase_start).split(".")[0] # Trim microseconds
|
||||
|
||||
return delta
|
||||
Reference in New Issue
Block a user