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/README.md b/roles/sap_hana_install/README.md index f1bca7492..da35f4cad 100644 --- a/roles/sap_hana_install/README.md +++ b/roles/sap_hana_install/README.md @@ -257,7 +257,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 +265,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 +284,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`, 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 host - hosts: all +- name: Ansible Play for SAP HANA installation - Add hosts + hosts: host0 become: true tasks: - name: Execute Ansible Role sap_hana_install @@ -301,10 +305,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/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..9b1ea5e74 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,49 @@ - 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) block: - 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 + 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.import_tasks: hana_addhosts.yml + ansible.builtin.include_tasks: + file: 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 +# 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'. +- name: SAP HANA post-install steps + ansible.builtin.include_tasks: + file: post_install.yml diff --git a/roles/sap_hana_install/tasks/post_install.yml b/roles/sap_hana_install/tasks/post_install.yml index 44ee52a80..1e58f2f5a 100644 --- a/roles/sap_hana_install/tasks/post_install.yml +++ b/roles/sap_hana_install/tasks/post_install.yml @@ -1,23 +1,33 @@ # 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 + - name: SAP HANA Post Install - Recreate the initial tenant database + ansible.builtin.include_tasks: + 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: @@ -25,24 +35,13 @@ 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 - when: sap_hana_install_recreate_tenant_database | d(true) - -# Optional Post Install Tasks + when: sap_hana_install_set_sidadm_noexpire | d(true) -# 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 +50,54 @@ 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'. - - - 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 + # 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 - 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 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 - 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) +# Idempotent tasks for new and existing HANA Systems +- 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 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) +- 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,30 @@ 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 - Display SAP HANA details and completed post tasks + ansible.builtin.debug: + msg: | + 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 }} + + {% if sap_hana_install_update_firewall %} + Firewall is enabled and SAP HANA ports are open. + {% endif %} + {% if sap_hana_install_modify_selinux_labels %} + 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 for SAP folders '{{ sap_hana_install_root_path }}' and '/usr/sap'. + {% endif %} 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 }}" - -# 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 + - 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: