From 703196426648364b9fc788bcac2081be83d134c8 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Tue, 2 Sep 2025 13:14:17 +0200 Subject: [PATCH 1/7] feat: sap_hana_install idempotency rework --- roles/sap_hana_install/.ansible-lint | 1 + roles/sap_hana_install/tasks/hana_exists.yml | 5 +- roles/sap_hana_install/tasks/hana_start.yml | 40 ++ roles/sap_hana_install/tasks/main.yml | 60 ++- roles/sap_hana_install/tasks/post_install.yml | 352 +++++------------- .../tasks/post_install/check_installation.yml | 85 +++++ .../tasks/post_install/fapolicyd.yml | 99 +++++ .../tasks/post_install/hdbuserstore.yml | 2 +- .../tasks/post_install/log_mode.yml | 4 +- .../post_install/recreate_tenant_database.yml | 5 +- roles/sap_hana_install/tasks/pre_install.yml | 11 +- .../tasks/pre_install/hdblcm_configfile.yml | 13 +- .../tasks/pre_install/hdblcm_prepare.yml | 4 +- .../tasks/pre_install/verify_checksum.yml | 4 +- 14 files changed, 391 insertions(+), 294 deletions(-) create mode 100644 roles/sap_hana_install/tasks/hana_start.yml create mode 100644 roles/sap_hana_install/tasks/post_install/check_installation.yml create mode 100644 roles/sap_hana_install/tasks/post_install/fapolicyd.yml diff --git a/roles/sap_hana_install/.ansible-lint b/roles/sap_hana_install/.ansible-lint index 8a5df4d43..a75ef53a9 100644 --- a/roles/sap_hana_install/.ansible-lint +++ b/roles/sap_hana_install/.ansible-lint @@ -14,3 +14,4 @@ skip_list: - schema # Allow templating inside name because it creates more detailed output: - name[template] + - yaml[line-length] diff --git a/roles/sap_hana_install/tasks/hana_exists.yml b/roles/sap_hana_install/tasks/hana_exists.yml index c97c88f7e..bde4f86f4 100644 --- a/roles/sap_hana_install/tasks/hana_exists.yml +++ b/roles/sap_hana_install/tasks/hana_exists.yml @@ -34,7 +34,7 @@ loop_var: __sap_hana_install_loop_instance label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" - - name: SAP HANA Checks - Trying to install HANA with other SID and existing instance number + - name: SAP HANA Checks - Fail if existing HANA was detected with same instance number but different SID ansible.builtin.fail: msg: "The instance number {{ sap_hana_install_number }} is already used by HANA system {{ __sap_hana_install_loop_instance.split('-')[0] | trim }}!" @@ -46,7 +46,7 @@ loop_var: __sap_hana_install_loop_instance label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" - - name: SAP HANA Checks - Trying to install HANA with existing SID and other instance number + - name: SAP HANA Checks - Fail if existing HANA was detected with same SID but different instance number ansible.builtin.fail: msg: "HANA system {{ sap_hana_install_sid }} already exists with different instance number {{ __sap_hana_install_loop_instance.split('-')[1] | trim }}!" @@ -58,7 +58,6 @@ loop_var: __sap_hana_install_loop_instance label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" -## If saphostcontrol is not installed - name: SAP HANA Checks - Check directories if no saphostctrl is found when: not __sap_hana_install_register_stat_saphostctrl.stat.exists diff --git a/roles/sap_hana_install/tasks/hana_start.yml b/roles/sap_hana_install/tasks/hana_start.yml new file mode 100644 index 000000000..49c4d2a5a --- /dev/null +++ b/roles/sap_hana_install/tasks/hana_start.yml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: Ensure SAP HANA is running - Set path to sapcontrol + ansible.builtin.set_fact: + __sap_hana_install_sapcontrol_path: + "/usr/sap/{{ sap_hana_install_sid | upper }}/HDB{{ sap_hana_install_number }}/exe/sapcontrol" + +- name: Ensure SAP HANA is running - Check for sapcontrol executable + ansible.builtin.stat: + path: "{{ __sap_hana_install_sapcontrol_path }}" + register: __sap_hana_install_stat_sapcontrol + +- name: Block to Ensure SAP HANA is running + when: __sap_hana_install_stat_sapcontrol.stat.exists + block: + + - name: Ensure SAP HANA is running - Start instance + ansible.builtin.command: + cmd: "{{ __sap_hana_install_sapcontrol_path }} -nr {{ sap_hana_install_number }} -function StartSystem" + become: true + become_user: "{{ sap_hana_install_sid | lower }}adm" + register: __sap_hana_install_register_start_hana + changed_when: "'StartSystem OK' in __sap_hana_install_register_start_hana.stdout" + + - name: Ensure SAP HANA is running - Wait for instance to be fully started + ansible.builtin.command: + cmd: "{{ __sap_hana_install_sapcontrol_path }} -nr {{ sap_hana_install_number }} -function GetProcessList" + become: true + become_user: "{{ sap_hana_install_sid | lower }}adm" + register: __sap_hana_install_register_sapcontrol_getprocesslist + # sapcontrol GetProcessList returns codes: + # 0 if some processes are starting or stopping (YELLOW) + # 3 if all processes are running (GREEN). + # 4 if all processes are stopped (GRAY). + until: __sap_hana_install_register_sapcontrol_getprocesslist.rc == 3 + retries: 60 # wait for 10 minutes + delay: 10 + changed_when: false + failed_when: false # command module will fail with non-zero return code diff --git a/roles/sap_hana_install/tasks/main.yml b/roles/sap_hana_install/tasks/main.yml index 5fd567645..8d5762110 100644 --- a/roles/sap_hana_install/tasks/main.yml +++ b/roles/sap_hana_install/tasks/main.yml @@ -110,7 +110,8 @@ - name: SAP HANA existence checking - ansible.builtin.import_tasks: hana_exists.yml + ansible.builtin.include_tasks: + file: hana_exists.yml when: - sap_hana_install_new_system | d(true) - not sap_hana_install_force | d(false) @@ -118,21 +119,60 @@ - sap_hana_install_check_hana_exists - sap_hana_install_preinstall +# SAP HANA has to be started when: +# 1. Existing SAP HANA was detected and '__sap_hana_install_fact_is_installed' is true. +# 2. Addhosts is executed when 'not sap_hana_install_new_system' +- name: Ensure SAP HANA is running for existing systems or addhosts operations + ansible.builtin.include_tasks: + file: hana_start.yml + when: + - __sap_hana_install_fact_is_installed | d(false) + or not sap_hana_install_new_system | d(true) + +# SELinux is not currently supported by SAP using SLES4SAP +# This can still be overwritten by extra variables. +- name: SAP HANA Pre Install - Ensure SELinux does not execute for SLES + ansible.builtin.set_fact: + sap_hana_install_modify_selinux_labels: false + when: ansible_os_family == "Suse" + + +# This role consists of installation and configuration tasks. +# Installation tasks have to be run only for new installations. +# Configuration tasks have to be run always to ensure idempotency. - name: Install SAP HANA - when: not __sap_hana_install_fact_is_installed | d(false) + when: + - not __sap_hana_install_fact_is_installed | d(false) + - sap_hana_install_new_system | d(true) block: + # pre_install.yml currently contains no configuration tasks. - name: SAP HANA pre-install steps - ansible.builtin.import_tasks: pre_install.yml + ansible.builtin.include_tasks: + file: pre_install.yml tags: sap_hana_install_preinstall - name: SAP HANA installation steps - ansible.builtin.import_tasks: hana_install.yml - when: sap_hana_install_new_system | d(true) + ansible.builtin.include_tasks: + file: hana_install.yml - - name: SAP HANA addhosts steps - ansible.builtin.import_tasks: hana_addhosts.yml - when: not sap_hana_install_new_system | d(true) - - name: SAP HANA post-install steps - ansible.builtin.import_tasks: post_install.yml +- name: SAP HANA addhosts steps + ansible.builtin.include_tasks: + file: hana_addhosts.yml + when: + - not sap_hana_install_new_system | d(true) + - __sap_hana_install_fact_is_installed | d(false) + + +# post_install is modular task file, that contains both installation and configuration tasks. +# addhosts should not execute post_install steps, therefore we use sap_hana_install_new_system. +- name: SAP HANA post-install steps + ansible.builtin.include_tasks: + file: post_install.yml + when: + - sap_hana_install_new_system | d(true) + +- name: Pause + ansible.builtin.pause: + minutes: 1200 diff --git a/roles/sap_hana_install/tasks/post_install.yml b/roles/sap_hana_install/tasks/post_install.yml index 44ee52a80..12a3d8348 100644 --- a/roles/sap_hana_install/tasks/post_install.yml +++ b/roles/sap_hana_install/tasks/post_install.yml @@ -1,48 +1,37 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: Tasks for new HANA Systems - when: sap_hana_install_new_system | d(true) +# Installation tasks that can be destructive and should never be executed on existing database. +- name: Block with tasks for new HANA Systems + when: + - not __sap_hana_install_fact_is_installed | d(false) block: - name: SAP HANA Post Install - Store connection information - ansible.builtin.include_tasks: post_install/hdbuserstore.yml + ansible.builtin.include_tasks: + file: post_install/hdbuserstore.yml tags: sap_hana_install_store_connection_information - name: SAP HANA Post Install - Set log_mode - ansible.builtin.include_tasks: post_install/log_mode.yml + ansible.builtin.include_tasks: + file: post_install/log_mode.yml tags: sap_hana_install_set_log_mode - name: SAP HANA Post Install - Apply license - ansible.builtin.include_tasks: post_install/license.yml + ansible.builtin.include_tasks: + file: post_install/license.yml when: sap_hana_install_apply_license - - name: SAP HANA Post Install - Set '{{ sap_hana_install_sid | lower }}adm' to no expire - ansible.builtin.shell: | - chage -m 0 -M 99999 -I -1 -E -1 {{ sap_hana_install_sid | lower }}adm - args: - executable: /bin/bash - become: true - register: __sap_hana_install_post_install_register_sidadm_noexpire - changed_when: __sap_hana_install_post_install_register_sidadm_noexpire.rc == 0 - when: sap_hana_install_set_sidadm_noexpire | default(true) - - name: SAP HANA Post Install - Recreate the initial tenant database - ansible.builtin.include_tasks: post_install/recreate_tenant_database.yml + ansible.builtin.include_tasks: + file: post_install/recreate_tenant_database.yml when: sap_hana_install_recreate_tenant_database | d(true) -# Optional Post Install Tasks - -# not needed because already done in sap_general_preconfigure -# - name: SAP HANA Post Install - Update /etc/hosts -# ansible.builtin.include_tasks: post_install/update_etchosts.yml -# when: -# - "sap_hana_install_update_etchosts | bool" - - - name: SAP HANA Post Install - Firewall - ansible.builtin.include_tasks: post_install/firewall.yml - when: "sap_hana_install_update_firewall | bool" - tags: sap_hana_install_configure_firewall + - name: SAP HANA Post Install - Perform an hdblcm installation check + ansible.builtin.include_tasks: + file: post_install/check_installation.yml + when: sap_hana_install_check_installation | d(false) + tags: sap_hana_install_check_installation - name: SAP HANA Post Install - Generate Input File for SAP Application Deployment '{{ sap_hana_install_nw_input_location }}/{{ sap_hana_install_sid }}.info.nw.install' @@ -51,101 +40,64 @@ dest: "{{ sap_hana_install_nw_input_location }}/{{ sap_hana_install_sid }}.info.nw.install" mode: '0600' become: false - delegate_to: 127.0.0.1 + delegate_to: localhost vars: ansible_become: false tags: sap_hana_install_generate_input_file -################ - -- name: Perform an hdblcm installation check - when: sap_hana_install_check_installation | d(false) - tags: sap_hana_install_check_installation - block: - - - name: SAP HANA hdblcm installation check - Create a Jinja2 template from the hdblcm xml configfile template - ansible.builtin.shell: | - set -o pipefail && - awk ' - !/^ /&&!/^\n")} - /^ /{split ($0, b, "[\*\*\*]"); gsub (">", ""); split ($0, a, "<"); printf ("%s\{\{ sap_hana_install_%s | d(sap_hana_install_master_password) \}\}%s\n", b[1], a[2], b[4])}' {{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.cfg.xml > {{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.xml.j2 - register: __sap_hana_install_create_jinja2_template - changed_when: false - - - name: SAP HANA hdblcm installation check - Display the location of the remote Jinja2 template - ansible.builtin.debug: - msg: | - The Jinja2 template for creating the hdblcm configfile xml has been saved to - '{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.xml.j2'. + # Cleanup extracted software + - name: SAP HANA Post Install - Deleting software extract directory '{{ sap_hana_install_software_extract_directory }}' + ansible.builtin.file: + path: "{{ sap_hana_install_software_extract_directory }}" + state: absent + when: sap_hana_install_cleanup_extract_directory - - name: SAP HANA hdblcm installation check - Download the Jinja2 template - ansible.builtin.fetch: - src: "{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.xml.j2" - dest: "{{ sap_hana_install_local_configfile_directory }}" - register: __sap_hana_install_register_fetch_hdblcm_configfile_xml_jinja2_template + - name: SAP HANA Post Install - Deleting Configfile Directory '{{ sap_hana_install_configfile_directory }}' + ansible.builtin.file: + path: "{{ sap_hana_install_configfile_directory }}" + state: absent + when: sap_hana_install_cleanup_configfile_directory - - name: SAP HANA hdblcm installation check - Display the location of the local Jinja2 template - ansible.builtin.debug: - msg: "The Jinja2 template has been downloaded to '{{ __sap_hana_install_register_fetch_hdblcm_configfile_xml_jinja2_template.dest }}'." - when: not ansible_check_mode - - - name: SAP HANA hdblcm installation check - Process the Jinja2 template to create the hdblcm xml configfile - ansible.builtin.template: - src: "{{ __sap_hana_install_register_fetch_hdblcm_configfile_xml_jinja2_template.dest }}" - dest: "{{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml" - mode: '0644' - register: __sap_hana_install_register_cftemplate - when: not ansible_check_mode - - name: SAP HANA hdblcm installation check - Construct an hdbcheck command line - ansible.builtin.set_fact: - __sap_hana_install_fact_installation_check_command: "set -o pipefail && ./hdbcheck -b --read_password_from_stdin=xml - --property_file={{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/global/hdb/install/support/hdbcheck.xml - --remote_execution=ssh - --scope=system - -b < {{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml" - when: sap_hana_install_use_hdbcheck | d(true) - - - name: SAP HANA hdblcm installation check - Construct an hdblcm command line - ansible.builtin.set_fact: - __sap_hana_install_fact_installation_check_command: "set -o pipefail && ./hdblcm --action=check_installation - --read_password_from_stdin=xml - -b < {{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml" - when: not sap_hana_install_use_hdbcheck | d(true) - - - name: SAP HANA hdblcm installation check - Display the command line - ansible.builtin.debug: - var: __sap_hana_install_fact_installation_check_command - -# Reason for noqa: The command to be executed contains input redirection - - name: SAP HANA hdblcm installation check with hdbcheck - Perform the check # noqa command-instead-of-shell - ansible.builtin.shell: "{{ __sap_hana_install_fact_installation_check_command }}" - args: - chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/global/hdb/install/bin" - register: __sap_hana_install_register_installation_check - changed_when: false - when: sap_hana_install_use_hdbcheck | d(true) - - - name: SAP HANA hdblcm installation check with hdbcheck - Display the result - ansible.builtin.debug: - var: __sap_hana_install_register_installation_check.stdout_lines - when: sap_hana_install_use_hdbcheck | d(true) +# Idempotent tasks for new and existing HANA Systems +- name: SAP HANA Post Install - Set '{{ sap_hana_install_sid | lower }}adm' to not expire + ansible.builtin.shell: | + chage -m 0 -M 99999 -I -1 -E -1 {{ sap_hana_install_sid | lower }}adm + args: + executable: /bin/bash + become: true + register: __sap_hana_install_post_install_register_sidadm_noexpire + changed_when: __sap_hana_install_post_install_register_sidadm_noexpire.rc == 0 + when: sap_hana_install_set_sidadm_noexpire | default(true) + +- name: SAP HANA Post Install - Firewall + ansible.builtin.include_tasks: + file: post_install/firewall.yml + when: sap_hana_install_update_firewall + tags: sap_hana_install_configure_firewall + +- name: SAP HANA Post Install - SELinux + ansible.builtin.include_role: + name: '{{ sap_hana_install_system_roles_collection }}.selinux' + vars: + selinux_fcontexts: + - { target: '/usr/sap(/.*)?', setype: 'usr_t' } + selinux_restore_dirs: + - /usr/sap + when: sap_hana_install_modify_selinux_labels -# Reason for noqa: The command to be executed contains input redirection - - name: SAP HANA hdblcm installation check with hdblcm - Perform the check # noqa command-instead-of-shell - ansible.builtin.shell: "{{ __sap_hana_install_fact_installation_check_command }}" - args: - chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" - register: __sap_hana_install_register_installation_check - changed_when: false - when: not sap_hana_install_use_hdbcheck | d(true) +- name: SAP HANA Post Install - Fapolicyd + ansible.builtin.include_tasks: + file: post_install/fapolicyd.yml + when: + # Ensure fapolicyd is checked only on supported systems. + - ansible_os_family == "RedHat" + - sap_hana_install_use_fapolicyd + - '"fapolicyd" in ansible_facts.packages' + tags: sap_hana_install_use_fapolicyd - - name: SAP HANA hdblcm installation check with hdblcm - Display the result - ansible.builtin.debug: - var: __sap_hana_install_register_installation_check.stdout_lines - when: not sap_hana_install_use_hdbcheck | d(true) +# Gather details about installed database for finished message - name: SAP HANA Install - Run 'hdblcm --list_systems' after the installation ansible.builtin.shell: | set -o pipefail && ./hdblcm --list_systems | awk '/\/hana\/shared\/{{ sap_hana_install_sid }}/{a=1} @@ -161,156 +113,40 @@ changed_when: false when: not ansible_check_mode -- name: Configure '/usr/sap' SELinux file contexts - ansible.builtin.include_role: - name: '{{ sap_hana_install_system_roles_collection }}.selinux' - vars: - selinux_fcontexts: - - { target: '/usr/sap(/.*)?', setype: 'usr_t' } - selinux_restore_dirs: - - /usr/sap - when: sap_hana_install_modify_selinux_labels - -- name: Set fact - HANA version +- name: SAP HANA Post Install - Set facts with HANA version and hosts ansible.builtin.set_fact: __sap_hana_install_fact_hana_version: "{{ __sap_hana_install_register_install_result.stdout.split(';')[0] }}" - when: not ansible_check_mode - -- name: SAP HANA Post Install - Deleting software extract directory '{{ sap_hana_install_software_extract_directory }}' - ansible.builtin.file: - path: "{{ sap_hana_install_software_extract_directory }}" - state: absent - when: sap_hana_install_cleanup_extract_directory - -- name: SAP HANA Post Install - Deleting Configfile Directory '{{ sap_hana_install_configfile_directory }}' - ansible.builtin.file: - path: "{{ sap_hana_install_configfile_directory }}" - state: absent - when: sap_hana_install_cleanup_configfile_directory - -- name: Set fact - HANA hosts - ansible.builtin.set_fact: __sap_hana_install_fact_hana_hosts: "{{ __sap_hana_install_register_install_result.stdout.split(';')[1] }}" when: not ansible_check_mode -- name: SAP HANA Deployment - Finished - ansible.builtin.debug: - msg: - - ' SAP HANA deployment successfully completed:' - - ' ' - - ' HANA Version - {{ __sap_hana_install_fact_hana_version }}' - - ' Hosts - {{ __sap_hana_install_fact_hana_hosts }}' - - ' SID - {{ sap_hana_install_sid }}' - - ' NR - {{ sap_hana_install_number }}' -# - ' Master Password - {{ sap_hana_install_master_password }}' -# - ' IP - {{ ansible_default_ipv4.address | default(ansible_all_ipv4_addresses[0]) }}' -# - ' Host - {{ ansible_hostname }}' -# - ' FQDN - {{ ansible_fqdn }}' - when: not ansible_check_mode - -- name: SAP HANA Post Install, fapolicyd - Update config for desired integrity level and revert if validation fails - when: - # Ensure fapolicyd is checked only on supported systems. - - ansible_os_family == "RedHat" - - sap_hana_install_use_fapolicyd - - '"fapolicyd" in ansible_facts.packages' - tags: sap_hana_install_use_fapolicyd - block: - - - name: SAP HANA Post Install, fapolicyd - Ensure Ansible marker for 'integrity' is present in fapolicyd config file - ansible.builtin.lineinfile: - path: /etc/fapolicyd/fapolicyd.conf - regexp: '# "integrity" managed by Ansible' - insertbefore: '^integrity\s*=.*' - line: '# "integrity" managed by Ansible' - - name: SAP HANA Post Install, fapolicyd - Ensure integrity level '{{ sap_hana_install_fapolicyd_integrity }}' is configured" - ansible.builtin.lineinfile: - path: /etc/fapolicyd/fapolicyd.conf - regexp: '^(integrity\s*=.*)' - insertafter: '# "integrity" managed by Ansible' - line: 'integrity = {{ sap_hana_install_fapolicyd_integrity }}' - backup: true - register: __sap_hana_install_fapolicyd_conf_updated - - - name: SAP HANA Post Install, fapolicyd - Validate the new version of the fapolicyd config file - ansible.builtin.command: fapolicyd-cli --check-config - changed_when: false - - rescue: - - - name: SAP HANA Post Install, fapolicyd - Restore fapolicyd config file from backup if validation fails - ansible.builtin.copy: - remote_src: true - dest: /etc/fapolicyd/fapolicyd.conf - src: "{{ __sap_hana_install_fapolicyd_conf_updated['backup'] }}" - owner: root - group: fapolicyd - mode: '0644' - - - name: SAP HANA Post Install, fapolicyd - Notify about failed validation - ansible.builtin.fail: - msg: >- - "The update of the fapolicyd config file failed, likely because an unsupported value has been used for - the parameter 'sap_hana_install_fapolicyd_integrity'. The previous version has been successfully restored." - -- name: SAP HANA Post Install, fapolicyd - Create rule and trust files, enable fapolicyd +- name: SAP HANA Post Install - New installation was finished + ansible.builtin.debug: + msg: | + SAP HANA deployment successfully completed: + HANA Version - {{ __sap_hana_install_fact_hana_version }} + Hosts - {{ __sap_hana_install_fact_hana_hosts }} + SID - {{ sap_hana_install_sid }} + NR - {{ sap_hana_install_number }} +# IP - {{ ansible_default_ipv4.address | default(ansible_all_ipv4_addresses[0]) }} +# Host - {{ ansible_hostname }} +# FQDN - {{ ansible_fqdn }} when: - - sap_hana_install_use_fapolicyd - - '"fapolicyd" in ansible_facts.packages' - tags: sap_hana_install_use_fapolicyd - block: - - - name: SAP HANA Post Install, fapolicyd - Process template for creating rule file '{{ sap_hana_install_fapolicyd_rule_file }}' - ansible.builtin.template: - src: fapolicyd-rules.j2 - dest: "/etc/fapolicyd/rules.d/{{ sap_hana_install_fapolicyd_rule_file }}.rules" - owner: root - group: fapolicyd - mode: '0644' - -# Reason for noqa: The return code of the command is always 0 no matter if there was a change or not - - name: SAP HANA Post Install, fapolicyd - Merge rule files # noqa no-changed-when - ansible.builtin.command: fagenrules --load - register: sap_hana_install_register_fagenrules_load - - - name: SAP HANA Post Install, fapolicyd - Display the output of the command 'fagenrules --load' - ansible.builtin.debug: - msg: "{{ sap_hana_install_register_fagenrules_load.stdout_lines }}" + - not __sap_hana_install_fact_is_installed | d(false) + - not ansible_check_mode -# We want to add files which have the execute mode bit set AND which are reported as executables -# by fapolicyd-cli -t, one for each directory of sap_hana_install_fapolicyd_trusted_directories. -# The fapolicy trust file name will be created from the directory names by replacing '/' by '_' and -# omitting the first '_'. - - name: SAP HANA Post Install, fapolicyd - Put all executable files from 'sap_hana_install_fapolicyd_trusted_directories' into fapolicyd trust files - ansible.builtin.shell: | - set -o pipefail && - find {{ __sap_hana_install_item }} -type f -executable -exec fapolicyd-cli -t {} \; -print | - awk '/\/x-/{a=1; b=NR} - { - if(a==1 && b==(NR-1)){ - system("fapolicyd-cli --file add "$0" --trust-file \ - {{ __sap_hana_install_item | regex_replace('//*', '_') | regex_replace("^_", "") }}"); a=0; b=0 - } - }' - loop: "{{ sap_hana_install_fapolicyd_trusted_directories }}" - loop_control: - loop_var: __sap_hana_install_item - label: >- - "{{ __sap_hana_install_item }} -> - /etc/fapolicyd/trust.d/{{ __sap_hana_install_item | - regex_replace('//*', '_') | - regex_replace('^_', '') }}" - changed_when: true - - - name: SAP HANA Post Install, fapolicyd - Enable fapolicyd - ansible.builtin.service: - name: fapolicyd - enabled: true - state: started - - - name: SAP HANA Post Install, fapolicyd - Restart fapolicyd - ansible.builtin.service: - name: fapolicyd - enabled: true - state: restarted +- name: SAP HANA Post Install - Configuration steps completed + ansible.builtin.debug: + msg: | + SAP HANA configuration steps were completed: + - Set user '{{ sap_hana_install_sid | lower }}adm' to not expire + {% if sap_hana_install_update_firewall %} + - Enable firewall and open SAP HANA ports + {% endif %} + {% if sap_hana_install_modify_selinux_labels %} + - SElinux policies updated for SAP folders /usr/sap/ + {% endif %} + {% if ansible_os_family == "RedHat" and sap_hana_install_use_fapolicyd and "fapolicyd" in ansible_facts.packages %} + - Fapolicyd configuration was updated + {% endif %} + when: not ansible_check_mode diff --git a/roles/sap_hana_install/tasks/post_install/check_installation.yml b/roles/sap_hana_install/tasks/post_install/check_installation.yml new file mode 100644 index 000000000..1bb100b3b --- /dev/null +++ b/roles/sap_hana_install/tasks/post_install/check_installation.yml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA hdblcm installation check - Create a Jinja2 template from the hdblcm xml configfile template + ansible.builtin.shell: | + set -o pipefail && + awk ' + !/^ /&&!/^\n")} + /^ /{split ($0, b, "[\*\*\*]"); gsub (">", ""); split ($0, a, "<"); printf ("%s\{\{ sap_hana_install_%s | d(sap_hana_install_master_password) \}\}%s\n", b[1], a[2], b[4])}' {{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.cfg.xml > {{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.xml.j2 + register: __sap_hana_install_create_jinja2_template + changed_when: false + +- name: SAP HANA hdblcm installation check - Display the location of the remote Jinja2 template + ansible.builtin.debug: + msg: | + The Jinja2 template for creating the hdblcm configfile xml has been saved to + '{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.xml.j2'. + +- name: SAP HANA hdblcm installation check - Download the Jinja2 template + ansible.builtin.fetch: + src: "{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.xml.j2" + dest: "{{ sap_hana_install_local_configfile_directory }}" + register: __sap_hana_install_register_fetch_hdblcm_configfile_xml_jinja2_template + +- name: SAP HANA hdblcm installation check - Display the location of the local Jinja2 template + ansible.builtin.debug: + msg: "The Jinja2 template has been downloaded to '{{ __sap_hana_install_register_fetch_hdblcm_configfile_xml_jinja2_template.dest }}'." + when: not ansible_check_mode + +- name: SAP HANA hdblcm installation check - Process the Jinja2 template to create the hdblcm xml configfile + ansible.builtin.template: + src: "{{ __sap_hana_install_register_fetch_hdblcm_configfile_xml_jinja2_template.dest }}" + dest: "{{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml" + mode: '0644' + register: __sap_hana_install_register_cftemplate + when: not ansible_check_mode + +- name: SAP HANA hdblcm installation check - Construct an hdbcheck command line + ansible.builtin.set_fact: + __sap_hana_install_fact_installation_check_command: "set -o pipefail && ./hdbcheck -b --read_password_from_stdin=xml + --property_file={{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/global/hdb/install/support/hdbcheck.xml + --remote_execution=ssh + --scope=system + -b < {{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml" + when: sap_hana_install_use_hdbcheck | d(true) + +- name: SAP HANA hdblcm installation check - Construct an hdblcm command line + ansible.builtin.set_fact: + __sap_hana_install_fact_installation_check_command: "set -o pipefail && ./hdblcm --action=check_installation + --read_password_from_stdin=xml + -b < {{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml" + when: not sap_hana_install_use_hdbcheck | d(true) + +- name: SAP HANA hdblcm installation check - Display the command line + ansible.builtin.debug: + var: __sap_hana_install_fact_installation_check_command + +# Reason for noqa: The command to be executed contains input redirection +- name: SAP HANA hdblcm installation check with hdbcheck - Perform the check # noqa command-instead-of-shell + ansible.builtin.shell: "{{ __sap_hana_install_fact_installation_check_command }}" + args: + chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/global/hdb/install/bin" + register: __sap_hana_install_register_installation_check + changed_when: false + when: sap_hana_install_use_hdbcheck | d(true) + +- name: SAP HANA hdblcm installation check with hdbcheck - Display the result + ansible.builtin.debug: + var: __sap_hana_install_register_installation_check.stdout_lines + when: sap_hana_install_use_hdbcheck | d(true) + +# Reason for noqa: The command to be executed contains input redirection +- name: SAP HANA hdblcm installation check with hdblcm - Perform the check # noqa command-instead-of-shell + ansible.builtin.shell: "{{ __sap_hana_install_fact_installation_check_command }}" + args: + chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" + register: __sap_hana_install_register_installation_check + changed_when: false + when: not sap_hana_install_use_hdbcheck | d(true) + +- name: SAP HANA hdblcm installation check with hdblcm - Display the result + ansible.builtin.debug: + var: __sap_hana_install_register_installation_check.stdout_lines + when: not sap_hana_install_use_hdbcheck | d(true) diff --git a/roles/sap_hana_install/tasks/post_install/fapolicyd.yml b/roles/sap_hana_install/tasks/post_install/fapolicyd.yml new file mode 100644 index 000000000..7fe169ead --- /dev/null +++ b/roles/sap_hana_install/tasks/post_install/fapolicyd.yml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA Post Install, fapolicyd - Update config for desired integrity level and revert if validation fails + block: + - name: SAP HANA Post Install, fapolicyd - Ensure Ansible marker for 'integrity' is present in fapolicyd config file + ansible.builtin.lineinfile: + path: /etc/fapolicyd/fapolicyd.conf + regexp: '# "integrity" managed by Ansible' + insertbefore: '^integrity\s*=.*' + line: '# "integrity" managed by Ansible' + + - name: SAP HANA Post Install, fapolicyd - Ensure integrity level '{{ sap_hana_install_fapolicyd_integrity }}' is configured" + ansible.builtin.lineinfile: + path: /etc/fapolicyd/fapolicyd.conf + regexp: '^(integrity\s*=.*)' + insertafter: '# "integrity" managed by Ansible' + line: 'integrity = {{ sap_hana_install_fapolicyd_integrity }}' + backup: true + register: __sap_hana_install_fapolicyd_conf_updated + + - name: SAP HANA Post Install, fapolicyd - Validate the new version of the fapolicyd config file + ansible.builtin.command: fapolicyd-cli --check-config + changed_when: false + + rescue: + + - name: SAP HANA Post Install, fapolicyd - Restore fapolicyd config file from backup if validation fails + ansible.builtin.copy: + remote_src: true + dest: /etc/fapolicyd/fapolicyd.conf + src: "{{ __sap_hana_install_fapolicyd_conf_updated['backup'] }}" + owner: root + group: fapolicyd + mode: '0644' + + - name: SAP HANA Post Install, fapolicyd - Notify about failed validation + ansible.builtin.fail: + msg: >- + "The update of the fapolicyd config file failed, likely because an unsupported value has been used for + the parameter 'sap_hana_install_fapolicyd_integrity'. The previous version has been successfully restored." + + +- name: SAP HANA Post Install, fapolicyd - Create rule and trust files, enable fapolicyd + block: + + - name: SAP HANA Post Install, fapolicyd - Process template for creating rule file '{{ sap_hana_install_fapolicyd_rule_file }}' + ansible.builtin.template: + src: fapolicyd-rules.j2 + dest: "/etc/fapolicyd/rules.d/{{ sap_hana_install_fapolicyd_rule_file }}.rules" + owner: root + group: fapolicyd + mode: '0644' + + # Reason for noqa: The return code of the command is always 0 no matter if there was a change or not + - name: SAP HANA Post Install, fapolicyd - Merge rule files # noqa no-changed-when + ansible.builtin.command: fagenrules --load + register: sap_hana_install_register_fagenrules_load + + - name: SAP HANA Post Install, fapolicyd - Display the output of the command 'fagenrules --load' + ansible.builtin.debug: + msg: "{{ sap_hana_install_register_fagenrules_load.stdout_lines }}" + + # We want to add files which have the execute mode bit set AND which are reported as executables + # by fapolicyd-cli -t, one for each directory of sap_hana_install_fapolicyd_trusted_directories. + # The fapolicy trust file name will be created from the directory names by replacing '/' by '_' and + # omitting the first '_'. + - name: SAP HANA Post Install, fapolicyd - Put all executable files from 'sap_hana_install_fapolicyd_trusted_directories' into fapolicyd trust files + ansible.builtin.shell: | + set -o pipefail && + find {{ __sap_hana_install_item }} -type f -executable -exec fapolicyd-cli -t {} \; -print | + awk '/\/x-/{a=1; b=NR} + { + if(a==1 && b==(NR-1)){ + system("fapolicyd-cli --file add "$0" --trust-file \ + {{ __sap_hana_install_item | regex_replace('//*', '_') | regex_replace("^_", "") }}"); a=0; b=0 + } + }' + loop: "{{ sap_hana_install_fapolicyd_trusted_directories }}" + loop_control: + loop_var: __sap_hana_install_item + label: >- + "{{ __sap_hana_install_item }} -> + /etc/fapolicyd/trust.d/{{ __sap_hana_install_item | + regex_replace('//*', '_') | + regex_replace('^_', '') }}" + changed_when: true + + - name: SAP HANA Post Install, fapolicyd - Enable fapolicyd + ansible.builtin.service: + name: fapolicyd + enabled: true + state: started + + - name: SAP HANA Post Install, fapolicyd - Restart fapolicyd + ansible.builtin.service: + name: fapolicyd + enabled: true + state: restarted diff --git a/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml b/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml index a4fa40e78..2593e5384 100644 --- a/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml +++ b/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml @@ -12,7 +12,7 @@ become: true become_user: "{{ sap_hana_install_sid | lower }}adm" when: not ansible_check_mode - changed_when: no + changed_when: false register: __sap_hana_install_store_connection_information tags: sap_hana_install_store_connection_information diff --git a/roles/sap_hana_install/tasks/post_install/log_mode.yml b/roles/sap_hana_install/tasks/post_install/log_mode.yml index 75338cdac..b490f7be8 100644 --- a/roles/sap_hana_install/tasks/post_install/log_mode.yml +++ b/roles/sap_hana_install/tasks/post_install/log_mode.yml @@ -22,7 +22,7 @@ - not ansible_check_mode - sap_hana_install_create_initial_tenant == 'n' - sap_hana_install_log_mode | d('') == 'overwrite' - changed_when: no + changed_when: false register: __sap_hana_install_register_hdbsql_logmode_no_initial_tenant tags: sap_hana_install_set_log_mode @@ -57,7 +57,7 @@ - not ansible_check_mode - sap_hana_install_create_initial_tenant == 'y' - sap_hana_install_log_mode | d('') == 'overwrite' - changed_when: no + changed_when: false register: __sap_hana_install_register_hdbsql_logmode_with_initial_tenant tags: sap_hana_install_set_log_mode diff --git a/roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml b/roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml index 8c2cfc8b6..e12f394fe 100644 --- a/roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml +++ b/roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml @@ -13,7 +13,8 @@ -m < {{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.j2 register: __sap_hana_install_create_jinja2_template - changed_when: no + changed_when: false - name: SAP HANA Pre Install - Display the location of the remote Jinja2 template ansible.builtin.debug: - msg: "The Jinja2 template for creating the hdblcm configfile has been saved to '{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.j2'." + msg: | + The Jinja2 template for creating the hdblcm configfile has been saved to + '{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.j2'. - name: SAP HANA Pre Install - Download the Jinja2 template ansible.builtin.fetch: diff --git a/roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml b/roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml index f1dca23ee..0b0e0f165 100644 --- a/roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml +++ b/roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml @@ -41,13 +41,13 @@ - name: Rescue block for SAPCAR and SAR file preparation block: - name: SAP HANA hdblcm prepare - Prepare SAPCAR - ansible.builtin.import_tasks: prepare_sapcar.yml + ansible.builtin.include_tasks: prepare_sapcar.yml tags: - sap_hana_install_prepare_sapcar - sap_hana_install_prepare_sarfiles - name: SAP HANA hdblcm prepare - Prepare SAR files - ansible.builtin.import_tasks: prepare_sarfiles.yml + ansible.builtin.include_tasks: prepare_sarfiles.yml tags: sap_hana_install_prepare_sarfiles rescue: - name: SAP HANA hdblcm prepare - Remove status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' diff --git a/roles/sap_hana_install/tasks/pre_install/verify_checksum.yml b/roles/sap_hana_install/tasks/pre_install/verify_checksum.yml index 9f189983e..125e25a65 100644 --- a/roles/sap_hana_install/tasks/pre_install/verify_checksum.yml +++ b/roles/sap_hana_install/tasks/pre_install/verify_checksum.yml @@ -20,9 +20,9 @@ # Reason for noqa: A double brace might also occur in an awk command sequence. - name: SAP HANA hdblcm prepare - Get expected checksum from file # noqa jinja[spacing] ansible.builtin.command: "awk 'BEGIN{a=0}/{{ __sap_hana_install_passed_file_dict.file }}/{a++; print $1}END{if (a==0){print \"Missing entry\"}}' {{ __sap_hana_install_passed_file_dict.checksum_file }}" - check_mode: no + check_mode: false register: __sap_hana_install_register_checksum_from_file - changed_when: no + changed_when: false - name: SAP HANA hdblcm prepare - Fail if an entry for file '{{ __sap_hana_install_passed_file_dict.file }}' is missing in '{{ __sap_hana_install_passed_file_dict.checksum_file }}' ansible.builtin.fail: From 3f48da35e4c928db85d04d21e7f5fccbabc43abf Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Tue, 2 Sep 2025 15:52:01 +0200 Subject: [PATCH 2/7] remove forgotten debug pause task --- roles/sap_hana_install/tasks/main.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/roles/sap_hana_install/tasks/main.yml b/roles/sap_hana_install/tasks/main.yml index 8d5762110..e9811f6da 100644 --- a/roles/sap_hana_install/tasks/main.yml +++ b/roles/sap_hana_install/tasks/main.yml @@ -172,7 +172,3 @@ file: post_install.yml when: - sap_hana_install_new_system | d(true) - -- name: Pause - ansible.builtin.pause: - minutes: 1200 From 6db061ec2a8a668f253d421bcba75abc65b772f6 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Fri, 5 Sep 2025 14:37:24 +0200 Subject: [PATCH 3/7] update final debug message and move user modification to new install block --- roles/sap_hana_install/tasks/post_install.yml | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/roles/sap_hana_install/tasks/post_install.yml b/roles/sap_hana_install/tasks/post_install.yml index 12a3d8348..8e9bd6d42 100644 --- a/roles/sap_hana_install/tasks/post_install.yml +++ b/roles/sap_hana_install/tasks/post_install.yml @@ -27,6 +27,16 @@ file: post_install/recreate_tenant_database.yml when: sap_hana_install_recreate_tenant_database | d(true) + - name: SAP HANA Post Install - Set '{{ sap_hana_install_sid | lower }}adm' to not expire + ansible.builtin.shell: | + chage -m 0 -M 99999 -I -1 -E -1 {{ sap_hana_install_sid | lower }}adm + args: + executable: /bin/bash + become: true + register: __sap_hana_install_post_install_register_sidadm_noexpire + changed_when: __sap_hana_install_post_install_register_sidadm_noexpire.rc == 0 + when: sap_hana_install_set_sidadm_noexpire | d(true) + - name: SAP HANA Post Install - Perform an hdblcm installation check ansible.builtin.include_tasks: file: post_install/check_installation.yml @@ -60,16 +70,6 @@ # Idempotent tasks for new and existing HANA Systems -- name: SAP HANA Post Install - Set '{{ sap_hana_install_sid | lower }}adm' to not expire - ansible.builtin.shell: | - chage -m 0 -M 99999 -I -1 -E -1 {{ sap_hana_install_sid | lower }}adm - args: - executable: /bin/bash - become: true - register: __sap_hana_install_post_install_register_sidadm_noexpire - changed_when: __sap_hana_install_post_install_register_sidadm_noexpire.rc == 0 - when: sap_hana_install_set_sidadm_noexpire | default(true) - - name: SAP HANA Post Install - Firewall ansible.builtin.include_tasks: file: post_install/firewall.yml @@ -120,33 +120,23 @@ when: not ansible_check_mode -- name: SAP HANA Post Install - New installation was finished +- name: SAP HANA Post Install - Display SAP HANA details and completed post tasks ansible.builtin.debug: msg: | - SAP HANA deployment successfully completed: + SAP HANA database is installed and running: HANA Version - {{ __sap_hana_install_fact_hana_version }} Hosts - {{ __sap_hana_install_fact_hana_hosts }} SID - {{ sap_hana_install_sid }} NR - {{ sap_hana_install_number }} -# IP - {{ ansible_default_ipv4.address | default(ansible_all_ipv4_addresses[0]) }} -# Host - {{ ansible_hostname }} -# FQDN - {{ ansible_fqdn }} - when: - - not __sap_hana_install_fact_is_installed | d(false) - - not ansible_check_mode -- name: SAP HANA Post Install - Configuration steps completed - ansible.builtin.debug: - msg: | - SAP HANA configuration steps were completed: - - Set user '{{ sap_hana_install_sid | lower }}adm' to not expire {% if sap_hana_install_update_firewall %} - - Enable firewall and open SAP HANA ports + Firewall is enabled and SAP HANA ports are open. {% endif %} {% if sap_hana_install_modify_selinux_labels %} - - SElinux policies updated for SAP folders /usr/sap/ + SElinux policies are configured for SAP folders '/usr/sap/' {% endif %} {% if ansible_os_family == "RedHat" and sap_hana_install_use_fapolicyd and "fapolicyd" in ansible_facts.packages %} - - Fapolicyd configuration was updated + Fapolicyd is configured. {% endif %} - when: not ansible_check_mode + when: + - not ansible_check_mode From 02db90ba101ee2635b3fd9857ffc9a990c4e0046 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Fri, 5 Sep 2025 17:16:34 +0200 Subject: [PATCH 4/7] Update output message for post tasks --- roles/sap_hana_install/tasks/post_install.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/sap_hana_install/tasks/post_install.yml b/roles/sap_hana_install/tasks/post_install.yml index 8e9bd6d42..1e58f2f5a 100644 --- a/roles/sap_hana_install/tasks/post_install.yml +++ b/roles/sap_hana_install/tasks/post_install.yml @@ -133,10 +133,10 @@ Firewall is enabled and SAP HANA ports are open. {% endif %} {% if sap_hana_install_modify_selinux_labels %} - SElinux policies are configured for SAP folders '/usr/sap/' + SELinux file contexts are configured for SAP folders '{{ sap_hana_install_root_path }}' and '/usr/sap'. {% endif %} {% if ansible_os_family == "RedHat" and sap_hana_install_use_fapolicyd and "fapolicyd" in ansible_facts.packages %} - Fapolicyd is configured. + Fapolicyd is configured for SAP folders '{{ sap_hana_install_root_path }}' and '/usr/sap'. {% endif %} when: - not ansible_check_mode From 6b61b09c6fc14eea66c528038f26abe9ed554e27 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Thu, 11 Sep 2025 12:34:42 +0200 Subject: [PATCH 5/7] fix conditionals for addhosts execution and reflect it in readme --- roles/sap_hana_install/README.md | 29 ++++++++++++++++----------- roles/sap_hana_install/tasks/main.yml | 17 +++++++--------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/roles/sap_hana_install/README.md b/roles/sap_hana_install/README.md index f1bca7492..e0c8490ae 100644 --- a/roles/sap_hana_install/README.md +++ b/roles/sap_hana_install/README.md @@ -231,6 +231,7 @@ in a temporary directory for use by the hdblcm command in the next step. - Print a short summary of the result of the installation. ### Add hosts to an existing SAP HANA Installation +Executes `hdblcm` to install SAP HANA database on new host, where SAP HANA is not installed yet, and connect it to host where SAP HANA is already installed. #### Pre-Install @@ -257,7 +258,7 @@ in a temporary directory for use by the hdblcm command in the next step. ```yaml --- - name: Ansible Play for SAP HANA installation - One host - hosts: all + hosts: host0 become: true tasks: - name: Execute Ansible Role sap_hana_install @@ -265,16 +266,18 @@ in a temporary directory for use by the hdblcm command in the next step. name: community.sap_install.sap_hana_install vars: sap_hana_install_software_directory: /software/hana - sap_hana_install_common_master_password: 'NewPass$321' + sap_hana_install_common_master_password: 'My SAP HANA Master Password' sap_hana_install_sid: 'H01' sap_hana_install_instance_nr: '00' ``` #### Example playbook for installing a new scale-out SAP HANA system +Installs SAP HANA on `host0` and other hosts listed in `sap_hana_install_addhosts`: `host1` and `host2`.
+**NOTE:** Requires working SSH communication between hosts. ```yaml --- - name: Ansible Play for SAP HANA installation - Scale-out - hosts: all + hosts: host0 become: true tasks: - name: Execute Ansible Role sap_hana_install @@ -282,18 +285,20 @@ in a temporary directory for use by the hdblcm command in the next step. name: community.sap_install.sap_hana_install vars: sap_hana_install_software_directory: /software/hana - sap_hana_install_common_master_password: 'NewPass$321' - sap_hana_install_root_password: 'NewPass$321' - sap_hana_install_addhosts: 'host2:role=worker,host3:role=worker:group=g02,host4:role=standby:group=g02' + sap_hana_install_common_master_password: 'My SAP HANA Master Password' + sap_hana_install_root_password: 'My root password' + sap_hana_install_addhosts: 'host0:role=worker,host1:role=worker:group=g02,host2:role=standby:group=g02' sap_hana_install_sid: 'H01' sap_hana_install_instance_nr: '00' ``` #### Example playbook for adding additional nodes to an existing SAP HANA installation +Installs SAP HANA on `host1` and `host2`, then connects them to existing `host0` defined in `sap_hana_install_addhosts`.
+**NOTE:** Requires working SSH communication between hosts. ```yaml --- -- name: Ansible Play for SAP HANA installation - Add host - hosts: all +- name: Ansible Play for SAP HANA installation - Add hosts + hosts: host1, host2 become: true tasks: - name: Execute Ansible Role sap_hana_install @@ -301,10 +306,10 @@ in a temporary directory for use by the hdblcm command in the next step. name: community.sap_install.sap_hana_install vars: sap_hana_install_software_directory: /software/hana - sap_hana_install_new_system: no - sap_hana_install_addhosts: 'host2:role=worker,host3:role=worker:group=g02,host4:role=standby:group=g02' - sap_hana_install_common_master_password: 'NewPass$321' - sap_hana_install_root_password: 'NewPass$321' + sap_hana_install_new_system: false + sap_hana_install_addhosts: 'host0:role=worker,host1:role=worker:group=g02,host2:role=standby:group=g02' + sap_hana_install_common_master_password: 'My SAP HANA Master Password' + sap_hana_install_root_password: 'My root password' sap_hana_install_sid: 'H01' sap_hana_install_instance_nr: '00' ``` diff --git a/roles/sap_hana_install/tasks/main.yml b/roles/sap_hana_install/tasks/main.yml index e9811f6da..ecde4a6a0 100644 --- a/roles/sap_hana_install/tasks/main.yml +++ b/roles/sap_hana_install/tasks/main.yml @@ -156,19 +156,16 @@ ansible.builtin.include_tasks: file: hana_install.yml - -- name: SAP HANA addhosts steps - ansible.builtin.include_tasks: - file: hana_addhosts.yml - when: - - not sap_hana_install_new_system | d(true) - - __sap_hana_install_fact_is_installed | d(false) + # addhosts will be run only on new host, where SAP HANA is not installed + - name: SAP HANA addhosts steps + ansible.builtin.include_tasks: + file: hana_addhosts.yml + when: + - not sap_hana_install_new_system | d(true) # post_install is modular task file, that contains both installation and configuration tasks. -# addhosts should not execute post_install steps, therefore we use sap_hana_install_new_system. +# This is executed for existing and new installations, further driven by '__sap_hana_install_fact_is_installed'. - name: SAP HANA post-install steps ansible.builtin.include_tasks: file: post_install.yml - when: - - sap_hana_install_new_system | d(true) From f74a0b643b5b95f60346d8abdff2b1fa6e03baed Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Thu, 11 Sep 2025 14:46:02 +0200 Subject: [PATCH 6/7] restore conditionals to resolve issue with addhosts tasks --- roles/sap_hana_install/tasks/main.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/roles/sap_hana_install/tasks/main.yml b/roles/sap_hana_install/tasks/main.yml index ecde4a6a0..9b1ea5e74 100644 --- a/roles/sap_hana_install/tasks/main.yml +++ b/roles/sap_hana_install/tasks/main.yml @@ -141,12 +141,9 @@ # Installation tasks have to be run only for new installations. # Configuration tasks have to be run always to ensure idempotency. - name: Install SAP HANA - when: - - not __sap_hana_install_fact_is_installed | d(false) - - sap_hana_install_new_system | d(true) + when: not __sap_hana_install_fact_is_installed | d(false) block: - # pre_install.yml currently contains no configuration tasks. - name: SAP HANA pre-install steps ansible.builtin.include_tasks: file: pre_install.yml @@ -155,14 +152,13 @@ - name: SAP HANA installation steps ansible.builtin.include_tasks: file: hana_install.yml + when: sap_hana_install_new_system | d(true) # addhosts will be run only on new host, where SAP HANA is not installed - name: SAP HANA addhosts steps ansible.builtin.include_tasks: file: hana_addhosts.yml - when: - - not sap_hana_install_new_system | d(true) - + when: not sap_hana_install_new_system | d(true) # post_install is modular task file, that contains both installation and configuration tasks. # This is executed for existing and new installations, further driven by '__sap_hana_install_fact_is_installed'. From 2f66417fc3d97d0b981d986414e3aa78ad595550 Mon Sep 17 00:00:00 2001 From: Marcel Mamula Date: Mon, 15 Sep 2025 11:05:30 +0200 Subject: [PATCH 7/7] update readme to show addhosts example --- roles/sap_hana_install/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/roles/sap_hana_install/README.md b/roles/sap_hana_install/README.md index e0c8490ae..da35f4cad 100644 --- a/roles/sap_hana_install/README.md +++ b/roles/sap_hana_install/README.md @@ -231,7 +231,6 @@ in a temporary directory for use by the hdblcm command in the next step. - Print a short summary of the result of the installation. ### Add hosts to an existing SAP HANA Installation -Executes `hdblcm` to install SAP HANA database on new host, where SAP HANA is not installed yet, and connect it to host where SAP HANA is already installed. #### Pre-Install @@ -293,12 +292,12 @@ Installs SAP HANA on `host0` and other hosts listed in `sap_hana_install_addhost ``` #### Example playbook for adding additional nodes to an existing SAP HANA installation -Installs SAP HANA on `host1` and `host2`, then connects them to existing `host0` defined in `sap_hana_install_addhosts`.
+Installs SAP HANA on `host1` and `host2`, while running on host `host0` where existing SAP HANA is installed.
**NOTE:** Requires working SSH communication between hosts. ```yaml --- - name: Ansible Play for SAP HANA installation - Add hosts - hosts: host1, host2 + hosts: host0 become: true tasks: - name: Execute Ansible Role sap_hana_install