Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/HIGH_AVAILABILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ For the framework to access the properties of the Azure Load Balancer in a high
1. Enable system managed identity on the management server by following the steps in [Configure managed identities on Azure VMs](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities?pivots=qs-configure-portal-windows-vm#system-assigned-managed-identity).
1. Open the Azure Load Balancer used for the high availability deployment of your SAP system on Azure.
1. In the Azure Load Balancer panel, go to Access control (IAM).
1. Follow steps 5 to 10 from [Use managed identity to access Azure Resource](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities?pivots=qs-configure-portal-windows-vm#system-assigned-managed-identity) to complete the configuration.
1. Follow steps from [Use managed identity to access Azure Resource](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal) to complete the configuration.

#### Configuring access using user-assigned managed identity

Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ cryptography==44.0.2
# azure-storage-queue
# msal
# pyjwt
dill==0.3.9
dill==0.4.0
# via pylint
exceptiongroup==1.2.2
# via pytest
Expand Down Expand Up @@ -130,11 +130,11 @@ msal-extensions==1.3.1
# via azure-identity
mypy-extensions==1.0.0
# via black
numpy==2.2.4
numpy==2.2.5
# via
# -r requirements.in
# pandas
packaging==24.2
packaging==25.0
# via
# ansible-compat
# ansible-core
Expand Down
4 changes: 2 additions & 2 deletions src/module_utils/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
]


FREEZE_FILESYSTEM = lambda file_system: [
FREEZE_FILESYSTEM = lambda file_system, mount_point: [
"mount",
"-o",
"ro",
file_system,
"/hana/shared",
mount_point,
]

PACEMAKER_STATUS = ["systemctl", "is-active", "pacemaker"]
Expand Down
20 changes: 14 additions & 6 deletions src/modules/check_indexserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,20 @@ def check_indexserver(self) -> None:
}
},
],
"suse": {
"[ha_dr_provider_suschksrv]": {
"provider": "susChkSrv",
"path": "/usr/share/SAPHanaSR",
}
},
"suse": [
{
"[ha_dr_provider_suschksrv]": {
"provider": "susChkSrv",
"path": "/usr/share/SAPHanaSR",
},
},
{
"[ha_dr_provider_suschksrv]": {
"provider": "susChkSrv",
"path": "/hana/shared/myHooks",
}
},
],
}

os_props_list = expected_properties.get(self.os_distribution)
Expand Down
32 changes: 18 additions & 14 deletions src/modules/filesystem_freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""

import logging
from typing import Dict, Any
from typing import Dict, Any, Tuple
from ansible.module_utils.basic import AnsibleModule

try:
Expand Down Expand Up @@ -94,12 +94,14 @@ def __init__(self, database_sid: str) -> None:
super().__init__()
self.database_sid = database_sid

def _find_filesystem(self) -> str:
def _find_filesystem(self) -> Tuple[str, str]:
"""
Find the filesystem mounted on /hana/shared.
This method reads the /proc/mounts file to identify the filesystem.
It returns the filesystem device and the mount point as /hana/shared.

:return: The filesystem mounted on /hana/shared.
:rtype: str
:rtype: Tuple[str, str]
"""
try:
with open("/proc/mounts", "r", encoding="utf-8") as mounts_file:
Expand All @@ -109,10 +111,10 @@ def _find_filesystem(self) -> str:
"/hana/shared",
f"/hana/shared/{self.database_sid}",
]:
return parts[0]
return parts[0], "/hana/shared"
except FileNotFoundError as ex:
self.handle_error(ex)
return None
return None, None

def run(self) -> Dict[str, Any]:
"""
Expand All @@ -121,22 +123,24 @@ def run(self) -> Dict[str, Any]:
:return: A dictionary containing the result of the test case.
:rtype: Dict[str, Any]
"""
file_system = self._find_filesystem()
file_system, mount_point = self._find_filesystem()

self.log(
logging.INFO,
f"Found the filesystem mounted on /hana/shared: {file_system}",
)

if file_system:
read_only_output = self.execute_command_subprocess(FREEZE_FILESYSTEM(file_system))
if file_system and mount_point:
self.log(
logging.INFO,
f"Found the filesystem mounted on: {file_system} at {mount_point}",
)
read_only_output = self.execute_command_subprocess(
FREEZE_FILESYSTEM(file_system, mount_point)
)
self.log(logging.INFO, read_only_output)
self.result.update(
{
"changed": True,
"message": "The file system (/hana/shared) was successfully mounted read-only.",
"message": f"The file system ({mount_point}) was mounted read-only.",
"status": TestStatus.SUCCESS.value,
"details": read_only_output,
"mount_point": mount_point,
}
)
else:
Expand Down
37 changes: 21 additions & 16 deletions src/modules/get_pcmk_properties_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ class HAClusterValidator(SapAutomationQA):
CONSTRAINTS_CATEGORIES = (".//*", "CONSTRAINTS_DEFAULTS")

RESOURCE_CATEGORIES = {
"stonith": ".//primitive[@class='stonith']",
"sbd_stonith": ".//primitive[@type='external/sbd']",
"fence_agent": ".//primitive[@type='fence_azure_arm']",
"topology": ".//clone/primitive[@type='SAPHanaTopology']",
"topology_meta": ".//clone/meta_attributes",
"hana": ".//master/primitive[@type='SAPHana']",
Expand Down Expand Up @@ -242,12 +243,9 @@ def _get_resource_expected_value(self, resource_type, section, param_name, op_na
:return: The expected value for the resource configuration parameter.
:rtype: str
"""
resource_defaults = self.constants["RESOURCE_DEFAULTS"].get(self.os_type, {})

if resource_type == "stonith":
resource_defaults = resource_defaults.get("stonith", {}).get(self.fencing_mechanism, {})
else:
resource_defaults = resource_defaults.get(resource_type, {})
resource_defaults = (
self.constants["RESOURCE_DEFAULTS"].get(self.os_type, {}).get(resource_type, {})
)

if section == "meta_attributes":
return resource_defaults.get("meta_attributes", {}).get(param_name)
Expand Down Expand Up @@ -333,16 +331,20 @@ def _parse_nvpair_elements(self, elements, category, subcategory=None, op_name=N
"""
parameters = []
for nvpair in elements:
parameters.append(
self._create_parameter(
category=category,
subcategory=subcategory,
op_name=op_name,
id=nvpair.get("id", ""),
name=nvpair.get("name", ""),
value=nvpair.get("value", ""),
name = nvpair.get("name", "")
if name in ["passwd", "password", "login"]:
continue
else:
parameters.append(
self._create_parameter(
category=category,
subcategory=subcategory,
op_name=op_name,
id=nvpair.get("id", ""),
name=name,
value=nvpair.get("value", ""),
)
)
)
return parameters

def _parse_os_parameters(self):
Expand Down Expand Up @@ -404,6 +406,9 @@ def _parse_global_ini_parameters(self):

for param_name, expected_value in global_ini_defaults.items():
value = global_ini_properties.get(param_name, "")
if isinstance(expected_value, list):
if value in expected_value:
expected_value = value
parameters.append(
self._create_parameter(
category="global_ini",
Expand Down
22 changes: 13 additions & 9 deletions src/modules/get_pcmk_properties_scs.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,16 +327,20 @@ def _parse_nvpair_elements(self, elements, category, subcategory=None, op_name=N
"""
parameters = []
for nvpair in elements:
parameters.append(
self._create_parameter(
category=category,
subcategory=subcategory,
op_name=op_name,
id=nvpair.get("id", ""),
name=nvpair.get("name", ""),
value=nvpair.get("value", ""),
name = nvpair.get("name", "")
if name in ["passwd", "password", "login"]:
continue
else:
parameters.append(
self._create_parameter(
category=category,
subcategory=subcategory,
op_name=op_name,
id=nvpair.get("id", ""),
name=name,
value=nvpair.get("value", ""),
)
)
)
return parameters

def _parse_resource(self, element, category):
Expand Down
5 changes: 0 additions & 5 deletions src/roles/ha_db_hana/tasks/azure-lb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
- name: "Pre Validations: Validate the Azure Load Balancer config"
become: true
block:
- name: "Install azure management network package"
ansible.builtin.pip:
name: "azure-mgmt-network"
state: present

- name: "Retrieve Subscription ID and Resource Group Name"
ansible.builtin.uri:
url: http://169.254.169.254/metadata/instance?api-version=2021-02-01
Expand Down
2 changes: 1 addition & 1 deletion src/roles/ha_db_hana/tasks/block-network.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
delegate_to: localhost
ansible.builtin.shell: |
for i in $(seq 1 30); do
if ! ping -c 1 -w 1 {{ ansible_host }}; then
if ! nc -zv -w1 {{ ansible_host }} {{ sap_port_to_ping }}; then
echo "Connection failed on attempt $i"
exit 1
fi
Expand Down
99 changes: 50 additions & 49 deletions src/roles/ha_db_hana/tasks/files/constants.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ VALID_CONFIGS:
SUSE: {}
AFA:
have-watchdog: "false"
stonith-timeout: "900"
stonith-timeout: "900s"
ISCSI:
have-watchdog: "true"
stonith-timeout: "144s"
Expand All @@ -57,30 +57,31 @@ VALID_CONFIGS:
# cibadmin --query --scope resources
RESOURCE_DEFAULTS:
SUSE:
stonith:
AFA:
instance_attributes:
pcmk_delay_max: "30s"
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "3600"
ISCSI:
instance_attributes:
pcmk_delay_max: "30s"
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "600"
timeout: "15"
fence_agent:
instance_attributes:
pcmk_delay_max: "15"
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "3600"
timeout: "120"

sbd_stonith:
instance_attributes:
pcmk_delay_max: "15"
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "600"
timeout: "15"

topology:
meta_attributes:
Expand Down Expand Up @@ -151,29 +152,29 @@ RESOURCE_DEFAULTS:
resource-stickiness: "0"

REDHAT:
stonith:
AFA:
instance_attributes:
pcmk_delay_max: "30s"
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "3600"
ISCSI:
instance_attributes:
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "600"
timeout: "15"
fence_agent:
instance_attributes:
pcmk_delay_max: "15"
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "3600"

sbd_stonith:
instance_attributes:
pcmk_monitor_retries: "4"
pcmk_action_limit: "3"
pcmk_reboot_timeout: "900"
power_timeout: "240"
pcmk_monitor_timeout: "120"
operations:
monitor:
interval: "600"
timeout: "15"

topology:
meta_attributes:
Expand Down Expand Up @@ -285,7 +286,7 @@ OS_PARAMETERS:
GLOBAL_INI:
SUSE:
provider: "SAPHanaSR"
path: "/usr/share/SAPHanaSR"
path: ["/usr/share/SAPHanaSR", "/hana/shared/myHooks"]
execution_order: "1"

REDHAT:
Expand Down
Loading