mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-10-02 14:33:21 -07:00
* feat(initial): Add pacemaker_stonith module and unit tests * feat(initial): Add working changes to pacemaker_stonith * refactor(review): Apply code review suggestions * Apply suggestions from code review Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * refactor(review): Additional code review items * bug(cli_action): Add missing runner arguments * Apply code review suggestions * Apply suggestions from code review Co-authored-by: Felix Fontein <felix@fontein.de> * Apply suggestions from code review Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * WIP * Apply doc changes to pacemaker stonith * Update plugins/modules/pacemaker_stonith.py --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
220 lines
7.6 KiB
Python
220 lines
7.6 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright (c) 2025, Dexter Le <dextersydney2001@gmail.com>
|
|
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from __future__ import absolute_import, division, print_function
|
|
__metaclass__ = type
|
|
|
|
DOCUMENTATION = '''
|
|
module: pacemaker_stonith
|
|
short_description: Manage Pacemaker STONITH
|
|
author:
|
|
- Dexter Le (@munchtoast)
|
|
version_added: 11.3.0
|
|
description:
|
|
- This module manages STONITH in a Pacemaker cluster using the Pacemaker CLI.
|
|
seealso:
|
|
- name: Pacemaker STONITH documentation
|
|
description: Complete documentation for Pacemaker STONITH.
|
|
link: https://clusterlabs.org/projects/pacemaker/doc/3.0/Pacemaker_Explained/html/resources.html#stonith
|
|
extends_documentation_fragment:
|
|
- community.general.attributes
|
|
attributes:
|
|
check_mode:
|
|
support: full
|
|
diff_mode:
|
|
support: partial
|
|
details:
|
|
- Only works when check mode is not enabled.
|
|
options:
|
|
state:
|
|
description:
|
|
- Indicate desired state for cluster STONITH.
|
|
choices: [present, absent, enabled, disabled]
|
|
default: present
|
|
type: str
|
|
name:
|
|
description:
|
|
- Specify the STONITH name to create.
|
|
required: true
|
|
type: str
|
|
stonith_type:
|
|
description:
|
|
- Specify the STONITH device type.
|
|
type: str
|
|
stonith_options:
|
|
description:
|
|
- Specify the STONITH option to create.
|
|
type: list
|
|
elements: str
|
|
default: []
|
|
stonith_operations:
|
|
description:
|
|
- List of operations to associate with STONITH.
|
|
type: list
|
|
elements: dict
|
|
default: []
|
|
suboptions:
|
|
operation_action:
|
|
description:
|
|
- Operation action to associate with STONITH.
|
|
type: str
|
|
operation_options:
|
|
description:
|
|
- Operation options to associate with action.
|
|
type: list
|
|
elements: str
|
|
stonith_metas:
|
|
description:
|
|
- List of metadata to associate with STONITH.
|
|
type: list
|
|
elements: str
|
|
stonith_argument:
|
|
description:
|
|
- Action to associate with STONITH.
|
|
type: dict
|
|
suboptions:
|
|
argument_action:
|
|
description:
|
|
- Action to apply to STONITH.
|
|
type: str
|
|
choices: [group, before, after]
|
|
argument_options:
|
|
description:
|
|
- Options to associate with STONITH action.
|
|
type: list
|
|
elements: str
|
|
agent_validation:
|
|
description:
|
|
- Enabled agent validation for STONITH creation.
|
|
type: bool
|
|
default: false
|
|
wait:
|
|
description:
|
|
- Timeout period for polling the STONITH creation.
|
|
type: int
|
|
default: 300
|
|
'''
|
|
|
|
EXAMPLES = '''
|
|
- name: Create virtual-ip STONITH
|
|
community.general.pacemaker_stonith:
|
|
state: present
|
|
name: virtual-stonith
|
|
stonith_type: fence_virt
|
|
stonith_options:
|
|
- "pcmk_host_list=f1"
|
|
stonith_operations:
|
|
- operation_action: monitor
|
|
operation_options:
|
|
- "interval=30s"
|
|
'''
|
|
|
|
RETURN = '''
|
|
previous_value:
|
|
description: The value of the STONITH before executing the module.
|
|
type: str
|
|
sample: " * virtual-stonith\t(stonith:fence_virt):\t Started"
|
|
returned: on success
|
|
value:
|
|
description: The value of the STONITH after executing the module.
|
|
type: str
|
|
sample: " * virtual-stonith\t(stonith:fence_virt):\t Started"
|
|
returned: on success
|
|
'''
|
|
|
|
from ansible_collections.community.general.plugins.module_utils.module_helper import StateModuleHelper
|
|
from ansible_collections.community.general.plugins.module_utils.pacemaker import pacemaker_runner
|
|
|
|
|
|
class PacemakerStonith(StateModuleHelper):
|
|
module = dict(
|
|
argument_spec=dict(
|
|
state=dict(type='str', default='present', choices=['present', 'absent', 'enabled', 'disabled']),
|
|
name=dict(type='str', required=True),
|
|
stonith_type=dict(type='str'),
|
|
stonith_options=dict(type='list', elements='str', default=[]),
|
|
stonith_operations=dict(type='list', elements='dict', default=[], options=dict(
|
|
operation_action=dict(type='str'),
|
|
operation_options=dict(type='list', elements='str'),
|
|
)),
|
|
stonith_metas=dict(type='list', elements='str'),
|
|
stonith_argument=dict(type='dict', options=dict(
|
|
argument_action=dict(type='str', choices=['before', 'after', 'group']),
|
|
argument_options=dict(type='list', elements='str'),
|
|
)),
|
|
agent_validation=dict(type='bool', default=False),
|
|
wait=dict(type='int', default=300),
|
|
),
|
|
required_if=[('state', 'present', ['stonith_type', 'stonith_options'])],
|
|
supports_check_mode=True
|
|
)
|
|
|
|
def __init_module__(self):
|
|
self.runner = pacemaker_runner(self.module)
|
|
self.vars.set('previous_value', self._get()['out'])
|
|
self.vars.set('value', self.vars.previous_value, change=True, diff=True)
|
|
|
|
def __quit_module__(self):
|
|
self.vars.set('value', self._get()['out'])
|
|
|
|
def _process_command_output(self, fail_on_err, ignore_err_msg=""):
|
|
def process(rc, out, err):
|
|
if fail_on_err and rc != 0 and err and ignore_err_msg not in err:
|
|
self.do_raise('pcs failed with error (rc={0}): {1}'.format(rc, err))
|
|
out = out.rstrip()
|
|
return None if out == "" else out
|
|
return process
|
|
|
|
def _get(self):
|
|
with self.runner('cli_action state name') as ctx:
|
|
result = ctx.run(cli_action='stonith', state='status')
|
|
return dict(rc=result[0],
|
|
out=result[1] if result[1] != "" else None,
|
|
err=result[2])
|
|
|
|
def fmt_stonith_resource(self):
|
|
return dict(resource_name=self.vars.stonith_type)
|
|
|
|
# TODO: Pluralize operation_options in separate PR and remove this helper fmt function
|
|
def fmt_stonith_operations(self):
|
|
modified_stonith_operations = []
|
|
for stonith_operation in self.vars.stonith_operations:
|
|
modified_stonith_operations.append(dict([("operation_action", stonith_operation.get('operation_action')),
|
|
("operation_option", stonith_operation.get('operation_options'))]))
|
|
return modified_stonith_operations
|
|
|
|
def state_absent(self):
|
|
with self.runner('cli_action state name', output_process=self._process_command_output(True, "does not exist"), check_mode_skip=True) as ctx:
|
|
ctx.run(cli_action='stonith')
|
|
|
|
def state_present(self):
|
|
with self.runner(
|
|
'cli_action state name resource_type resource_option resource_operation resource_meta resource_argument agent_validation wait',
|
|
output_process=self._process_command_output(True, "already exists"),
|
|
check_mode_skip=True) as ctx:
|
|
ctx.run(cli_action='stonith',
|
|
resource_type=self.fmt_stonith_resource(),
|
|
resource_option=self.vars.stonith_options,
|
|
resource_operation=self.fmt_stonith_operations(),
|
|
resource_meta=self.vars.stonith_metas,
|
|
resource_argument=self.vars.stonith_argument)
|
|
|
|
def state_enabled(self):
|
|
with self.runner('cli_action state name', output_process=self._process_command_output(True, "Starting"), check_mode_skip=True) as ctx:
|
|
ctx.run(cli_action='stonith')
|
|
|
|
def state_disabled(self):
|
|
with self.runner('cli_action state name', output_process=self._process_command_output(True, "Stopped"), check_mode_skip=True) as ctx:
|
|
ctx.run(cli_action='stonith')
|
|
|
|
|
|
def main():
|
|
PacemakerStonith.execute()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|