diff --git a/roles/sap_ha_pacemaker_cluster/defaults/main.yml b/roles/sap_ha_pacemaker_cluster/defaults/main.yml index b5d88e74d..dfe183bfa 100644 --- a/roles/sap_ha_pacemaker_cluster/defaults/main.yml +++ b/roles/sap_ha_pacemaker_cluster/defaults/main.yml @@ -160,9 +160,19 @@ sap_ha_pacemaker_cluster_hana_hook_chksrv: false # SAP Hana global.ini path calculated from SID sap_ha_pacemaker_cluster_hana_global_ini_path: '' # Default: /usr/sap//SYS/global/hdb/custom/config/global.ini -# Disable auto-detection of SAPHanaSR-angi package and use Classic +# SAP Hana nameserver.ini path calculated from SID +sap_ha_pacemaker_cluster_hana_nameserver_ini_path: '' # Default: /usr/sap//SYS/global/hdb/custom/config/nameserver.ini + +# (angi): Disable auto-detection of SAPHanaSR-angi package and use Classic sap_ha_pacemaker_cluster_saphanasr_angi_detection: true +# (angi): Enable SAPHanaFilesystem resource creation +sap_ha_pacemaker_cluster_hana_create_filesystem_resource: true + +# Optional: Define a node as a majority-maker node. +# This node is excluded from SAP resources setup. +sap_ha_pacemaker_cluster_quorum_majority_maker_node: '' + ################################################################################ # NetWeaver generic definitions ################################################################################ diff --git a/roles/sap_ha_pacemaker_cluster/handlers/main.yml b/roles/sap_ha_pacemaker_cluster/handlers/main.yml index 22db7dda0..03ae4498d 100644 --- a/roles/sap_ha_pacemaker_cluster/handlers/main.yml +++ b/roles/sap_ha_pacemaker_cluster/handlers/main.yml @@ -4,3 +4,18 @@ ansible.builtin.systemd_service: daemon_reload: true listen: "systemd daemon-reload" + + +# TODO: this is currently not working: +# stderr: '/usr/sap/RH1/HDB02/exe/hdbnsutil: error while loading shared libraries: libhdbns.so: +# cannot open shared object file: No such file or directory' + +#- name: "Reload HANA HA/DR providers" +# become: true +# become_user: "{{ sap_ha_pacemaker_cluster_hana_sid | lower }}adm" +# ansible.builtin.command: +# argv: +# - "/usr/sap/{{ sap_ha_pacemaker_cluster_hana_sid }}/HDB{{ sap_ha_pacemaker_cluster_hana_instance_nr }}/exe/hdbnsutil" +# - -reloadHADRProviders +# changed_when: false +# listen: "reload HADR Providers" diff --git a/roles/sap_ha_pacemaker_cluster/meta/argument_specs.yml b/roles/sap_ha_pacemaker_cluster/meta/argument_specs.yml index 8fabd4602..e86d651fe 100644 --- a/roles/sap_ha_pacemaker_cluster/meta/argument_specs.yml +++ b/roles/sap_ha_pacemaker_cluster/meta/argument_specs.yml @@ -132,7 +132,7 @@ argument_specs: # - hana_scaleup_costopt - hana_scaleup_perf # - hana_scaleup_perf_dr -# - hana_scaleout + - hana_scaleout - nwas_abap_ascs_ers # - nwas_abap_pas_aas - nwas_java_scs_ers @@ -340,6 +340,10 @@ argument_specs: - name: crypto_cipher value: aes256 + sap_ha_pacemaker_cluster_quorum_majority_maker_node: + description: + - Define a host name that is configured only as a majority-maker node. + - This is an optional host, typically in HANA scale-out HA environments, to add an empty cluster member for the purpose of adding a quorum vote to the otherwise even number of hosts. ########################################################################## # Parameters that are optionally imported from 'ha_cluster' LSR parameters @@ -589,13 +593,25 @@ argument_specs: description: - Path with location of global.ini for srHook update + sap_ha_pacemaker_cluster_hana_nameserver_ini_path: + default: "/usr/sap//SYS/global/hdb/custom/config/nameserver.ini" + description: + - Path with the location of the nameserver.ini for scale-out updates. + sap_ha_pacemaker_cluster_saphanasr_angi_detection: + type: bool default: true description: - Disabling this variable enables to use Classic SAPHanaSR agents even on server, where SAPHanaSR-angi is available. - Value `false` (Classic) is ignored when only SAPHanaSR-angi packages are available. + sap_ha_pacemaker_cluster_hana_create_filesystem: + type: bool + default: true + description: + - Controls if the SAPHanaFileystem resource is created in an 'angi' setup. + ########################################################################## # NetWeaver specific parameters ########################################################################## diff --git a/roles/sap_ha_pacemaker_cluster/tasks/RedHat/post_steps_hana.yml b/roles/sap_ha_pacemaker_cluster/tasks/RedHat/post_steps_hana.yml new file mode 100644 index 000000000..fbc4d58bc --- /dev/null +++ b/roles/sap_ha_pacemaker_cluster/tasks/RedHat/post_steps_hana.yml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# Starting SAPHana clone immediately after cluster configuration can lead to +# HANA shutdown. Following steps will leave enough time for resource agents +# to load HANA configuration before disabling maintenance. +# +# TODO: +# Add RedHat specific steps to mitigate issues with abrupt start of cluster. + +- name: "SAP HA Install Pacemaker - (SAPHana*) pcs resource cleanup" + ansible.builtin.command: + cmd: pcs resource cleanup {{ __sap_ha_pacemaker_cluster_hanacontroller_resource_name + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) + else __sap_ha_pacemaker_cluster_hana_resource_name }} + changed_when: true + +- name: "SAP HA Install Pacemaker - (SAPHana* clone) pcs resource refresh" + ansible.builtin.command: + cmd: pcs resource refresh {{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) + else __sap_ha_pacemaker_cluster_hana_resource_clone_name }} + changed_when: true + +# Sleep 30 is added to leave enough time for agents to load data from HANA. +# TODO: Add detection for Idle HANA, to ensure that Resource Agents loaded data. +- name: "SAP HA Install Pacemaker - Sleep wait for SAP HANA to become idle" + ansible.builtin.command: + cmd: sleep {{ 1 if ansible_check_mode else 30 }} + changed_when: false + +- name: "SAP HA Install Pacemaker - (SAPHana* clone) Remove resource maintenance" + ansible.builtin.command: + cmd: pcs resource meta {{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) + else __sap_ha_pacemaker_cluster_hana_resource_clone_name }} maintenance= + changed_when: true diff --git a/roles/sap_ha_pacemaker_cluster/tasks/RedHat/post_steps_hana_scaleup.yml b/roles/sap_ha_pacemaker_cluster/tasks/RedHat/post_steps_hana_scaleup.yml deleted file mode 100644 index cc2d20a1c..000000000 --- a/roles/sap_ha_pacemaker_cluster/tasks/RedHat/post_steps_hana_scaleup.yml +++ /dev/null @@ -1,36 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- -# Starting SAPHana clone immediately after cluster configuration can lead to -# HANA shutdown. Following steps will leave enough time for resource agents -# to load HANA configuration before disabling maintenance. -# -# TODO: -# Add RedHat specific steps to mitigate issues with abrupt start of cluster. - -- name: "SAP HA Install Pacemaker - (SAPHana) pcs resource cleanup" - ansible.builtin.command: - cmd: pcs resource cleanup {{ __sap_ha_pacemaker_cluster_hana_resource_name - if not __sap_ha_pacemaker_cluster_saphanasr_angi_available - else __sap_ha_pacemaker_cluster_hanacontroller_resource_name }} - changed_when: true - -- name: "SAP HA Install Pacemaker - (SAPHana clone) pcs resource refresh" - ansible.builtin.command: - cmd: pcs resource refresh {{ __sap_ha_pacemaker_cluster_hana_resource_clone_name - if not __sap_ha_pacemaker_cluster_saphanasr_angi_available - else __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name }} - changed_when: true - -# Sleep 30 is added to leave enough time for agents to load data from HANA. -# TODO: Add detection for Idle HANA, to ensure that Resource Agents loaded data. -- name: "SAP HA Install Pacemaker - Sleep wait for SAP HANA to become idle" - ansible.builtin.command: - cmd: sleep 30 - changed_when: false - -- name: "SAP HA Install Pacemaker - (SAPHana clone) Remove resource maintenance" - ansible.builtin.command: - cmd: pcs resource meta {{ __sap_ha_pacemaker_cluster_hana_resource_clone_name - if not __sap_ha_pacemaker_cluster_saphanasr_angi_available - else __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name }} maintenance= - changed_when: true diff --git a/roles/sap_ha_pacemaker_cluster/tasks/RedHat/pre_steps_hana.yml b/roles/sap_ha_pacemaker_cluster/tasks/RedHat/pre_steps_hana.yml index ac5f90234..78590789d 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/RedHat/pre_steps_hana.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/RedHat/pre_steps_hana.yml @@ -55,3 +55,18 @@ when: - __sap_ha_pacemaker_cluster_saphanasr_angi_check is defined - __sap_ha_pacemaker_cluster_saphanasr_angi_check.rc == 0 + + +# Make sure that "Autostart" is disabled in the HANA profiles. +# The profile path is '/hana/shared//profile/_HDB_'. +- name: "SAP HA Prepare Pacemaker - Disable 'Autostart' in the HANA instance profiles" + ansible.builtin.replace: + path: "/hana/shared/{{ sap_ha_pacemaker_cluster_hana_sid }}/profile/{{ sap_ha_pacemaker_cluster_hana_sid }}_HDB{{ sap_ha_pacemaker_cluster_hana_instance_nr }}_{{ ansible_hostname }}" + backup: true + regexp: 'Autostart\s*=\s*1' + replace: 'Autostart = 0' + # Throttle and retry loop was added to combat NFS write lockups on Azure NFS + throttle: 1 + retries: "{{ 1 if ansible_check_mode else 30 }}" + delay: "{{ 1 if ansible_check_mode else 10 }}" + ignore_errors: "{{ ansible_check_mode }}" diff --git a/roles/sap_ha_pacemaker_cluster/tasks/ascertain_sap_landscape.yml b/roles/sap_ha_pacemaker_cluster/tasks/ascertain_sap_landscape.yml index c5aa9e643..8a580faa4 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/ascertain_sap_landscape.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/ascertain_sap_landscape.yml @@ -32,6 +32,37 @@ when: - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup') | length > 0 +# Majority-maker: The role does not handle the simultaneous setup of a quorum-only node. +- name: "SAP HA Prepare Pacemaker - Fail if the majority-maker node is in the play hosts list" + ansible.builtin.assert: + that: + - sap_ha_pacemaker_cluster_quorum_majority_maker_node not in ansible_play_hosts + fail_msg: | + This role does not handle the simultaneous setup of SAP hosts and a quorum-only + cluster node, also called 'majority-maker'. + + Remove the majority-maker node from the target hosts of the playbook run. + when: + - sap_ha_pacemaker_cluster_quorum_majority_maker_node | length > 0 + +# Scale-out +- name: "SAP HA Prepare Pacemaker - Verify that for 'hana_scaleout' types a minimum of 4 HANA hosts is used" + ansible.builtin.assert: + that: + - ansible_play_hosts | difference(sap_ha_pacemaker_cluster_quorum_majority_maker_node | split(',')) | length > 3 + fail_msg: | + There are less than 4 HANA target hosts available for a scale-out setup. + + Play hosts: + {{ ansible_play_hosts | to_nice_yaml }} + Excluded majority-maker hosts: {{ sap_ha_pacemaker_cluster_quorum_majority_maker_node }} + + Available hosts: + {{ ansible_play_hosts | difference(sap_ha_pacemaker_cluster_quorum_majority_maker_node | split(',')) | to_nice_yaml }} + when: + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0 + + # Host type rules: # - there can only be 0 or 1 HANA type in the list # - there can only be 0 or 1 NW (A)SCS/ERS type in the list diff --git a/roles/sap_ha_pacemaker_cluster/tasks/configure_srhook.yml b/roles/sap_ha_pacemaker_cluster/tasks/configure_srhook.yml index 54ea2285f..5181e5636 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/configure_srhook.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/configure_srhook.yml @@ -46,7 +46,7 @@ path: "{{ __sap_ha_pacemaker_cluster_hana_global_ini_path }}" marker: "" block: | - [ha_dr_provider_{{ srhook_item.provider }}] + [ha_dr_provider_{{ __hook_classname }}] provider = {{ srhook_item.provider }} path = {{ srhook_item.path }} {% for option in srhook_item.options | d([]) -%} @@ -56,8 +56,13 @@ loop_control: loop_var: srhook_item label: "{{ srhook_item.provider }}" - when: "('[ha_dr_provider_' + srhook_item.provider + ']') | lower + when: "('[ha_dr_provider_' + __hook_classname + ']') | lower not in __sap_ha_pacemaker_cluster_global_ini_contents.stdout | lower" + vars: + __hook_classname: + "{{ srhook_item.provider | lower + if ansible_os_family == 'RedHat' + else srhook_item.provider }}" # Separate task to create [trace] block so hooks can be appended to it - name: "SAP HA Pacemaker srHook - Add [trace] block in global.ini" @@ -74,14 +79,19 @@ ansible.builtin.lineinfile: path: "{{ __sap_ha_pacemaker_cluster_hana_global_ini_path }}" insertafter: "^\\[trace\\]" - line: "ha_dr_{{ srhook_item.provider }} = info" + line: "ha_dr_{{ __hook_classname }} = info" loop: "{{ __sap_ha_pacemaker_cluster_hana_hooks }}" loop_control: loop_var: srhook_item label: "{{ srhook_item.provider }}" when: - - "('ha_dr_' + srhook_item.provider + ' = info') | lower + - "('ha_dr_' + __hook_classname + ' = info') | lower not in __sap_ha_pacemaker_cluster_global_ini_contents.stdout | lower" + vars: + __hook_classname: + "{{ srhook_item.provider | lower + if ansible_os_family == 'RedHat' + else srhook_item.provider }}" # jinja2 template contains logic to add extra entries if: # TkOver hook is present or SAPHanaSR-angi is used. @@ -92,5 +102,9 @@ mode: "0440" owner: root group: root - src: templates/sudofile_20-saphana.j2 + src: templates/sudofile_20-saphana_{{ __sudofile_suffix }}.j2 validate: visudo -cf %s + vars: + __sudofile_suffix: + "{{ 'angi_' if __sap_ha_pacemaker_cluster_saphanasr_angi_available + else '' }}{{ ansible_os_family }}" diff --git a/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleout.yml b/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleout.yml index f72bcae17..132f40583 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleout.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleout.yml @@ -1,14 +1,218 @@ # SPDX-License-Identifier: Apache-2.0 --- -# Variables containing variables must be constructed with values -# to be fed into an included role +- name: "SAP HA Prepare Pacemaker - Add resource: SAP HANA Topology" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_resource_primitives: "{{ __sap_ha_pacemaker_cluster_resource_primitives + [__resource_hana_topology] }}" + vars: + __resource_hana_topology: + id: "{{ __sap_ha_pacemaker_cluster_hana_topology_resource_name }}" + agent: "{{ __sap_ha_pacemaker_cluster_resource_agents.saphanatopology }}" + instance_attrs: + - attrs: + - name: SID + value: "{{ __sap_ha_pacemaker_cluster_hana_sid }}" + - name: InstanceNumber + value: "{{ __sap_ha_pacemaker_cluster_hana_instance_nr }}" + operations: + - action: start + attrs: + - name: timeout + value: 600 + - action: stop + attrs: + - name: timeout + value: 300 + - action: monitor + attrs: + - name: interval + value: 30 + - name: timeout + value: 300 + when: + - __resource_hana_topology.agent not in (__sap_ha_pacemaker_cluster_resource_primitives | map(attribute='agent')) -# TODO: add here any scale-out special variable constructions -# Make sure to first respect 'ha_cluster' native variables -# - name: "SAP HA Prepare Pacemaker - Construct cluster vars for SAP HANA Scale-out" -# ansible.builtin.set_fact: +- name: "SAP HA Prepare Pacemaker - Add resource: SAP HANA DB" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_resource_primitives: "{{ __sap_ha_pacemaker_cluster_resource_primitives + [__resource_hana] }}" + vars: + __resource_hana: + id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_name }}" + agent: "{{ __sap_ha_pacemaker_cluster_resource_agents.saphanacontroller }}" + instance_attrs: + - attrs: + - name: SID + value: "{{ __sap_ha_pacemaker_cluster_hana_sid }}" + - name: InstanceNumber + value: "{{ __sap_ha_pacemaker_cluster_hana_instance_nr }}" + - name: AUTOMATED_REGISTER + value: "{{ sap_ha_pacemaker_cluster_hana_automated_register | string }}" + - name: DUPLICATE_PRIMARY_TIMEOUT + value: "{{ sap_ha_pacemaker_cluster_hana_duplicate_primary_timeout | string }}" + - name: PREFER_SITE_TAKEOVER + value: "{{ sap_ha_pacemaker_cluster_hana_prefer_site_takeover | string }}" + operations: + - action: start + attrs: + - name: timeout + value: 3600 + - action: stop + attrs: + - name: timeout + value: 3600 + - action: monitor + attrs: + - name: interval + value: 61 + - name: role + value: Unpromoted + - name: timeout + value: 700 + - action: monitor + attrs: + - name: interval + value: 60 + - name: role + value: Promoted + - name: timeout + value: 700 + - action: promote + attrs: + - name: timeout + value: 700 + - action: demote + attrs: + - name: timeout + value: 320 + meta_attrs: + - attrs: + - name: priority + value: 100 + when: + - __resource_hana.agent not in (__sap_ha_pacemaker_cluster_resource_primitives | map(attribute='agent')) -- name: "SAP HA Prepare Pacemaker - Info" - ansible.builtin.debug: - msg: "INFO: There is currently no Scale-out specific construction, in addition to the SAP HANA common definitions." +# The filesystem resource is only created when 'angi' detection is enabled +# and the 'angi' package is available. +- name: "SAP HA Prepare Pacemaker - Add resource: SAP HANA Filesystem" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_resource_primitives: "{{ __sap_ha_pacemaker_cluster_resource_primitives + [__resource_hana_filesystem] }}" + vars: + __resource_hana_filesystem: + id: "{{ __sap_ha_pacemaker_cluster_hana_filesystem_resource_name }}" + agent: "{{ __sap_ha_pacemaker_cluster_resource_agents.saphanafilesystem }}" + instance_attrs: + - attrs: + - name: SID + value: "{{ __sap_ha_pacemaker_cluster_hana_sid }}" + - name: InstanceNumber + value: "{{ __sap_ha_pacemaker_cluster_hana_instance_nr }}" + - name: ON_FAIL_ACTION + value: fence + operations: + - action: start + attrs: + - name: interval + value: 0 + - name: timeout + value: 10 + - action: stop + attrs: + - name: interval + value: 0 + - name: timeout + value: 20 + - action: monitor + attrs: + - name: interval + value: 120 + - name: timeout + value: 180 + when: + - __resource_hana_filesystem.agent not in (__sap_ha_pacemaker_cluster_resource_primitives | map(attribute='agent')) + - sap_ha_pacemaker_cluster_hana_create_filesystem_resource + - sap_ha_pacemaker_cluster_saphanasr_angi_detection + - __sap_ha_pacemaker_cluster_saphanasr_angi_available + + +- name: "SAP HA Prepare Pacemaker - Add resource clone: SAP HANA Topology" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_resource_clones: "{{ __sap_ha_pacemaker_cluster_resource_clones + [__clone_hana_topology] }}" + vars: + __clone_hana_topology: + id: "{{ __sap_ha_pacemaker_cluster_hana_topology_resource_clone_name }}" + resource_id: "{{ __sap_ha_pacemaker_cluster_hana_topology_resource_name }}" + meta_attrs: + - attrs: + - name: clone-max + value: "{{ __sap_ha_pacemaker_cluster_meta_clone_max }}" + - name: clone-node-max + value: 1 + - name: interleave + value: "true" + when: + - __clone_hana_topology.resource_id not in (__sap_ha_pacemaker_cluster_resource_clones | map(attribute='resource_id')) + + +- name: "SAP HA Prepare Pacemaker - Add resource clone: SAP HANA Controller" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_resource_clones: + "{{ __sap_ha_pacemaker_cluster_resource_clones + [__clone_hana] }}" + vars: + __clone_hana: + id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name }}" + resource_id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_name }}" + meta_attrs: + - attrs: + - name: clone-max + value: "{{ __sap_ha_pacemaker_cluster_meta_clone_max }}" + - name: clone-node-max + value: 1 + - name: interleave + value: "true" + - name: promotable + value: "true" + - name: maintenance + value: "true" + when: + - __clone_hana.resource_id not in (__sap_ha_pacemaker_cluster_resource_clones | map(attribute='resource_id')) + +- name: "SAP HA Prepare Pacemaker - Add resource clone: SAP HANA Filesystem" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_resource_clones: "{{ __sap_ha_pacemaker_cluster_resource_clones + [__clone_hana_filesystem] }}" + vars: + __clone_hana_filesystem: + id: "{{ __sap_ha_pacemaker_cluster_hana_filesystem_resource_clone_name }}" + resource_id: "{{ __sap_ha_pacemaker_cluster_hana_filesystem_resource_name }}" + meta_attrs: + - attrs: + - name: clone-max + value: "{{ __sap_ha_pacemaker_cluster_meta_clone_max }}" + - name: clone-node-max + value: 1 + - name: interleave + value: "true" + when: + - __clone_hana_filesystem.resource_id not in (__sap_ha_pacemaker_cluster_resource_clones | map(attribute='resource_id')) + - sap_ha_pacemaker_cluster_hana_create_filesystem_resource + - sap_ha_pacemaker_cluster_saphanasr_angi_detection + - __sap_ha_pacemaker_cluster_saphanasr_angi_available + +# First start Topology, then HANA (automatically stops in reverse order) +- name: "SAP HA Prepare Pacemaker - Add order constraint: Topology starts before DB" + ansible.builtin.set_fact: + __sap_ha_pacemaker_cluster_constraints_order: + "{{ __sap_ha_pacemaker_cluster_constraints_order + [__constraint_order_hana_topology] }}" + vars: + __constraint_order_hana_topology: + id: "{{ __sap_ha_pacemaker_cluster_hana_order_topology_hana_name }}" + resource_first: + id: "{{ __sap_ha_pacemaker_cluster_hana_topology_resource_clone_name }}" + action: start + resource_then: + id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name }}" + action: start + options: + - name: symmetrical + value: "false" + when: + - __constraint_order_hana_topology.resource_then not in (__sap_ha_pacemaker_cluster_constraints_order | map(attribute='resource_then')) diff --git a/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleup_angi.yml b/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleup_angi.yml index 109535268..fd8c4107a 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleup_angi.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_hana_scaleup_angi.yml @@ -140,7 +140,7 @@ meta_attrs: - attrs: - name: clone-max - value: 2 + value: "{{ __sap_ha_pacemaker_cluster_meta_clone_max }}" - name: clone-node-max value: 1 - name: interleave @@ -160,7 +160,7 @@ meta_attrs: - attrs: - name: clone-max - value: 2 + value: "{{ __sap_ha_pacemaker_cluster_meta_clone_max }}" - name: clone-node-max value: 1 - name: interleave @@ -181,6 +181,8 @@ resource_id: "{{ __sap_ha_pacemaker_cluster_hana_filesystem_resource_name }}" meta_attrs: - attrs: + - name: clone-max + value: "{{ __sap_ha_pacemaker_cluster_meta_clone_max }}" - name: clone-node-max value: 1 - name: interleave diff --git a/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_vip_constraints_hana.yml b/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_vip_constraints_hana.yml index 1220d750b..e2c1747d8 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_vip_constraints_hana.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/construct_vars_vip_constraints_hana.yml @@ -10,7 +10,8 @@ id: "{{ __sap_ha_pacemaker_cluster_hana_order_hana_vip_primary_name }}" resource_first: id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name - if __sap_ha_pacemaker_cluster_saphanasr_angi_available + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) else __sap_ha_pacemaker_cluster_hana_resource_clone_name }}" action: promote resource_then: @@ -51,7 +52,8 @@ id: "{{ __sap_ha_pacemaker_cluster_hana_order_hana_vip_secondary_name }}" resource_first: id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name - if __sap_ha_pacemaker_cluster_saphanasr_angi_available + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) else __sap_ha_pacemaker_cluster_hana_resource_clone_name }}" action: start resource_then: @@ -94,7 +96,8 @@ resource_leader: # SAPHana is replaced by SAP HANA Controller for SAPHanaSR-angi id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name - if __sap_ha_pacemaker_cluster_saphanasr_angi_available + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) else __sap_ha_pacemaker_cluster_hana_resource_clone_name }}" # SUSE SAPHanaSR is using Master Slave clone using Master/Slave roles role: "{{ 'master' if ansible_os_family == 'Suse' and not __sap_ha_pacemaker_cluster_saphanasr_angi_available @@ -155,7 +158,8 @@ resource_leader: # SAPHana is replaced by SAP HANA Controller for SAPHanaSR-angi id: "{{ __sap_ha_pacemaker_cluster_hanacontroller_resource_clone_name - if __sap_ha_pacemaker_cluster_saphanasr_angi_available + if (__sap_ha_pacemaker_cluster_saphanasr_angi_available + or (sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0)) else __sap_ha_pacemaker_cluster_hana_resource_clone_name }}" # SUSE SAPHanaSR is using Master Slave clone using Master/Slave roles role: "{{ 'slave' if ansible_os_family == 'Suse' and not __sap_ha_pacemaker_cluster_saphanasr_angi_available diff --git a/roles/sap_ha_pacemaker_cluster/tasks/include_construct_vip_resources.yml b/roles/sap_ha_pacemaker_cluster/tasks/include_construct_vip_resources.yml index 6a5517cb4..9f849f4f1 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/include_construct_vip_resources.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/include_construct_vip_resources.yml @@ -16,6 +16,18 @@ sap_ha_pacemaker_cluster_healthcheck_hana_secondary_port } if sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup_perf') | length > 0 else omit }}" + hana_scaleout: "{{ + { + __sap_ha_pacemaker_cluster_vip_hana_primary_resource_name: + __sap_ha_pacemaker_cluster_vip_hana_primary_ip_address | regex_replace('/.*', ''), + __sap_ha_pacemaker_cluster_vip_hana_secondary_resource_name: + __sap_ha_pacemaker_cluster_vip_hana_secondary_ip_address | regex_replace('/.*', ''), + __sap_ha_pacemaker_cluster_healthcheck_hana_primary_resource_name: + sap_ha_pacemaker_cluster_healthcheck_hana_primary_port, + __sap_ha_pacemaker_cluster_healthcheck_hana_secondary_resource_name: + sap_ha_pacemaker_cluster_healthcheck_hana_secondary_port + } if sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0 else omit }}" + nwas_abap_ascs_ers: "{{ { __sap_ha_pacemaker_cluster_vip_nwas_ascs_resource_name: diff --git a/roles/sap_ha_pacemaker_cluster/tasks/include_vars_hana.yml b/roles/sap_ha_pacemaker_cluster/tasks/include_vars_hana.yml index e26aded48..9aa48d6ab 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/include_vars_hana.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/include_vars_hana.yml @@ -169,3 +169,14 @@ "{{ '/usr/sap/' ~ __sap_ha_pacemaker_cluster_hana_sid ~ '/SYS/global/hdb/custom/config/global.ini' if sap_ha_pacemaker_cluster_hana_global_ini_path | string | length == 0 else sap_ha_pacemaker_cluster_hana_global_ini_path }}" + + __sap_ha_pacemaker_cluster_hana_nameserver_ini_path: + "{{ '/usr/sap/' ~ __sap_ha_pacemaker_cluster_hana_sid ~ '/SYS/global/hdb/custom/config/nameserver.ini' + if sap_ha_pacemaker_cluster_hana_nameserver_ini_path | string | length == 0 + else sap_ha_pacemaker_cluster_hana_nameserver_ini_path }}" + + __sap_ha_pacemaker_cluster_meta_clone_max: + "{{ (ansible_play_hosts | length) - 1 + if (sap_ha_pacemaker_cluster_quorum_majority_maker_node | string | length > 0) + and (sap_ha_pacemaker_cluster_quorum_majority_maker_node in ansible_play_hosts) + else (ansible_play_hosts | length) | string }}" diff --git a/roles/sap_ha_pacemaker_cluster/tasks/main.yml b/roles/sap_ha_pacemaker_cluster/tasks/main.yml index a6a43c26c..ffbe761bd 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/main.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/main.yml @@ -89,6 +89,15 @@ - __sap_ha_pacemaker_cluster_saphanasr_angi_available tags: pre_ha_cluster +- name: "SAP HA Prepare Pacemaker - Include variable construction for SAP HANA Scale-out" + ansible.builtin.include_tasks: + file: construct_vars_hana_scaleout.yml + apply: + tags: pre_ha_cluster + when: + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0 + tags: pre_ha_cluster + # Common variables for Netweaver scenarios - name: "SAP HA Prepare Pacemaker - Include variable construction for SAP NetWeaver common" @@ -256,15 +265,28 @@ tags: pre_ha_cluster # Prerequisite changes for certain scenarios, if applicable - - name: "SAP HA Install Pacemaker - Include scenario specific prerequisites" + - name: "SAP HA Install Pacemaker - Include HANA scenario specific prerequisites" + ansible.builtin.include_tasks: + file: "{{ pre_hana_item }}" + apply: + tags: pre_ha_cluster + loop: + - pre_steps_hana.yml + loop_control: + loop_var: pre_hana_item + when: + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana') | length > 0 + tags: pre_ha_cluster + + - name: "SAP HA Install Pacemaker - Include NWAS scenario specific prerequisites" ansible.builtin.include_tasks: - file: "{{ pre_item }}" + file: "{{ pre_nwas_item }}" apply: tags: pre_ha_cluster loop: - pre_steps_nwas_cs_ers.yml loop_control: - loop_var: pre_item + loop_var: pre_nwas_item when: - sap_ha_pacemaker_cluster_host_type | select('search', 'nwas_.*_ers') | length > 0 tags: pre_ha_cluster @@ -364,11 +386,11 @@ # Graceful start of SAPHana clone to ensure resource agents are able to load configuration. - name: "SAP HA Install Pacemaker - Gracefully start SAP HANA cluster" ansible.builtin.include_tasks: - file: "{{ ansible_facts['os_family'] }}/post_steps_hana_scaleup.yml" + file: "{{ ansible_facts['os_family'] }}/post_steps_hana.yml" apply: tags: post_ha_cluster when: - - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup') | length > 0 + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana') | length > 0 run_once: true tags: post_ha_cluster diff --git a/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_gcp_ce_vm.yml b/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_gcp_ce_vm.yml index 8e92896d0..d18d7bc15 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_gcp_ce_vm.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_gcp_ce_vm.yml @@ -71,7 +71,7 @@ {{ sap_ha_pacemaker_cluster_healthcheck_hana_secondary_port }} {%- else %}0{%- endif %} when: - - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup') | length > 0 + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana') | length > 0 - name: "SAP HA Install Pacemaker - GCP CE VM - Define healthcheck details for NW ASCS/ERS" ansible.builtin.set_fact: @@ -122,7 +122,7 @@ loop_var: haproxy_item label: "{{ haproxy_item.name }}: {{ haproxy_item.port }}" when: - - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup') | length > 0 + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana') | length > 0 - haproxy_item.port | length > 4 diff --git a/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_ibmcloud_vs.yml b/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_ibmcloud_vs.yml index b7ce5a1cc..f3f22ec0d 100644 --- a/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_ibmcloud_vs.yml +++ b/roles/sap_ha_pacemaker_cluster/tasks/platform/preconfigure_cloud_ibmcloud_vs.yml @@ -93,7 +93,7 @@ {{ sap_ha_pacemaker_cluster_healthcheck_hana_secondary_port }} {%- else %}0{%- endif %} when: - - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup') | length > 0 + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana') | length > 0 - name: "SAP HA Install Pacemaker - IBM Cloud VS - Define healthcheck details for NW ASCS/ERS" ansible.builtin.set_fact: @@ -143,7 +143,7 @@ loop_var: haproxy_item label: "{{ haproxy_item.name }}: {{ haproxy_item.port }}" when: - - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleup') | length > 0 + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana') | length > 0 - haproxy_item.port | length > 4 - name: "SAP HA Install Pacemaker - IBM Cloud VS - Create haproxy config for NWAS ASCS/ERS instances" diff --git a/roles/sap_ha_pacemaker_cluster/tasks/pre_steps_hana.yml b/roles/sap_ha_pacemaker_cluster/tasks/pre_steps_hana.yml new file mode 100644 index 000000000..4a0064e25 --- /dev/null +++ b/roles/sap_ha_pacemaker_cluster/tasks/pre_steps_hana.yml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# Preconfiguration tasks for HANA servers. +# These tasks are run before the cluster setup. + +# BLOCK: +# - Scale-out only: remove alternative nameserver master nodes +- name: "SAP HA Pacemaker - Block to handle the nameserver configuration update" + when: + - sap_ha_pacemaker_cluster_host_type is defined + - sap_ha_pacemaker_cluster_host_type | select('search', 'hana_scaleout') | length > 0 + become: true + become_user: "{{ sap_ha_pacemaker_cluster_hana_sid | lower }}adm" + block: + + - name: "SAP HA Pacemaker - Stop the HANA instances" + ansible.builtin.command: + argv: + - /usr/sap/hostctrl/exe/sapcontrol + - -nr + - "{{ sap_ha_pacemaker_cluster_hana_instance_nr }}" + - -function + - StopSystem + #- HDB + register: __sap_ha_pacemaker_cluster_register_hana_stop + # Retry with short delay to allow for the hdbdaemon to be running first + retries: "{{ 1 if ansible_check_mode else 60 }}" + delay: "{{ 1 if ansible_check_mode else 5 }}" + until: __sap_ha_pacemaker_cluster_register_hana_stop.rc == 0 + changed_when: true + ignore_errors: "{{ ansible_check_mode }}" + + - name: "SAP HA Pacemaker - Wait until the local HANA instance is reported as stopped" + ansible.builtin.command: + argv: + - /usr/sap/hostctrl/exe/sapcontrol + - -nr + - "{{ sap_ha_pacemaker_cluster_hana_instance_nr }}" + - -function + - WaitforStopped + - "{{ 1 if ansible_check_mode else 600 }}" + - "{{ 1 if ansible_check_mode else 10 }}" + register: __sap_ha_pacemaker_cluster_register_hana_stop_wait + # Retry with short delay to allow for the hdbdaemon to be running first + retries: "{{ 1 if ansible_check_mode else 60 }}" + delay: "{{ 1 if ansible_check_mode else 5 }}" + until: __sap_ha_pacemaker_cluster_register_hana_stop_wait.rc == 0 + changed_when: false + check_mode: false + ignore_errors: "{{ ansible_check_mode }}" + + - name: "SAP HA Pacemaker - Remove alternative coordinator nameserver entries" + ansible.builtin.replace: + backup: true + path: "{{ __sap_ha_pacemaker_cluster_hana_nameserver_ini_path }}" + after: '[landscape]' + regexp: '^(master\s*=\s*\w*:\d*).*$' + replace: '\1' + # Throttle to run on one host at a time and retry loop to prevent NFS write lockups + throttle: 1 + retries: "{{ 1 if ansible_check_mode else 30 }}" + delay: "{{ 1 if ansible_check_mode else 10 }}" + ignore_errors: "{{ ansible_check_mode }}" + + - name: "SAP HA Pacemaker - Start the HANA instances" + ansible.builtin.command: + argv: + - /usr/sap/hostctrl/exe/sapcontrol + - -nr + - "{{ sap_ha_pacemaker_cluster_hana_instance_nr }}" + - -function + - StartSystem + #- HDB + register: __sap_ha_pacemaker_cluster_register_hana_start + # Retry with short delay to allow for the hdbdaemon to be running first + retries: "{{ 1 if ansible_check_mode else 60 }}" + delay: "{{ 1 if ansible_check_mode else 5 }}" + until: __sap_ha_pacemaker_cluster_register_hana_start.rc == 0 + changed_when: true + ignore_errors: "{{ ansible_check_mode }}" + + - name: "SAP HA Pacemaker - Wait until the local HANA instance is reported as running" + ansible.builtin.command: + argv: + - /usr/sap/hostctrl/exe/sapcontrol + - -nr + - "{{ sap_ha_pacemaker_cluster_hana_instance_nr }}" + - -function + - WaitforStarted + - "{{ 1 if ansible_check_mode else 600 }}" + - "{{ 1 if ansible_check_mode else 10 }}" + register: __sap_ha_pacemaker_cluster_register_hana_start_wait + # Retry with short delay to allow for the hdbdaemon to be running first + retries: "{{ 1 if ansible_check_mode else 60 }}" + delay: "{{ 1 if ansible_check_mode else 5 }}" + until: __sap_ha_pacemaker_cluster_register_hana_start_wait.rc == 0 + changed_when: false + check_mode: false + ignore_errors: "{{ ansible_check_mode }}" + +### END of BLOCK for nameserver setup. diff --git a/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_RedHat.j2 b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_RedHat.j2 new file mode 100644 index 000000000..ad6ebb9f2 --- /dev/null +++ b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_RedHat.j2 @@ -0,0 +1,14 @@ +# Managed by Ansible +# Role: {{ ansible_role_name }} +# +# Description: +# The following are sudo entries which are required for the pacemaker cluster +# to update the SAP HANA cluster resource status. + +# RHEL 9 and later by default prohibit sudo commands to be run from scripts without a real tty. +# For the HANA HA solution it is required to allow this functionality. +# This setting allows it for all {{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm user sudo commands. +Defaults:{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm !requiretty + +# Required: Allow the user to set and update cluster attributes for HANA resources. +{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm ALL=(ALL) NOPASSWD: /usr/sbin/crm_attribute -n hana_* diff --git a/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana.j2 b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_Suse.j2 similarity index 91% rename from roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana.j2 rename to roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_Suse.j2 index 3b2547842..7c81a1005 100644 --- a/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana.j2 +++ b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_Suse.j2 @@ -6,8 +6,8 @@ # to update the SAP HANA cluster resource status. {% for node in sap_ha_pacemaker_cluster_cluster_nodes %} -Cmnd_Alias {{ node.hana_site | upper }}_SOK = /usr/sbin/crm_attribute -n hana_{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}_site_srHook_{{ node.hana_site }} -v SOK -t crm_config -s {{ sap_ha_pacemaker_cluster_hadr_provider_name }} -Cmnd_Alias {{ node.hana_site | upper }}_SFAIL = /usr/sbin/crm_attribute -n hana_{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}_site_srHook_{{ node.hana_site }} -v SFAIL -t crm_config -s {{ sap_ha_pacemaker_cluster_hadr_provider_name }} +Cmnd_Alias {{ node.hana_site | upper }}_SOK = /usr/sbin/crm_attribute -n hana_{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}_site_srHook_{{ node.hana_site }} -v SOK -t crm_config -s SAPHanaSR +Cmnd_Alias {{ node.hana_site | upper }}_SFAIL = /usr/sbin/crm_attribute -n hana_{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}_site_srHook_{{ node.hana_site }} -v SFAIL -t crm_config -s SAPHanaSS {% endfor %} {% if __sap_ha_pacemaker_cluster_hana_hook_tkover and __sap_ha_pacemaker_cluster_saphanasr_angi_available %} Cmnd_Alias HOOK_HELPER = /usr/bin/SAPHanaSR-hookHelper --sid={{ __sap_ha_pacemaker_cluster_hana_sid | upper }} --case=checkTakeover diff --git a/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_angi_RedHat.j2 b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_angi_RedHat.j2 new file mode 100644 index 000000000..8d34cef6b --- /dev/null +++ b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_angi_RedHat.j2 @@ -0,0 +1,17 @@ +# Managed by Ansible +# Role: {{ ansible_role_name }} +# +# Description: +# The following are sudo entries which are required for the pacemaker cluster +# to update the SAP HANA cluster resource status. + +# RHEL 9 and later by default prohibit sudo commands to be run from scripts without a real tty. +# For the HANA HA solution it is required to allow this functionality. +# This setting allows it for all {{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm user sudo commands. +Defaults:{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm !requiretty + +# Required: Allow the user to set and update cluster attributes for HANA resources. +{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm ALL=(ALL) NOPASSWD: /usr/sbin/crm_attribute -n hana_* + +# Optional: Allow the user to execute the SAPHanaSR-hookHelper script for optional functionality of the HANA HA tools. +{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm ALL=(ALL) NOPASSWD: /usr/bin/SAPHanaSR-hookHelper diff --git a/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_angi_Suse.j2 b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_angi_Suse.j2 new file mode 100644 index 000000000..3d8b87c81 --- /dev/null +++ b/roles/sap_ha_pacemaker_cluster/templates/sudofile_20-saphana_angi_Suse.j2 @@ -0,0 +1,28 @@ +# Managed by Ansible +# Role: {{ ansible_role_name }} +# +# Description: +# The following are sudo entries which are required for the pacemaker cluster +# to update the SAP HANA cluster resource status. + +{% for node in sap_ha_pacemaker_cluster_cluster_nodes %} +Cmnd_Alias {{ node.hana_site | upper }}_SOK = /usr/sbin/crm_attribute -n hana_{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}_site_srHook_{{ node.hana_site }} -v SOK -t crm_config -s SAPHanaSR +Cmnd_Alias {{ node.hana_site | upper }}_SFAIL = /usr/sbin/crm_attribute -n hana_{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}_site_srHook_{{ node.hana_site }} -v SFAIL -t crm_config -s SAPHanaSR +{% endfor %} +{% if __sap_ha_pacemaker_cluster_hana_hook_tkover and __sap_ha_pacemaker_cluster_saphanasr_angi_available %} +Cmnd_Alias HOOK_HELPER = /usr/bin/SAPHanaSR-hookHelper --sid={{ __sap_ha_pacemaker_cluster_hana_sid | upper }} --case=checkTakeover + +{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm ALL=(ALL) NOPASSWD: {% for node in sap_ha_pacemaker_cluster_cluster_nodes %}{{ node.hana_site | upper }}_SOK, {{ node.hana_site | upper }}_SFAIL{{ ", " if not loop.last else "" }}{% endfor %}, HOOK_HELPER + +Defaults!{% for node in sap_ha_pacemaker_cluster_cluster_nodes %}{{ node.hana_site | upper }}_SOK, {{ node.hana_site | upper }}_SFAIL{{ ", " if not loop.last else "" }}{% endfor %}, HOOK_HELPER !requiretty +{% elif __sap_ha_pacemaker_cluster_hana_hook_tkover and not __sap_ha_pacemaker_cluster_saphanasr_angi_available %} +Cmnd_Alias HOOK_HELPER = /usr/sbin/SAPHanaSR-hookHelper --sid={{ __sap_ha_pacemaker_cluster_hana_sid | upper }} --case=checkTakeover + +{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm ALL=(ALL) NOPASSWD: {% for node in sap_ha_pacemaker_cluster_cluster_nodes %}{{ node.hana_site | upper }}_SOK, {{ node.hana_site | upper }}_SFAIL{{ ", " if not loop.last else "" }}{% endfor %}, HOOK_HELPER + +Defaults!{% for node in sap_ha_pacemaker_cluster_cluster_nodes %}{{ node.hana_site | upper }}_SOK, {{ node.hana_site | upper }}_SFAIL{{ ", " if not loop.last else "" }}{% endfor %}, HOOK_HELPER !requiretty +{% else %} +{{ __sap_ha_pacemaker_cluster_hana_sid | lower }}adm ALL=(ALL) NOPASSWD: {% for node in sap_ha_pacemaker_cluster_cluster_nodes %}{{ node.hana_site | upper }}_SOK, {{ node.hana_site | upper }}_SFAIL{{ ", " if not loop.last else "" }}{% endfor %} + +Defaults!{% for node in sap_ha_pacemaker_cluster_cluster_nodes %}{{ node.hana_site | upper }}_SOK, {{ node.hana_site | upper }}_SFAIL{{ ", " if not loop.last else "" }}{% endfor %} !requiretty +{% endif %} diff --git a/roles/sap_ha_pacemaker_cluster/vars/RedHat.yml b/roles/sap_ha_pacemaker_cluster/vars/RedHat.yml index f0c81c6ff..2c6da4e32 100644 --- a/roles/sap_ha_pacemaker_cluster/vars/RedHat.yml +++ b/roles/sap_ha_pacemaker_cluster/vars/RedHat.yml @@ -152,11 +152,38 @@ __sap_ha_pacemaker_cluster_hook_hana_scaleup_perf_angi: value: 2 - name: action_on_lost value: stop - - name: stop_timeout - value: 25 -__sap_ha_pacemaker_cluster_hook_hana_scaleout: [] -__sap_ha_pacemaker_cluster_hook_hana_scaleout_angi: [] +__sap_ha_pacemaker_cluster_hook_hana_scaleout: + saphanasr: + - provider: SAPHanaSR + path: /usr/share/SAPHanaSR-ScaleOut + options: + - name: execution_order + value: 1 + chksrv: + - provider: ChkSrv + path: /usr/share/SAPHanaSR-ScaleOut + options: + - name: execution_order + value: 2 + - name: action_on_lost + value: stop + +__sap_ha_pacemaker_cluster_hook_hana_scaleout_angi: + saphanasr: + - provider: HanaSR + path: /usr/share/sap-hana-ha/ + options: + - name: execution_order + value: 1 + chksrv: + - provider: ChkSrv + path: /usr/share/sap-hana-ha/ + options: + - name: execution_order + value: 2 + - name: action_on_lost + value: stop # Enable default OS recommended hooks sap_ha_pacemaker_cluster_hana_hook_tkover: false diff --git a/roles/sap_ha_pacemaker_cluster/vars/hana_scaleout.yml b/roles/sap_ha_pacemaker_cluster/vars/hana_scaleout.yml new file mode 100644 index 000000000..027014b80 --- /dev/null +++ b/roles/sap_ha_pacemaker_cluster/vars/hana_scaleout.yml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: Apache-2.0 +--- +# SAP HANA Scale-Out specific parameter values +# +# TODO: make sure to first respect 'ha_cluster' native variables + +# Extra package list is combination of: +# minimal base packages required for all scenarios +# scenario specific packages +__sap_ha_pacemaker_cluster_sap_extra_packages: "{{ + __sap_ha_pacemaker_cluster_sap_extra_packages_dict.minimal | d([]) + + (__sap_ha_pacemaker_cluster_sap_extra_packages_dict.hana_angi + if __sap_ha_pacemaker_cluster_saphanasr_angi_available + else __sap_ha_pacemaker_cluster_sap_extra_packages_dict.hana_scaleout) }}" + +# SUSE Specific: Combine list of zypper patterns +__sap_ha_pacemaker_cluster_sap_zypper_patterns: "{{ + __sap_ha_pacemaker_cluster_sap_zypper_patterns_dict.minimal | d([]) + + __sap_ha_pacemaker_cluster_sap_zypper_patterns_dict.hana_scaleout | d([]) }}" + +# Set variable with dictionary name based on angi availability +__sap_ha_pacemaker_cluster_hana_hook_dictionary: + "{{ '__sap_ha_pacemaker_cluster_hook_' + + (sap_ha_pacemaker_cluster_host_type | select('search', 'hana'))[0] + + ('_angi' if __sap_ha_pacemaker_cluster_saphanasr_angi_available else '') }}" + +# Recommended srhooks are set to true only if default dictionary is populated +__sap_ha_pacemaker_cluster_hana_hook_tkover: + "{{ true if + (lookup('ansible.builtin.vars', __sap_ha_pacemaker_cluster_hana_hook_dictionary).tkover + is defined and (sap_ha_pacemaker_cluster_hana_hook_tkover | bool)) + else false }}" +__sap_ha_pacemaker_cluster_hana_hook_chksrv: + "{{ true if + (lookup('ansible.builtin.vars', __sap_ha_pacemaker_cluster_hana_hook_dictionary).chksrv + is defined and (sap_ha_pacemaker_cluster_hana_hook_chksrv | bool)) + else false }}" + +# Combine final list of srhooks based on user input and angi availability +__sap_ha_pacemaker_cluster_hana_hooks: "{{ + lookup('ansible.builtin.vars', __sap_ha_pacemaker_cluster_hana_hook_dictionary).saphanasr + + (lookup('ansible.builtin.vars', __sap_ha_pacemaker_cluster_hana_hook_dictionary).tkover + | d([]) if __sap_ha_pacemaker_cluster_hana_hook_tkover else []) + + (lookup('ansible.builtin.vars', __sap_ha_pacemaker_cluster_hana_hook_dictionary).chksrv + | d([]) if __sap_ha_pacemaker_cluster_hana_hook_chksrv else []) + }}" diff --git a/roles/sap_ha_pacemaker_cluster/vars/hana_scaleout_perf.yml b/roles/sap_ha_pacemaker_cluster/vars/hana_scaleout_perf.yml deleted file mode 100644 index b26f2a626..000000000 --- a/roles/sap_ha_pacemaker_cluster/vars/hana_scaleout_perf.yml +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- -# SAP HANA Scale-Out specific parameter values -# -# TODO: make sure to first respect 'ha_cluster' native variables - -# Extra package list is combination of: -# minimal base packages required for all scenarios -# scenario specific packages -__sap_ha_pacemaker_cluster_sap_extra_packages: "{{ - __sap_ha_pacemaker_cluster_sap_extra_packages_dict.minimal | d([]) - + (__sap_ha_pacemaker_cluster_sap_extra_packages_dict.hana_angi - if __sap_ha_pacemaker_cluster_saphanasr_angi_available - else __sap_ha_pacemaker_cluster_sap_extra_packages_dict.hana_scaleout) }}" - -# SUSE Specific: Combine list of zypper patterns -__sap_ha_pacemaker_cluster_sap_zypper_patterns: "{{ - __sap_ha_pacemaker_cluster_sap_zypper_patterns_dict.minimal | d([]) - + __sap_ha_pacemaker_cluster_sap_zypper_patterns_dict.hana_scaleout | d([]) }}" - -sap_ha_pacemaker_cluster_hadr_provider_name: SAPHanaSR diff --git a/roles/sap_ha_pacemaker_cluster/vars/hana_scaleup_perf.yml b/roles/sap_ha_pacemaker_cluster/vars/hana_scaleup_perf.yml index 78f8d571a..551ee500b 100644 --- a/roles/sap_ha_pacemaker_cluster/vars/hana_scaleup_perf.yml +++ b/roles/sap_ha_pacemaker_cluster/vars/hana_scaleup_perf.yml @@ -44,7 +44,3 @@ __sap_ha_pacemaker_cluster_hana_hooks: "{{ + (lookup('ansible.builtin.vars', __sap_ha_pacemaker_cluster_hana_hook_dictionary).chksrv | d([]) if __sap_ha_pacemaker_cluster_hana_hook_chksrv else []) }}" - -# Define sap_ha_pacemaker_cluster_hadr_provider_name for jinja2 template -# SAPHanaSR-angi package is using same provider name as SAPHanaSR -sap_ha_pacemaker_cluster_hadr_provider_name: SAPHanaSR