mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-09-30 05:23:21 -07:00
pacemaker_resource: Add cloning support for resources and groups (#10665)
Some checks are pending
EOL CI / EOL Sanity (Ⓐ2.16) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py2.7) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.11) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.6) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/3/) (push) Waiting to run
nox / Run extra sanity tests (push) Waiting to run
Some checks are pending
EOL CI / EOL Sanity (Ⓐ2.16) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py2.7) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.11) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.6) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/3/) (push) Waiting to run
nox / Run extra sanity tests (push) Waiting to run
* add clone state for pacemaker_resource * add changelog fragment * Additional description entry for comment header * Apply suggestions from code review Co-authored-by: Felix Fontein <felix@fontein.de> * Update plugins/modules/pacemaker_resource.py Co-authored-by: Felix Fontein <felix@fontein.de> * fix formatting for yamllint * Apply code review suggestions * refactor state name to cloned * Update plugins/modules/pacemaker_resource.py Co-authored-by: Felix Fontein <felix@fontein.de> * Apply suggestions from code review Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Apply suggestions from code review --------- Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
This commit is contained in:
parent
d0123a1038
commit
3baa13a3e4
4 changed files with 113 additions and 7 deletions
2
changelogs/fragments/10665-pacemaker-resource-clone.yml
Normal file
2
changelogs/fragments/10665-pacemaker-resource-clone.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- pacemaker_resource - add ``state=cloned`` for cloning pacemaker resources or groups (https://github.com/ansible-collections/community.general/issues/10322, https://github.com/ansible-collections/community.general/pull/10665).
|
|
@ -13,6 +13,7 @@ from ansible_collections.community.general.plugins.module_utils.cmd_runner impor
|
||||||
_state_map = {
|
_state_map = {
|
||||||
"present": "create",
|
"present": "create",
|
||||||
"absent": "remove",
|
"absent": "remove",
|
||||||
|
"cloned": "clone",
|
||||||
"status": "status",
|
"status": "status",
|
||||||
"enabled": "enable",
|
"enabled": "enable",
|
||||||
"disabled": "disable",
|
"disabled": "disable",
|
||||||
|
@ -65,6 +66,8 @@ def pacemaker_runner(module, **kwargs):
|
||||||
resource_operation=cmd_runner_fmt.as_func(fmt_resource_operation),
|
resource_operation=cmd_runner_fmt.as_func(fmt_resource_operation),
|
||||||
resource_meta=cmd_runner_fmt.stack(cmd_runner_fmt.as_opt_val)("meta"),
|
resource_meta=cmd_runner_fmt.stack(cmd_runner_fmt.as_opt_val)("meta"),
|
||||||
resource_argument=cmd_runner_fmt.as_func(fmt_resource_argument),
|
resource_argument=cmd_runner_fmt.as_func(fmt_resource_argument),
|
||||||
|
resource_clone_ids=cmd_runner_fmt.as_list(),
|
||||||
|
resource_clone_meta=cmd_runner_fmt.as_list(),
|
||||||
apply_all=cmd_runner_fmt.as_bool("--all"),
|
apply_all=cmd_runner_fmt.as_bool("--all"),
|
||||||
agent_validation=cmd_runner_fmt.as_bool("--agent-validation"),
|
agent_validation=cmd_runner_fmt.as_bool("--agent-validation"),
|
||||||
wait=cmd_runner_fmt.as_opt_eq_val("--wait"),
|
wait=cmd_runner_fmt.as_opt_eq_val("--wait"),
|
||||||
|
|
|
@ -27,13 +27,14 @@ options:
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- Indicate desired state for cluster resource.
|
- Indicate desired state for cluster resource.
|
||||||
- The state V(cleanup) has been added in community.general 11.3.0.
|
- The states V(cleanup) and V(cloned) have been added in community.general 11.3.0.
|
||||||
choices: [present, absent, enabled, disabled, cleanup]
|
- If O(state=cloned) or O(state=present), you can set O(resource_clone_ids) and O(resource_clone_meta) to determine exactly what and how to clone.
|
||||||
|
choices: [present, absent, cloned, enabled, disabled, cleanup]
|
||||||
default: present
|
default: present
|
||||||
type: str
|
type: str
|
||||||
name:
|
name:
|
||||||
description:
|
description:
|
||||||
- Specify the resource name to create.
|
- Specify the resource name to create or clone to.
|
||||||
- This is required if O(state=present), O(state=absent), O(state=enabled), or O(state=disabled).
|
- This is required if O(state=present), O(state=absent), O(state=enabled), or O(state=disabled).
|
||||||
type: str
|
type: str
|
||||||
resource_type:
|
resource_type:
|
||||||
|
@ -95,6 +96,18 @@ options:
|
||||||
- Options to associate with resource action.
|
- Options to associate with resource action.
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
|
resource_clone_ids:
|
||||||
|
description:
|
||||||
|
- List of clone resource IDs to clone from.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
version_added: 11.3.0
|
||||||
|
resource_clone_meta:
|
||||||
|
description:
|
||||||
|
- List of metadata to associate with clone resource.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
version_added: 11.3.0
|
||||||
wait:
|
wait:
|
||||||
description:
|
description:
|
||||||
- Timeout period for polling the resource creation.
|
- Timeout period for polling the resource creation.
|
||||||
|
@ -142,7 +155,7 @@ class PacemakerResource(StateModuleHelper):
|
||||||
module = dict(
|
module = dict(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
state=dict(type='str', default='present', choices=[
|
state=dict(type='str', default='present', choices=[
|
||||||
'present', 'absent', 'enabled', 'disabled', 'cleanup']),
|
'present', 'absent', 'cloned', 'enabled', 'disabled', 'cleanup']),
|
||||||
name=dict(type='str'),
|
name=dict(type='str'),
|
||||||
resource_type=dict(type='dict', options=dict(
|
resource_type=dict(type='dict', options=dict(
|
||||||
resource_name=dict(type='str'),
|
resource_name=dict(type='str'),
|
||||||
|
@ -159,6 +172,8 @@ class PacemakerResource(StateModuleHelper):
|
||||||
argument_action=dict(type='str', choices=['clone', 'master', 'group', 'promotable']),
|
argument_action=dict(type='str', choices=['clone', 'master', 'group', 'promotable']),
|
||||||
argument_option=dict(type='list', elements='str'),
|
argument_option=dict(type='list', elements='str'),
|
||||||
)),
|
)),
|
||||||
|
resource_clone_ids=dict(type='list', elements='str'),
|
||||||
|
resource_clone_meta=dict(type='list', elements='str'),
|
||||||
wait=dict(type='int', default=300),
|
wait=dict(type='int', default=300),
|
||||||
),
|
),
|
||||||
required_if=[
|
required_if=[
|
||||||
|
@ -194,6 +209,10 @@ class PacemakerResource(StateModuleHelper):
|
||||||
('out', result[1] if result[1] != "" else None),
|
('out', result[1] if result[1] != "" else None),
|
||||||
('err', result[2])])
|
('err', result[2])])
|
||||||
|
|
||||||
|
def fmt_as_stack_argument(self, value, arg):
|
||||||
|
if value is not None:
|
||||||
|
return [x for k in value for x in (arg, k)]
|
||||||
|
|
||||||
def state_absent(self):
|
def state_absent(self):
|
||||||
force = get_pacemaker_maintenance_mode(self.runner)
|
force = get_pacemaker_maintenance_mode(self.runner)
|
||||||
with self.runner('cli_action state name force', output_process=self._process_command_output(True, "does not exist"), check_mode_skip=True) as ctx:
|
with self.runner('cli_action state name force', output_process=self._process_command_output(True, "does not exist"), check_mode_skip=True) as ctx:
|
||||||
|
@ -201,10 +220,19 @@ class PacemakerResource(StateModuleHelper):
|
||||||
|
|
||||||
def state_present(self):
|
def state_present(self):
|
||||||
with self.runner(
|
with self.runner(
|
||||||
'cli_action state name resource_type resource_option resource_operation resource_meta resource_argument wait',
|
'cli_action state name resource_type resource_option resource_operation resource_meta resource_argument '
|
||||||
|
'resource_clone_ids resource_clone_meta wait',
|
||||||
output_process=self._process_command_output(not get_pacemaker_maintenance_mode(self.runner), "already exists"),
|
output_process=self._process_command_output(not get_pacemaker_maintenance_mode(self.runner), "already exists"),
|
||||||
check_mode_skip=True) as ctx:
|
check_mode_skip=True) as ctx:
|
||||||
ctx.run(cli_action='resource')
|
ctx.run(cli_action='resource', resource_clone_ids=self.fmt_as_stack_argument(self.module.params["resource_clone_ids"], "clone"))
|
||||||
|
|
||||||
|
def state_cloned(self):
|
||||||
|
with self.runner(
|
||||||
|
'cli_action state name resource_clone_ids resource_clone_meta wait',
|
||||||
|
output_process=self._process_command_output(
|
||||||
|
not get_pacemaker_maintenance_mode(self.runner),
|
||||||
|
"already a clone resource"), check_mode_skip=True) as ctx:
|
||||||
|
ctx.run(cli_action='resource', resource_clone_meta=self.fmt_as_stack_argument(self.module.params["resource_clone_meta"], "meta"))
|
||||||
|
|
||||||
def state_enabled(self):
|
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:
|
with self.runner('cli_action state name', output_process=self._process_command_output(True, "Starting"), check_mode_skip=True) as ctx:
|
||||||
|
|
|
@ -78,6 +78,10 @@ test_cases:
|
||||||
argument_action: group
|
argument_action: group
|
||||||
argument_option:
|
argument_option:
|
||||||
- test_group
|
- test_group
|
||||||
|
resource_clone_ids:
|
||||||
|
- test_clone
|
||||||
|
resource_clone_meta:
|
||||||
|
- test_clone_meta1=789
|
||||||
wait: 200
|
wait: 200
|
||||||
output:
|
output:
|
||||||
changed: true
|
changed: true
|
||||||
|
@ -100,7 +104,7 @@ test_cases:
|
||||||
dc-version=2.1.9-1.fc41-7188dbf
|
dc-version=2.1.9-1.fc41-7188dbf
|
||||||
have-watchdog=false
|
have-watchdog=false
|
||||||
err: ""
|
err: ""
|
||||||
- command: [/testbin/pcs, resource, create, virtual-ip, ocf:heartbeat:IPaddr2, "ip=[192.168.2.1]", op, start, timeout=1200, op, stop, timeout=1200, op, monitor, timeout=1200, meta, test_meta1=123, meta, test_meta2=456, --group, test_group, --wait=200]
|
- command: [/testbin/pcs, resource, create, virtual-ip, ocf:heartbeat:IPaddr2, "ip=[192.168.2.1]", op, start, timeout=1200, op, stop, timeout=1200, op, monitor, timeout=1200, meta, test_meta1=123, meta, test_meta2=456, --group, test_group, clone, test_clone, test_clone_meta1=789, --wait=200]
|
||||||
environ: *env-def
|
environ: *env-def
|
||||||
rc: 0
|
rc: 0
|
||||||
out: "Assumed agent name 'ocf:heartbeat:IPaddr2'"
|
out: "Assumed agent name 'ocf:heartbeat:IPaddr2'"
|
||||||
|
@ -496,3 +500,72 @@ test_cases:
|
||||||
rc: 0
|
rc: 0
|
||||||
out: "NO resources configured"
|
out: "NO resources configured"
|
||||||
err: ""
|
err: ""
|
||||||
|
- id: test_clone_minimal_input_resource_not_exist
|
||||||
|
input:
|
||||||
|
state: cloned
|
||||||
|
name: virtual-ip
|
||||||
|
output:
|
||||||
|
failed: true
|
||||||
|
msg: "pcs failed with error (rc=1): Error: unable to find group or resource: virtual-ip"
|
||||||
|
mocks:
|
||||||
|
run_command:
|
||||||
|
- command: [/testbin/pcs, resource, status, virtual-ip]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 1
|
||||||
|
out: ""
|
||||||
|
err: "Error: resource or tag id 'virtual-ip' not found"
|
||||||
|
- command: [/testbin/pcs, property, config]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 1
|
||||||
|
out: |
|
||||||
|
Cluster Properties: cib-bootstrap-options
|
||||||
|
cluster-infrastructure=corosync
|
||||||
|
cluster-name=hacluster
|
||||||
|
dc-version=2.1.9-1.fc41-7188dbf
|
||||||
|
have-watchdog=false
|
||||||
|
err: ""
|
||||||
|
- command: [/testbin/pcs, resource, clone, virtual-ip, --wait=300]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 1
|
||||||
|
out: ""
|
||||||
|
err: "Error: unable to find group or resource: virtual-ip"
|
||||||
|
- id: test_clone_filled_input_resource_exists
|
||||||
|
input:
|
||||||
|
state: cloned
|
||||||
|
name: virtual-ip
|
||||||
|
resource_clone_ids:
|
||||||
|
- test_clone
|
||||||
|
resource_clone_meta:
|
||||||
|
- test_clone_meta1=789
|
||||||
|
wait: 200
|
||||||
|
output:
|
||||||
|
changed: true
|
||||||
|
previous_value: " * virtual-ip\t(ocf:heartbeat:IPAddr2):\t Started"
|
||||||
|
value: " * Clone Set: virtual-ip-clone [virtual-ip]\t(ocf:heartbeat:IPAddr2):\t Started"
|
||||||
|
mocks:
|
||||||
|
run_command:
|
||||||
|
- command: [/testbin/pcs, resource, status, virtual-ip]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 0
|
||||||
|
out: " * virtual-ip\t(ocf:heartbeat:IPAddr2):\t Started"
|
||||||
|
err: ""
|
||||||
|
- command: [/testbin/pcs, property, config]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 1
|
||||||
|
out: |
|
||||||
|
Cluster Properties: cib-bootstrap-options
|
||||||
|
cluster-infrastructure=corosync
|
||||||
|
cluster-name=hacluster
|
||||||
|
dc-version=2.1.9-1.fc41-7188dbf
|
||||||
|
have-watchdog=false
|
||||||
|
err: ""
|
||||||
|
- command: [/testbin/pcs, resource, clone, virtual-ip, test_clone, meta, test_clone_meta1=789, --wait=200]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 0
|
||||||
|
out: ""
|
||||||
|
err: ""
|
||||||
|
- command: [/testbin/pcs, resource, status, virtual-ip]
|
||||||
|
environ: *env-def
|
||||||
|
rc: 0
|
||||||
|
out: " * Clone Set: virtual-ip-clone [virtual-ip]\t(ocf:heartbeat:IPAddr2):\t Started"
|
||||||
|
err: ""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue