Skip to content

Commit b1b0f53

Browse files
Updated commands to get the automated-register and priority fencing delay (#122)
* Add provider value resolution and enhance parameter status determination logic * Refactor cluster parameter retrieval logic and update related tests * Refactor command imports and update cluster status retrieval logic to use new parameters * Refactor HANA resource handling by renaming parameters and updating related logic across multiple files * Refactor command execution logic to simplify parameter value retrieval * Fix typo in method name and update related test cases for cluster parameter retrieval * Fix inconsistent quote style in test case for cluster parameter retrieval * Update cluster parameter retrieval to include PRIORITY_FENCING_DELAY and fix typo in test case name
1 parent 60656ed commit b1b0f53

26 files changed

+301
-152
lines changed

src/module_utils/commands.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,21 @@
3030
OperatingSystemFamily.SUSE: ["crm", "configure", "get_property", "stonith-action"],
3131
}
3232

33-
AUTOMATED_REGISTER = [
34-
"cibadmin",
35-
"--query",
36-
"--xpath",
37-
"//nvpair[@name='AUTOMATED_REGISTER']",
33+
AUTOMATED_REGISTER = lambda rsc: [
34+
"crm_resource",
35+
"--resource",
36+
rsc,
37+
"--get-parameter=AUTOMATED_REGISTER",
3838
]
3939

40+
PRIORITY_FENCING_DELAY = [
41+
"crm_attribute",
42+
"--type",
43+
"crm_config",
44+
"--name",
45+
"priority-fencing-delay",
46+
"--quiet",
47+
]
4048

4149
FREEZE_FILESYSTEM = lambda file_system, mount_point: [
4250
"mount",

src/modules/get_cluster_status_db.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
try:
1515
from ansible.module_utils.get_cluster_status import BaseClusterStatusChecker
1616
from ansible.module_utils.enums import OperatingSystemFamily, HanaSRProvider
17-
from ansible.module_utils.commands import AUTOMATED_REGISTER
17+
from ansible.module_utils.commands import AUTOMATED_REGISTER, PRIORITY_FENCING_DELAY
1818
except ImportError:
1919
from src.module_utils.get_cluster_status import BaseClusterStatusChecker
20-
from src.module_utils.commands import AUTOMATED_REGISTER
20+
from src.module_utils.commands import AUTOMATED_REGISTER, PRIORITY_FENCING_DELAY
2121
from src.module_utils.enums import OperatingSystemFamily, HanaSRProvider
2222

2323

@@ -146,13 +146,15 @@ def __init__(
146146
db_instance_number: str,
147147
saphanasr_provider: HanaSRProvider,
148148
ansible_os_family: OperatingSystemFamily,
149-
hana_resource_name: str = "",
149+
hana_clone_resource_name: str = "",
150+
hana_primitive_resource_name: str = "",
150151
):
151152
super().__init__(ansible_os_family)
152153
self.database_sid = database_sid
153154
self.saphanasr_provider = saphanasr_provider
154155
self.db_instance_number = db_instance_number
155-
self.hana_resource_name = hana_resource_name
156+
self.hana_clone_resource_name = hana_clone_resource_name
157+
self.hana_primitive_resource_name = hana_primitive_resource_name
156158
self.result.update(
157159
{
158160
"primary_node": "",
@@ -161,18 +163,28 @@ def __init__(
161163
"replication_mode": "",
162164
"primary_site_name": "",
163165
"AUTOMATED_REGISTER": "false",
166+
"PRIORITY_FENCING_DELAY": "",
164167
}
165168
)
166169

167-
def _get_automation_register(self) -> None:
170+
def _get_cluster_parameters(self) -> None:
168171
"""
169-
Retrieves the value of the AUTOMATED_REGISTER attribute.
172+
Retrieves the values of the AUTOMATED_REGISTER and PRIORITY_FENCING_DELAY attributes.
170173
"""
171-
try:
172-
cmd_output = self.execute_command_subprocess(AUTOMATED_REGISTER).strip()
173-
self.result["AUTOMATED_REGISTER"] = ET.fromstring(cmd_output).get("value")
174-
except Exception:
175-
self.result["AUTOMATED_REGISTER"] = "unknown"
174+
param_commands = {
175+
"AUTOMATED_REGISTER": (
176+
AUTOMATED_REGISTER(self.hana_primitive_resource_name)
177+
if self.hana_primitive_resource_name
178+
else AUTOMATED_REGISTER(self.hana_clone_resource_name)
179+
),
180+
"PRIORITY_FENCING_DELAY": PRIORITY_FENCING_DELAY,
181+
}
182+
183+
for param_name, command in param_commands.items():
184+
try:
185+
self.result[param_name] = self.execute_command_subprocess(command).strip()
186+
except Exception:
187+
self.result[param_name] = "unknown"
176188

177189
def _process_node_attributes(self, cluster_status_xml: ET.Element) -> Dict[str, Any]:
178190
"""
@@ -209,8 +221,8 @@ def _process_node_attributes(self, cluster_status_xml: ET.Element) -> Dict[str,
209221
HanaSRProvider.ANGI: {
210222
"clone_attr": f"hana_{self.database_sid}_clone_state",
211223
"sync_attr": (
212-
f"master-{self.hana_resource_name}"
213-
if self.hana_resource_name
224+
f"master-{self.hana_clone_resource_name}"
225+
if self.hana_clone_resource_name
214226
else f"master-rsc_SAPHanaCon_{self.database_sid.upper()}"
215227
+ f"_HDB{self.db_instance_number}"
216228
),
@@ -281,7 +293,7 @@ def run(self) -> Dict[str, str]:
281293
:rtype: Dict[str, str]
282294
"""
283295
result = super().run()
284-
self._get_automation_register()
296+
self._get_cluster_parameters()
285297
return result
286298

287299

@@ -294,7 +306,8 @@ def run_module() -> None:
294306
database_sid=dict(type="str", required=True),
295307
saphanasr_provider=dict(type="str", required=True),
296308
db_instance_number=dict(type="str", required=True),
297-
hana_resource_name=dict(type="str", required=False),
309+
hana_clone_resource_name=dict(type="str", required=False),
310+
hana_primitive_resource_name=dict(type="str", required=False),
298311
filter=dict(type="str", required=False, default="os_family"),
299312
)
300313

@@ -307,7 +320,8 @@ def run_module() -> None:
307320
str(ansible_facts(module).get("os_family", "UNKNOWN")).upper()
308321
),
309322
db_instance_number=module.params["db_instance_number"],
310-
hana_resource_name=module.params.get("hana_resource_name", ""),
323+
hana_clone_resource_name=module.params.get("hana_clone_resource_name", ""),
324+
hana_primitive_resource_name=module.params.get("hana_primitive_resource_name", ""),
311325
)
312326
checker.run()
313327

src/modules/get_pcmk_properties_scs.py

Lines changed: 91 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,82 @@ def _validate_resource_constants(self):
246246

247247
return parameters
248248

249+
def _resolve_provider_values(self, expected_value: dict) -> list:
250+
"""
251+
Resolve provider-specific values from a configuration dictionary.
252+
253+
This method handles the complex logic of extracting appropriate values
254+
based on the NFS provider configuration. It supports both provider-specific
255+
configurations and fallback to all available providers.
256+
257+
:param expected_value: Dictionary containing provider configurations
258+
:type expected_value: dict
259+
:return: List of resolved values for validation
260+
:rtype: list
261+
:raises TypeError: If expected_value is not a dictionary
262+
"""
263+
if not isinstance(expected_value, dict):
264+
raise TypeError("Expected value must be a dictionary for provider resolution")
265+
266+
provider_values = []
267+
if self.nfs_provider and self.nfs_provider in expected_value:
268+
provider_config = expected_value[self.nfs_provider]
269+
provider_values = self._extract_values_from_config(provider_config)
270+
else:
271+
for _, provider_config in expected_value.items():
272+
extracted_values = self._extract_values_from_config(provider_config)
273+
if isinstance(extracted_values, list):
274+
provider_values.extend(extracted_values)
275+
else:
276+
provider_values.append(extracted_values)
277+
278+
return provider_values if isinstance(provider_values, list) else [provider_values]
279+
280+
def _extract_values_from_config(self, provider_config):
281+
"""
282+
Extract values from a provider configuration structure.
283+
284+
Handles various configuration formats:
285+
- {"value": [list]} or {"value": "single"}
286+
- [list] directly
287+
- "single" value directly
288+
289+
:param provider_config: Configuration object to extract values from
290+
:type provider_config: dict or list or str
291+
:return: Extracted value(s)
292+
:rtype: list or str
293+
"""
294+
if isinstance(provider_config, dict) and "value" in provider_config:
295+
return provider_config["value"]
296+
elif isinstance(provider_config, (list, str)):
297+
return provider_config
298+
else:
299+
return provider_config
300+
301+
def _compare_value_with_expectations(self, value: str, expected_values) -> str:
302+
"""
303+
Compare a value against expected values and return test status.
304+
305+
:param value: The actual value to compare
306+
:type value: str
307+
:param expected_values: Expected value(s) for comparison
308+
:type expected_values: str or list
309+
:return: Test status (SUCCESS or ERROR)
310+
:rtype: str
311+
"""
312+
if isinstance(expected_values, list):
313+
return (
314+
TestStatus.SUCCESS.value
315+
if str(value) in [str(v) for v in expected_values]
316+
else TestStatus.ERROR.value
317+
)
318+
else:
319+
return (
320+
TestStatus.SUCCESS.value
321+
if str(value) == str(expected_values)
322+
else TestStatus.ERROR.value
323+
)
324+
249325
def _determine_parameter_status(self, value, expected_value):
250326
"""
251327
Determine the status of a parameter with SCS-specific logic for NFS provider.
@@ -257,60 +333,31 @@ def _determine_parameter_status(self, value, expected_value):
257333
:return: The status of the parameter.
258334
:rtype: str
259335
"""
336+
# Handle tuple format (value, required)
260337
if isinstance(expected_value, tuple):
261338
expected_val, required = expected_value
262339
if not required and (expected_val is None or value == ""):
263340
return TestStatus.INFO.value
264341
expected_value = expected_val
265342

343+
# Handle empty/null cases
266344
if expected_value is None or value == "":
267345
return TestStatus.INFO.value
346+
347+
# Handle simple string/list cases
268348
elif isinstance(expected_value, (str, list)):
269-
if isinstance(expected_value, list):
270-
return (
271-
TestStatus.SUCCESS.value
272-
if str(value) in expected_value
273-
else TestStatus.ERROR.value
274-
)
275-
else:
276-
return (
277-
TestStatus.SUCCESS.value
278-
if str(value) == str(expected_value)
279-
else TestStatus.ERROR.value
280-
)
349+
return self._compare_value_with_expectations(value, expected_value)
350+
351+
# Handle complex provider-based dictionary cases
281352
elif isinstance(expected_value, dict):
282-
provider_values = []
283-
if self.nfs_provider and self.nfs_provider in expected_value:
284-
provider_config = expected_value[self.nfs_provider]
285-
if isinstance(provider_config, dict) and "value" in provider_config:
286-
provider_values = provider_config["value"]
287-
else:
288-
provider_values = provider_config
289-
else:
290-
# If provider is unknown/not set, collect all provider values
291-
for provider_key, provider_config in expected_value.items():
292-
if isinstance(provider_config, dict) and "value" in provider_config:
293-
if isinstance(provider_config["value"], list):
294-
provider_values.extend(provider_config["value"])
295-
else:
296-
provider_values.append(provider_config["value"])
297-
elif isinstance(provider_config, list):
298-
provider_values.extend(provider_config)
299-
else:
300-
provider_values.append(provider_config)
301-
302-
if isinstance(provider_values, list):
303-
return (
304-
TestStatus.SUCCESS.value
305-
if str(value) in provider_values
306-
else TestStatus.ERROR.value
307-
)
308-
else:
309-
return (
310-
TestStatus.SUCCESS.value
311-
if str(value) == str(provider_values)
312-
else TestStatus.ERROR.value
313-
)
353+
try:
354+
provider_values = self._resolve_provider_values(expected_value)
355+
return self._compare_value_with_expectations(value, provider_values)
356+
except (TypeError, KeyError) as ex:
357+
self.result["message"] += f"Error resolving provider values: {str(ex)} "
358+
return TestStatus.ERROR.value
359+
360+
# Handle unexpected types
314361
else:
315362
return TestStatus.ERROR.value
316363

src/roles/ha_db_hana/tasks/block-network.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
- node_tier == "hana"
2424
- pre_validations_status == "PASSED"
2525
- cluster_status_pre.stonith_action == "reboot"
26+
- cluster_status_pre.PRIORITY_FENCING_DELAY is defined
27+
- cluster_status_pre.PRIORITY_FENCING_DELAY != ""
28+
- cluster_status_pre.PRIORITY_FENCING_DELAY != "unknown"
2629
block:
2730
- name: "Test Execution: Block Network Communication"
2831
when: ansible_hostname == cluster_status_pre.primary_node
@@ -93,7 +96,8 @@
9396
operation_step: "test_execution"
9497
database_sid: "{{ db_sid | lower }}"
9598
saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}"
96-
hana_resource_name: "{{ hana_resource_name | default('') }}"
99+
hana_clone_resource_name: "{{ hana_clone_resource_name | default('') }}"
100+
hana_primitive_resource_name: "{{ hana_primitive_resource_name | default('') }}"
97101
register: cluster_status_test_execution_primary
98102
retries: "{{ default_retries }}"
99103
delay: "{{ default_delay }}"
@@ -120,7 +124,8 @@
120124
operation_step: "test_execution"
121125
database_sid: "{{ db_sid | lower }}"
122126
saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}"
123-
hana_resource_name: "{{ hana_resource_name | default('') }}"
127+
hana_clone_resource_name: "{{ hana_clone_resource_name | default('') }}"
128+
hana_primitive_resource_name: "{{ hana_primitive_resource_name | default('') }}"
124129
register: cluster_status_post_primary
125130
retries: "{{ default_retries }}"
126131
delay: "{{ default_delay }}"
@@ -140,7 +145,8 @@
140145
operation_step: "test_execution"
141146
database_sid: "{{ db_sid | lower }}"
142147
saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}"
143-
hana_resource_name: "{{ hana_resource_name | default('') }}"
148+
hana_clone_resource_name: "{{ hana_clone_resource_name | default('') }}"
149+
hana_primitive_resource_name: "{{ hana_primitive_resource_name | default('') }}"
144150
register: cluster_status_test_execution_secondary
145151
retries: "{{ default_retries }}"
146152
delay: "{{ default_delay }}"
@@ -158,7 +164,8 @@
158164
operation_step: "test_execution"
159165
database_sid: "{{ db_sid | lower }}"
160166
saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}"
161-
hana_resource_name: "{{ hana_resource_name | default('') }}"
167+
hana_clone_resource_name: "{{ hana_clone_resource_name | default('') }}"
168+
hana_primitive_resource_name: "{{ hana_primitive_resource_name | default('') }}"
162169
register: cluster_status_post_secondary
163170
retries: "{{ default_retries }}"
164171
delay: "{{ default_delay }}"
@@ -227,6 +234,7 @@
227234
test_case_details_from_test_case: {
228235
"Pre Validations: Remove any location_constraints": "{{ location_constraints_results }}",
229236
"Pre Validations: Validate HANA DB cluster status": "{{ cluster_status_pre }}",
237+
"Pre Validations: priority-fencing-delay": "{{ cluster_status_pre.PRIORITY_FENCING_DELAY | default('Not Configured') }}",
230238
"Pre Validations: CleanUp any failed resource": "{{ cleanup_failed_resource_pre }}",
231239
"Cluster Status": "{{ cluster_status_pre }}",
232240
}

src/roles/ha_db_hana/tasks/files/constants.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,6 @@ OS_PARAMETERS:
731731
# === Global INI ===
732732
# Reading the global.ini file to get the provider and path for the SAPHanaSR resource agent
733733
GLOBAL_INI:
734-
GLOBAL_INI:
735734
SUSE:
736735
SAPHanaSR:
737736
provider:

src/roles/ha_db_hana/tasks/fs-freeze.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
operation_step: "test_execution"
6060
database_sid: "{{ db_sid | lower }}"
6161
saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}"
62-
hana_resource_name: "{{ hana_resource_name | default('') }}"
62+
hana_clone_resource_name: "{{ hana_clone_resource_name | default('') }}"
63+
hana_primitive_resource_name: "{{ hana_primitive_resource_name | default('') }}"
6364
register: cluster_status_test_execution
6465
retries: "{{ default_retries }}"
6566
delay: "{{ default_delay }}"
@@ -76,7 +77,8 @@
7677
operation_step: "post_failover"
7778
database_sid: "{{ db_sid | lower }}"
7879
saphanasr_provider: "{{ saphanasr_provider | default('SAPHanaSR') }}"
79-
hana_resource_name: "{{ hana_resource_name | default('') }}"
80+
hana_clone_resource_name: "{{ hana_clone_resource_name | default('') }}"
81+
hana_primitive_resource_name: "{{ hana_primitive_resource_name | default('') }}"
8082
register: cluster_status_post
8183
retries: "{{ default_retries }}"
8284
delay: "{{ default_delay }}"

0 commit comments

Comments
 (0)