diff --git a/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.1-set_runtime_facts.yml b/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.1-set_runtime_facts.yml index b9619b432..03c464e2b 100644 --- a/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.1-set_runtime_facts.yml +++ b/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.1-set_runtime_facts.yml @@ -92,6 +92,22 @@ saphanaSR_version: "{{ ansible_facts.packages['SAPHanaSR'][0].version if 'SAPHanaSR' in ansible_facts.packages else '0.0.0' }}" saphanaSR_angi_version: "{{ ansible_facts.packages['SAPHanaSR-angi'][0].version if 'SAPHanaSR-angi' in ansible_facts.packages else '0.0.0' }}" + - name: "5.5 HANA Pacemaker - Install SAPHanaSR package if not installed" + community.general.zypper: + name: "SAPHanaSR>=0.161.1_BF" + state: present + when: + - saphanaSR_version == '0.0.0' + - not use_hanasr_angi + + - name: "5.5 HANA Pacemaker - Install SAPHanaSR-angi package if not installed" + community.general.zypper: + name: SAPHanaSR-angi + state: present + when: + - saphanaSR_angi_version == '0.0.0' + - use_hanasr_angi + - distribution_full_id in ['sles_sap15.4', 'sles_sap15.5', 'sles_sap15.6'] # old code left here for backwards comaptibility - name: "5.5 HANA Pacemaker - Capture the Hana DB version" diff --git a/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.3-SAPHanaSR.yml b/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.3-SAPHanaSR.yml index 2e2d38e3c..a3942ec13 100644 --- a/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.3-SAPHanaSR.yml +++ b/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/tasks/5.5.3-SAPHanaSR.yml @@ -96,7 +96,8 @@ - name: HANA 2.0 only - Implement the classic Python system replication hook SAPHanaSR when: - - hdb_version[0:2] == "2." + - hana_version_ok + - basic_hook_check is success - not is_certified_for_hanasr_angi block: # Print validation summary report for debug @@ -162,7 +163,7 @@ owner: "{{ db_sid | lower }}adm" group: sapsys - - name: "5.5 HANA Pacemaker - Adjust global.ini on each cluster node" + - name: "5.5 HANA Pacemaker - Adjust global.ini on each cluster node (RHEL)" ansible.builtin.blockinfile: path: /hana/shared/{{ db_sid | upper }}/global/hdb/custom/config/global.ini block: | @@ -171,23 +172,30 @@ path = /hana/shared/myHooks execution_order = 1 + [ha_dr_provider_chksrv] + provider = ChkSrv + path = /hana/shared/myHooks + execution_order = 2 + action_on_lost = kill + [trace] ha_dr_saphanasr = info + ha_dr_chksrv = info when: - - suschk_hook_check is success + - ansible_os_family | upper == "REDHAT" - - name: "5.5 HANA Pacemaker - Adjust global.ini on each cluster node" + - name: "5.5 HANA Pacemaker - Adjust global.ini on each cluster node (SLES)" ansible.builtin.blockinfile: path: /hana/shared/{{ db_sid | upper }}/global/hdb/custom/config/global.ini block: | [ha_dr_provider_SAPHanaSR] provider = SAPHanaSR - path = /usr/share/SAPHanaSR + path = /hana/shared/myHooks execution_order = 1 [ha_dr_provider_suschksrv] provider = susChkSrv - path = /usr/share/SAPHanaSR + path = /hana/shared/myHooks execution_order = 3 action_on_lost = fence @@ -197,13 +205,23 @@ - suschk_hook_check is success - ansible_os_family | upper == "SUSE" - - name: "5.5 HANA Pacemaker - Create sudoers file for /etc/sudoers.d/20-saphana for SLES" + - name: "5.5 HANA Pacemaker - Create sudoers file 20-saphana for SLES" ansible.builtin.template: src: "20-saphana-suse.j2" dest: "/etc/sudoers.d/20-saphana" mode: "0440" owner: root group: root + when: ansible_os_family | upper == "SUSE" + + - name: "5.5 HANA Pacemaker - Create sudoers file 20-saphana for RHEL" + ansible.builtin.template: + src: "20-saphana-rhel.j2" + dest: "/etc/sudoers.d/20-saphana" + mode: "0440" + owner: root + group: root + when: ansible_os_family | upper == "REDHAT" - name: "5.5 HANA Pacemaker - Start HANA System on both nodes" become_user: "{{ db_sid | lower }}adm" @@ -293,7 +311,11 @@ - name: "HANA 2.0 SPS5 only Only on SLES 15 SP4 and greater - Implement the SAPHanaSR-angi Python system replication hook" when: - hana_version_ok + - basic_hook_check is success + - suschk_hook_check is success + - angi_hook_check is success - is_certified_for_hanasr_angi + - ansible_os_family | upper == "SUSE" # redundant, need to remove it later. block: # Summary Report - name: "5.5 HANA Pacemaker - Display validation summary" @@ -310,11 +332,34 @@ 2. SAPHanaSR-angi Python Hook: {{ 'PASSED' if angi_hook_check is success else 'FAILED' }} 3. susChkSrv Python Hook: {{ 'PASSED' if suschk_hook_check is success else 'FAILED' }} - # Note: The hook code updates automatically through OS updates or package updates. - # If you point parameter path to the default /usr/share/SAPHanaSR-angi location, - # the Python hook code updates automatically through OS updates or package updates. - # HANA uses the hook code updates when it next restarts. With an optional own path - # like /hana/shared/myHooks, you can decouple OS updates from the hook version that you use + # /*---------------------------------------------------------------------------8 + # Note: The hook code updates automatically through OS updates or package + # updates.If you point parameter path to the default /usr/share/SAPHanaSR-angi + # location, the Python hook code updates automatically through OS updates or + # package updates. + # + # HANA uses the hook code updates when it next restarts. With an optional own + # path like /hana/shared/myHooks, you can decouple OS updates from the hook + # version that you use + # /*---------------------------------------------------------------------------8 + # Decision: We will use the default path /usr/share/SAPHanaSR-angi. + # /*---------------------------------------------------------------------------8 + - name: "5.5 HANA Pacemaker - Stop HANA System on both nodes" + become_user: "{{ db_sid | lower }}adm" + become: true + ansible.builtin.command: "{{ sapcontrol_command }} -function StopSystem" + failed_when: false + changed_when: false + register: hana_system_stopped + + - name: "5.5 HANA Pacemaker - Wait 2 minutes for SAP system to stop" + ansible.builtin.wait_for: + timeout: 120 + delay: 10 + # host: "{{ inventory_hostname }}" + # port: "{{ hana_instance_port }}" + # state: stopped + - name: "5.5 HANA Pacemaker - Adjust global.ini on each cluster node" ansible.builtin.blockinfile: path: /hana/shared/{{ db_sid | upper }}/global/hdb/custom/config/global.ini @@ -333,11 +378,8 @@ [trace] ha_dr_sushanasr = info ha_dr_saphanasr = info - when: - - suschk_hook_check is success - - ansible_os_family | upper == "SUSE" - - name: "5.5 HANA Pacemaker - Create sudoers file for /etc/sudoers.d/20-saphana for SLES" + - name: "5.5 HANA Pacemaker - Create sudoers file for SLES" ansible.builtin.template: src: "20-saphana-suse.j2" dest: "/etc/sudoers.d/20-saphana" @@ -345,4 +387,149 @@ owner: root group: root -# End of configuration for SAPHanaSR python hook + - name: "5.5 HANA Pacemaker - Start HANA System" + block: + - name: "5.5 HANA Pacemaker - Start HANA System on both nodes" + ansible.builtin.command: "{{ sapcontrol_command }} -function StartSystem" + become: true + become_user: "{{ db_sid | lower }}adm" + register: hana_system_started + failed_when: hana_system_started.rc not in [0, 3] + changed_when: hana_system_started.rc == 0 + + - name: "5.5 HANA Pacemaker - Display start status" + ansible.builtin.debug: + msg: "SAP System start command executed successfully" + when: hana_system_started.rc == 0 + + rescue: + - name: "5.5 HANA Pacemaker - Handle HANA System start failure" + ansible.builtin.fail: + msg: | + Failed to start SAP system: + Return code: {{ hana_system_started.rc }} + stdout: {{ hana_system_started.stdout }} + stderr: {{ hana_system_started.stderr }} + when: hana_system_started.rc not in [0, 3] + + - name: "5.5 HANA Pacemaker - Start HANA Database" + ansible.builtin.import_tasks: ../../../roles-misc/0.4-helpers/tasks/04.01-start_hana.yml + + - name: "5.5 HANA Pacemaker - Pause to give HANA replication time to stabilize" + ansible.builtin.wait_for: + timeout: "{{ hsr_status_report_wait_in_s }}" + + - name: "5.5 HANA Pacemaker - Validate SAPHanaSR-angi Hook Configuration" + when: inventory_hostname == primary_instance_name + block: + # Step 1: Change to trace directory + - name: "5.5 HANA Pacemaker - Get trace directory path" + ansible.builtin.command: "cdtrace" + become: true + become_user: "{{ db_sid | lower }}adm" + register: cdtrace_result + changed_when: false + + # Step 2: Check SAPHanaSR-angi configuration + - name: "5.5 HANA Pacemaker - Check SAPHanaSR-angi load status" + ansible.builtin.shell: "grep 'HADR.*load.*susHanaSR' nameserver_*.trc" + args: + chdir: "{{ cdtrace_result.stdout }}" + become: true + become_user: "{{ db_sid | lower }}adm" + register: sushanasr_load + changed_when: false + failed_when: false + + - name: "5.5 HANA Pacemaker - Check SAPHanaSR-angi initialization" + ansible.builtin.shell: "grep 'susHanaSR.init' nameserver_*.trc" + args: + chdir: "{{ cdtrace_result.stdout }}" + become: true + become_user: "{{ db_sid | lower }}adm" + register: sushanasr_init + changed_when: false + failed_when: false + + # Step 3: Check susChkSrv.py configuration + - name: "5.5 HANA Pacemaker - Check susChkSrv.py load status" + ansible.builtin.shell: "grep 'HADR.*load.*susChkSrv' nameserver_*.trc" + args: + chdir: "{{ cdtrace_result.stdout }}" + become: true + become_user: "{{ db_sid | lower }}adm" + register: suschksrv_load + changed_when: false + failed_when: false + + - name: "5.5 HANA Pacemaker - Check susChkSrv.py initialization" + ansible.builtin.shell: "grep 'susChkSrv.init' nameserver_*.trc" + args: + chdir: "{{ cdtrace_result.stdout }}" + become: true + become_user: "{{ db_sid | lower }}adm" + register: suschksrv_init + changed_when: false + failed_when: false + + - name: "5.5 HANA Pacemaker - Check susChkSrv events" + ansible.builtin.shell: > + set -o pipefail + egrep '(LOST:|STOP:|START:|DOWN:|init|load|fail)' nameserver_suschksrv.trc" + args: + chdir: "{{ cdtrace_result.stdout }}" + become: true + become_user: "{{ db_sid | lower }}adm" + register: suschksrv_events + changed_when: false + failed_when: false + + # Step 4: Set validation results + - name: "5.5 HANA Pacemaker - Set hook configuration status" + ansible.builtin.set_fact: + hook_status: + susHanaSR: + loaded: "{{ (sushanasr_load.stdout | default('')) is search('HADR.*load.*susHanaSR') }}" + initialized: "{{ (sushanasr_init.stdout | default('')) is search('susHanaSR.init') }}" + susChkSrv: + loaded: "{{ (suschksrv_load.stdout | default('')) is search('HADR.*load.*susChkSrv') }}" + initialized: "{{ (suschksrv_init.stdout | default('')) is search('susChkSrv.init') }}" + events_found: "{{ (suschksrv_events.stdout | default('')) is search('(START:|init|load)') }}" + + # Step 5: Display validation results + - name: "5.5 HANA Pacemaker - Display hook configuration validation results" + ansible.builtin.debug: + msg: | + SAPHanaSR-angi Hook Configuration Status: + + 1. susHanaSR.py: + - Loaded: {{ hook_status.susHanaSR.loaded }} + - Initialized: {{ hook_status.susHanaSR.initialized }} + + 2. susChkSrv.py: + - Loaded: {{ hook_status.susChkSrv.loaded }} + - Initialized: {{ hook_status.susChkSrv.initialized }} + - Events Found: {{ hook_status.susChkSrv.events_found }} + + # Step 6: Set overall validation status + - name: "5.5 HANA Pacemaker - Set overall hook validation status" + ansible.builtin.set_fact: + hooks_properly_configured: "{{ + hook_status.susHanaSR.loaded and + hook_status.susHanaSR.initialized and + hook_status.susChkSrv.loaded and + hook_status.susChkSrv.initialized + }}" + + - name: "5.5 HANA Pacemaker - Display overall hook configuration status" + ansible.builtin.debug: + msg: | + SAPHanaSR-angi Hook Configuration Status: {{ 'PASSED' if hooks_properly_configured else 'FAILED' }} + + rescue: + - name: "5.5 HANA Pacemaker - Handle hook validation failure" + ansible.builtin.fail: + msg: | + Failed to validate hook configuration: + {{ ansible_failed_result.msg | default('Unknown error occurred') }} +# +------------------------------------4--------------------------------------*/ diff --git a/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/templates/20-saphana-rhel.j2 b/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/templates/20-saphana-rhel.j2 new file mode 100644 index 000000000..a51b5a8c9 --- /dev/null +++ b/deploy/ansible/roles-sap/5.5-hanadb-pacemaker/templates/20-saphana-rhel.j2 @@ -0,0 +1,6 @@ +Cmnd_Alias SITEA_SOK = /usr/sbin/crm_attribute -n hana_{{ db_sid | lower }}_site_srHook_SITEA -v SOK -t crm_config -s SAPHanaSR +Cmnd_Alias SITEA_SFAIL = /usr/sbin/crm_attribute -n hana_{{ db_sid | lower }}_site_srHook_SITEA -v SFAIL -t crm_config -s SAPHanaSR +Cmnd_Alias SITEB_SOK = /usr/sbin/crm_attribute -n hana_{{ db_sid | lower }}_site_srHook_SITEB -v SOK -t crm_config -s SAPHanaSR +Cmnd_Alias SITEB_SFAIL = /usr/sbin/crm_attribute -n hana_{{ db_sid | lower }}_site_srHook_SITEB -v SFAIL -t crm_config -s SAPHanaSR +{{ db_sid | lower }}adm ALL=(ALL) NOPASSWD: SITEA_SOK, SITEA_SFAIL, SITEB_SOK, SITEB_SFAIL +Defaults!SITEA_SOK, SITEA_SFAIL, SITEB_SOK, SITEB_SFAIL !requiretty