diff --git a/roles/sap_hana_install/README.md b/roles/sap_hana_install/README.md index 48fed18d6..a713de00d 100644 --- a/roles/sap_hana_install/README.md +++ b/roles/sap_hana_install/README.md @@ -23,6 +23,9 @@ Managed nodes: - Directory with SAP Installation media is present and `sap_install_media_detect_source_directory` updated. Download can be completed using [community.sap_launchpad](https://github.com/sap-linuxlab/community.sap_launchpad). - Ensure that servers are configured for SAP HANA. See [Recommended](#recommended) section. - Ensure that volumes and filesystems are configured correctly. See [Recommended](#recommended) section. + - SAP HANA Scale-Out requires shared filesystems: + - `/hana/shared` customizable in the variable `sap_hana_install_shared_path`. + - `/lss/shared` customizable in the variable `sap_hana_install_lss_inst_path`. **Specific to SAP HANA 2.0 SPS08 or higher.** ### Prepare SAP HANA installation media @@ -143,6 +146,27 @@ of this file will not be reflected. ## Execution +This Ansible Role can be executed in following scenarios: +1. Install new SAP HANA System on one host. + - `sap_hana_install_new_system` is `true`. + - `sap_hana_install_addhosts` is not defined or empty String. + - Playbook inventory: One host. + +2. Install new SAP HANA System on multiple hosts for High Availability. + - `sap_hana_install_new_system` is `true`. + - `sap_hana_install_addhosts` is not defined or empty String. + - Playbook inventory: Multiple hosts. + +3. Install new SAP HANA Scale-Out System on multiple hosts. + - `sap_hana_install_new_system` is `true`. + - `sap_hana_install_addhosts` is defined as valid addhosts String. + - Playbook inventory: Multiple hosts. + +4. Install new hosts to existing SAP HANA Scale-Out System + - `sap_hana_install_new_system` is `false`. + - `sap_hana_install_addhosts` is defined as valid addhosts String. + - `sap_hana_install_sapadm_password` is defined. + - Playbook inventory: Multiple hosts. @@ -154,101 +178,135 @@ It is recommended to execute this role together with other roles in this collect 4. *`sap_hana_install`* -### Execution Flow -#### Perform Initial Checks - -These checks will be performed by default but can be skipped by setting `sap_hana_install_force` to `true`. -- If variable `sap_hana_install_check_sidadm_user` is undefined or set to `yes`: Check if user sidadm exists. If yes, - abort the role. -- Check if `/usr/sap/hostctrl/exe/saphostctrl` exists and get info on running HANA instances: - - If a conflicting instances exist, the role aborts with a failure - - If the desired instance is running, the role aborts with success -- If `/usr/sap/hostctrl/exe/saphostctrl` does not exist: - - Check if the directory `/hana/shared/` exists. If yes and not empty, abort the role. - - Check if the directory `/usr/sap/` exists. If yes and not empty, abort the role. - -#### Pre-Install - -- Set all passwords to follow master password if set to 'y'. - -- Prepare the software located in directory `sap_hana_install_software_directory`: - - - If file `hdblcm` is found, skip the next step and proceed with the `hdblcm` existence check. - - - If file `hdblcm` is not found, proceed with the next step. - -- Prepare SAR files for `hdblcm`: - - - Get a list of hardware matching SAPCAR executables from `sap_hana_install_software_directory` in case its file name is not - provided by role variable. - - - Select the most recent version of SAPCAR from the hardware matching SAPCAR executables identified before. - - - Get all SAR files from `sap_hana_install_software_directory` or use the SAR files provided by the corresponding role variable, if set. - - - Extract all SAR files into `sap_hana_install_software_extract_directory`. - -Note: For each SAPCAR or SAR file called or used by the role, if variable `sap_hana_install_verify_checksums` -is set to `yes`, the role will perform a checksum verification against a specific or global checksum file. - -- Check existence of `hdblcm` in `SAP_HANA_DATABASE` directory from the extracted SAR files. - -- Check the existence of file `configfile.cfg` in the directory `configfiles` below `sap_hana_install_software_extract_directory`. - -If this file exists, copy it to a temporary directory for use by the hdblcm command. Be aware that when using this file, -any modifications to role variables after creation of this file will not be reflected. - -If this file is not present, perform the following three steps: - -- Create a hdblcm configfile template directly from the hdblcm command, using option `dump_configfile_template`. - -- Convert the configfile template into a Jinja2 template and download it to the control node. - -- Process the Jinja2 template, using the configured role variables or default settings, to create a customized hdblm configfile -in a temporary directory for use by the hdblcm command in the next step. - -#### SAP HANA Install - -- Execute hdblcm, using the configfile mentioned above. - -#### Post-Install - -- Create and Store Connection Info in hdbuserstore. - -- Set Log Mode key to overwrite value and apply to system. - -- Apply SAP HANA license to the new deployed instance if set to `yes`. - -- Set expiry of Unix created users to `never`. - -- Update `/etc/hosts` (optional - `yes` by default). - -- Apply firewall rules (optional - `no` by default). - -- Generate input file for `sap_swpm`. - -- Print a short summary of the result of the installation. - -### Add hosts to an existing SAP HANA Installation - -#### Pre-Install - -- Process SAP HANA configfile based on input parameters. - -#### SAP HANA Add Hosts - -- For each host to be added, check if there is: - - an instance profile in `/hana/shared//profile/_HDB_` - - a directory `/usr/sap//HDB/` - - an entry in the output of `./hdblcm --list_systems` - If any of the above is true, abort the role. - -- Execute hdblcm. - -#### Post-Install - -- Print a short summary of the result of the installation. +### Execution Flow +#### Validate mandatory variables +- If the mandatory variables are undefined or invalid (e.g. empty string, wrong length, etc.), abort the role with failure. Variables that are mandatory: + - `sap_hana_install_sid` + - `sap_hana_install_number` + - `sap_hana_install_master_password` + - `sap_hana_install_addhosts` if the variable `sap_hana_install_new_system` is set to `false`. +- All other password variables are set to the value of `sap_hana_install_master_password` if `sap_hana_install_use_master_password` is set to `y`. +- If the variable `sap_hana_install_new_system` is undefined or invalid and `sap_hana_install_master_password` is not set to `true`, abort the role with failure. + + +#### Check existing installation +This part is performed when: +- Always, unless `sap_hana_install_force` is set to `true`. + +- If the file `/usr/sap/hostctrl/exe/saphostctrl` is present, get a list of instances with `saphostctrl -function ListInstances`: + - If an instance with the same SID and Instance Number is found, skip Pre-Tasks and Installation and proceed to either Addhosts or Post-Tasks. + - If an instance with the same SID but different Instance number is found, abort the role with failure. + - If an instance with the same Instance number but different SID is found, abort the role with failure. +- If the file `/usr/sap/hostctrl/exe/saphostctrl` is not present: + - If the directory `/hana/shared/` exists and contains files, abort the role with failure. + - If the directory `/usr/sap/` exists and contains files, abort the role with failure. + - If the variable `sap_hana_install_groupid` is defined, check if group `sapsys` already exists: + - If it already exists with a different group ID, abort the role with failure. + - If the variable `sap_hana_install_check_sidadm_user` is defined, check if user `` already exists: + - If it already exists, abort the role with failure. +- If the existing instance was not found when adding hosts, abort the role with failure. + + +#### Check Addhosts +This part is performed when: +- The variable `sap_hana_install_addhosts` is defined and not empty String. + +**Addhosts are relevant to both Installation and Addhosts operations, because we need to delegate Pre-Tasks and Post-Tasks to them.** + +Steps: +1. If the variable `sap_hana_install_addhosts` does not contain hosts, abort the role with failure. + - This list of the `all hosts` is used for all Post-Tasks steps for idempotency. +2. Gather list of all Instance profiles in `/hana/shared//profile/`. +3. Gather list of all directories in `/usr/sap//HDB/`. +4. If the existing instance profile or directory was found in hosts list, create separate list without them. + - This list of the `new hosts` is used for one-time tasks. + + +#### Pre-Tasks for Installation +This part is performed when: +- The variable `sap_hana_install_new_system` is set to `true`. +- Existing SAP HANA was not detected. + +Steps: +1. If the variable `sap_hana_install_use_fapolicyd` is set to `true` and operating system is `RedHat`, install and disable `fapolicyd` on all new hosts. +2. Configure permissions for the SAP HANA directories on all new hosts. +3. If the variable `sap_hana_install_modify_selinux_labels` is set to `true`, configure `SElinux` on all new hosts. +4. Prepare the directory defined in variable `sap_hana_install_software_directory`. +5. If the `hdblcm` was not found in the directory `sap_hana_install_software_directory`: + - Find latest `SAPCAR` executable in the directory `sap_hana_install_software_directory` and use latest one matching OS Architecture. + - Extract found `SAR` files using selected `SAPCAR` executable. + - If the variable `sap_hana_install_verify_checksums` is set to `true`, validate checksum. +6. If the file `configfiles/configfile.cfg` is found in the directory defined in `sap_hana_install_software_directory`, make copy of it and use it for installation. + - If the file was not found, create template using `hdblcm` command and fill it in with jinja2 template. + + +#### Pre-Tasks for Addhosts +This part is performed when: +- The variable `sap_hana_install_new_system` is set to `false`. +- Existing SAP HANA was detected. +- New hosts identified in the variable `sap_hana_install_addhosts`. + +Steps: +1. Gather details of user `adm` and group `sapsys` on managed node. + - If the user or group is not present, abort the role with failure. + - Generate password hash for `sapadm` user using the value of `sap_hana_install_sapadm_password` variable. +2. Create the user `adm` on all addhosts. + - This is not required during installation, because the `root` user is used instead. +3. If the variable `sap_hana_install_use_fapolicyd` is set to `true` and operating system is `RedHat`, install and disable `fapolicyd` on all new hosts. +4. Configure permissions for the SAP HANA directories on all new hosts. +5. If the variable `sap_hana_install_modify_selinux_labels` is set to `true`, configure `SElinux` on all new hosts. +6. If the file `configfiles/configfile.cfg` is found in the directory defined in `sap_hana_install_software_directory`, make copy of it and use it for installation. + - If the file was not found, create template using `hdblcm` command and fill it in with jinja2 template. + + +#### Installation +This part is performed when: +- The variable `sap_hana_install_new_system` is set to `true`. +- Existing SAP HANA was not detected. + +Steps: +1. Execute the `hdblcm` executable in the directory `sap_hana_install_software_directory` using the configfile prepared in pre-tasks. + + +#### Addhosts +This part is performed when: +- The variable `sap_hana_install_new_system` is set to `false`. +- Existing SAP HANA was detected. +- New hosts identified in the variable `sap_hana_install_addhosts`. + +Steps: +1. Prepare new addhosts string only with new hosts and update `configfile.cfg`. +2. Execute the `hdblcm` executable in the directory `/hana/shared//hdblcm/` using the configfile prepared in pre-tasks. + + +#### Post-Tasks for Installation +This part is performed when: +- The variable `sap_hana_install_new_system` is set to `true`. + +Steps: +1. Update Secure User Store configuration (`hdbuserstore`) for `adm` user, for new installations. +2. Set Log Mode key to overwrite value and apply to system, for new installations. +3. Apply SAP HANA license if the variable `sap_hana_install_apply_license` is set to `true`, for new installations. +4. Recreate the initial tenant database if the variable `sap_hana_install_recreate_tenant_database` is set to `true`, for new installations. +5. Set expiration of unix users to `never` if the variable `sap_hana_install_set_sidadm_noexpire` is set to `true`, for new installations. +6. Apply firewall rules if the variable `sap_hana_install_update_firewall` is set to `true`. +7. Apply SElinux policies if the variable `sap_hana_install_modify_selinux_labels` is set to `true`. +8. (Red Hat specific) Configure `fapolicyd` if the variable `sap_hana_install_use_fapolicyd` is set to `true`. +9. Output final status of installed system. + + +#### Post-Tasks for Addhosts +This part is performed when: +- The variable `sap_hana_install_new_system` is set to `false`. + +Steps: +1. Update Secure User Store configuration (`hdbuserstore`) for `adm` user, for new hosts. +5. Set expiration of unix users to `never` if the variable `sap_hana_install_set_sidadm_noexpire` is set to `true`, for new hosts. +6. Apply firewall rules if the variable `sap_hana_install_update_firewall` is set to `true`. +7. Apply SElinux policies if the variable `sap_hana_install_modify_selinux_labels` is set to `true`. +8. (Red Hat specific) Configure `fapolicyd` if the variable `sap_hana_install_use_fapolicyd` is set to `true`. +9. Output final status of installed system. ### Example @@ -276,7 +334,7 @@ Installs SAP HANA on `host0` and other hosts listed in `sap_hana_install_addhost ```yaml --- - name: Ansible Play for SAP HANA installation - Scale-out - hosts: host0 + hosts: host0, host1, host2, host3 become: true tasks: - name: Execute Ansible Role sap_hana_install @@ -286,7 +344,7 @@ Installs SAP HANA on `host0` and other hosts listed in `sap_hana_install_addhost sap_hana_install_software_directory: /software/hana sap_hana_install_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_addhosts: 'host1:role=worker,host2:role=worker:group=g02,host3:role=standby:group=g02' sap_hana_install_sid: 'H01' sap_hana_install_instance_nr: '00' ``` @@ -297,7 +355,7 @@ Installs SAP HANA on `host1` and `host2`, while running on host `host0` where ex ```yaml --- - name: Ansible Play for SAP HANA installation - Add hosts - hosts: host0 + hosts: host0, host1 become: true tasks: - name: Execute Ansible Role sap_hana_install @@ -306,9 +364,9 @@ Installs SAP HANA on `host1` and `host2`, while running on host `host0` where ex vars: sap_hana_install_software_directory: /software/hana 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_addhosts: 'host1,host2' sap_hana_install_master_password: 'My SAP HANA Master Password' - sap_hana_install_root_password: 'My root password' + sap_hana_install_sapadm_password: 'My sapadm password' sap_hana_install_sid: 'H01' sap_hana_install_instance_nr: '00' ``` @@ -325,7 +383,7 @@ With the following tags, the role can be called to perform certain activities on with `--skip-tags`, to skip modifying these directories. This can be useful when using tag `sap_hana_install_preinstall`. - tag `sap_hana_install_configure_firewall`: Use this flag to only configure the firewall ports for - SAP HANA. Note: The role variable `sap_hana_install_update_firewall` has to be set to `yes` as + SAP HANA. Note: The role variable `sap_hana_install_update_firewall` has to be set to `true` as well. - tag `sap_hana_install_extract_sarfiles`: Use this flag with `--skip-tags` to run the SAR file preparation steps of tag `sap_hana_install_prepare_sarfiles` without extracting the SAR files. @@ -383,15 +441,17 @@ With the following tags, the role can be called to perform certain activities on - If you don't want to install LSS, the simplest way is to set parameter `sap_hana_install_components: 'server'` (the default is `all`). - If you want to install LSS, check/set the following parameters and adjust accordingly as the defaults may not be suitable (list below shows the default values hdblcm will use): ``` - sap_hana_insall_lss_inst_path: /lss/shared - sap_hana_insall_lss_user_password: '' - sap_hana_insall_lss_userid: '' - sap_hana_insall_lss_groupid: '' - sap_hana_insall_lss_user_home: /usr/sap/${SID}/lss/home - sap_hana_insall_lss_user_shell: /bin/sh - sap_hana_insall_lss_backup_password: '' + sap_hana_install_lss_inst_path: /lss/shared + sap_hana_install_lss_user_password: '' + sap_hana_install_lss_userid: '' + sap_hana_install_lss_groupid: '' + sap_hana_install_lss_user_home: /usr/sap/${SID}/lss/home + sap_hana_install_lss_user_shell: /bin/sh + sap_hana_install_lss_backup_password: '' sap_hana_install_secure_store: localsecurestore ``` +> **NOTE**: SAP HANA 2.0 SPS08 requires LSS filesystem to be shared across all Scale-Out (cluster) hosts.
+> This role will check if directory defined in `sap_hana_insall_lss_inst_path` is present for SPS08 or higher and if it is mounted as shared file system. - ### Additional examples For more examples on how to use this role in different installation scenarios, refer to the [ansible.playbooks_for_sap](https://github.com/sap-linuxlab/ansible.playbooks_for_sap) playbooks. @@ -405,6 +465,7 @@ Apache 2.0 ## Maintainers - [Bernd Finger](https://github.com/berndfinger) +- [Marcel Mamula](https://github.com/marcelmamula) ## Role Variables @@ -442,7 +503,7 @@ Default is `True`, in which case the installation will not be performed if the ` - _Type:_ `bool` - _Default:_ `true` -Set to `true` to ensure the SAP system user `{{ sap_hana_install_sid | lower }}adm` is configured with a non-expiring password. +Set to `true` to ensure the SAP system user `{{ sap_hana_install_sid | lower }}adm` is configured with a non-expiring password.
Set to `false` to skip this step — typically done when the user is managed by a central identity provider (e.g. Active Directory or LDAP). ### sap_hana_install_new_system @@ -453,12 +514,19 @@ Set to `false` to skip this step — typically done when the user is managed by Set to `False` to use existing SAP HANA database and add more hosts using variable `sap_hana_install_addhosts`.
Default is `True`, in which case fresh SAP HANA installation will be performed. +### sap_hana_install_addhosts + +- _Type:_ `string` + +If the following variable is specified, the role will perform a scaleout installation or it will add additional hosts to an existing SAP HANA system.
+Example: `sap_hana_install_addhosts: 'host2:role=worker,host3:role=worker:group=g02,host4:role=standby:group=g02',host5`. + ### sap_hana_install_update_firewall - _Type:_ `bool` - _Default:_ `False` -The role can be configured to also set the required firewall ports for SAP HANA. If this is desired, set the variable `sap_hana_install_update_firewall` to `yes` (default is `no`).
+The role can be configured to also set the required firewall ports for SAP HANA. If this is desired, set the variable `sap_hana_install_update_firewall` to `true` (default is `false`).
The firewall ports are defined in a variable which is compatible with the variable structure used by Linux System Role `firewall`.
The firewall ports for SAP HANA are defined in member `port` of the first field of variable `sap_hana_install_firewall` (`sap_hana_install_firewall[0].port`), see file `defaults/main.yml`.
If the member `state` is set to `enabled`, the ports will be enabled. If the member `state` is set to `disabled`, the ports will be disabled, which might be useful for testing.
diff --git a/roles/sap_hana_install/defaults/main.yml b/roles/sap_hana_install/defaults/main.yml index ac9f49550..658abc45a 100644 --- a/roles/sap_hana_install/defaults/main.yml +++ b/roles/sap_hana_install/defaults/main.yml @@ -165,7 +165,7 @@ sap_hana_install_use_master_password: 'y' # sap_hana_install_lss_backup_password: # sap_hana_install_ase_user_password: # sap_hana_install_root_password: -# sap_hana_install_sapadm_password: +# sap_hana_install_sapadm_password: # This password is required when adding hosts with `sap_hana_install_new_system: false` # sap_hana_install_xs_org_password: # Optional steps @@ -201,6 +201,9 @@ sap_hana_install_firewall: sap_hana_install_hdbuserstore_key: 'HDB_SYSTEMDB' sap_hana_install_nw_input_location: '/tmp' +# Overwrite existing hdbuserstore configuration. +sap_hana_install_hdbuserstore_force: false + # License sap_hana_install_apply_license: false # sap_hana_install_license_path: @@ -236,6 +239,10 @@ sap_hana_install_create_initial_tenant: 'y' # Example: # sap_hana_install_addhosts: 'host2:role=worker,host3:role=worker:group=g02,host4:role=standby:group=g02' +# Define hostname of master server where addhosts operation will be executed. +# If undefined, master specific steps will be executed on first host in the play. +# sap_hana_install_scaleout_master: '' + # The hostname is set by 'hdblcm --dump_configfile_template' during the preinstall phase but can also # be set to a different value in your playbook or hostvars: # sap_hana_install_hostname: diff --git a/roles/sap_hana_install/tasks/assert-addhosts-loop-block.yml b/roles/sap_hana_install/tasks/assert-addhosts-loop-block.yml deleted file mode 100644 index 0b79a30a3..000000000 --- a/roles/sap_hana_install/tasks/assert-addhosts-loop-block.yml +++ /dev/null @@ -1,38 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- - -- name: SAP HANA Add Hosts - Check for SAP HANA instance profile for '{{ line_item }}' - ansible.builtin.stat: - path: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/profile/{{ sap_hana_install_sid }}_HDB{{ sap_hana_install_number }}_{{ line_item }}" - register: __sap_hana_install_register_instance_profile_addhost - -- name: SAP HANA Add Hosts - Show the path name of the instance profile - ansible.builtin.debug: - msg: >- - Instance profile: '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/profile/ - {{ sap_hana_install_sid }}_HDB{{ sap_hana_install_number }}_{{ line_item }}' - -- name: SAP HANA Add Hosts - Assert that there is no instance profile for the additional hosts - ansible.builtin.assert: - that: not __sap_hana_install_register_instance_profile_addhost.stat.exists - fail_msg: >- - FAIL: Addhost operation will not be performed because there is already an instance profile for host {{ line_item }} at - {{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/profile/{{ sap_hana_install_sid }}_HDB{{ sap_hana_install_number }}_{{ line_item }} - success_msg: "PASS: No instance profile was found for host '{{ line_item }}'." - -- name: SAP HANA Add Hosts - Check for SAP HANA instance directory in '/usr/sap' - ansible.builtin.stat: - path: "/usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/{{ line_item }}" - register: __sap_hana_install_register_usr_sap_instance_directory - -- name: SAP HANA Add Hosts - Show the path name of the instance directory in '/usr/sap' - ansible.builtin.debug: - msg: "Instance directory in /usr/sap: '/usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/{{ line_item }}'" - -- name: SAP HANA Add Hosts - Assert that there is no SAP HANA instance directory in '/usr/sap' for the additional hosts - ansible.builtin.assert: - that: not __sap_hana_install_register_usr_sap_instance_directory.stat.exists - fail_msg: >- - FAIL: Addhost operation will not be performed because there is already an instance directory for host {{ line_item }} at location - /usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/{{ line_item }} - success_msg: "PASS: No instance directory was found for host '{{ line_item }}' in /usr/sap." diff --git a/roles/sap_hana_install/tasks/hana_addhosts.yml b/roles/sap_hana_install/tasks/hana_addhosts.yml index 9f65c381f..5543c1be3 100644 --- a/roles/sap_hana_install/tasks/hana_addhosts.yml +++ b/roles/sap_hana_install/tasks/hana_addhosts.yml @@ -1,99 +1,63 @@ # SPDX-License-Identifier: Apache-2.0 --- +# This file is executed only if we detected addhosts that are not present yet. +# We need to create new updated addhosts string after removing existing hosts. +# New addhosts string has to be injected into configfile, +# because we cannot override user set 'sap_hana_install_addhosts' due to precedence. -- name: SAP HANA Add Hosts - Fill new variable __sap_hana_install_addhosts_hosts +- name: SAP HANA - Addhosts - Set fact for updated addhosts string ansible.builtin.set_fact: - __sap_hana_install_addhosts_hosts: "{{ __sap_hana_install_addhosts_hosts | d([]) + [item.split(':')[0]] }}" - with_items: "{{ sap_hana_install_addhosts.split(',') }}" + __sap_hana_install_fact_addhosts: "{{ __sap_hana_install_fact_addhosts | d([]) + [item] }}" + loop: "{{ sap_hana_install_addhosts.split(',') | map('trim') | reject('equalto', '') | list }}" + when: + - item.split(':')[0] in __sap_hana_install_fact_addhosts_hosts_new -- name: SAP HANA Add Hosts - Show the contents of __sap_hana_install_addhosts_hosts - ansible.builtin.debug: - var: __sap_hana_install_addhosts_hosts - -- name: SAP HANA Add Hosts - Show the additional hosts to be added - ansible.builtin.debug: - msg: "Additional hosts: '{{ __sap_hana_install_addhosts_hosts }}'" - -- name: SAP HANA Add Hosts - Make sure the additional hosts are not yet part of the exiting SAP HANA system - file checks - ansible.builtin.include_tasks: assert-addhosts-loop-block.yml - loop: "{{ __sap_hana_install_addhosts_hosts }}" - loop_control: - loop_var: line_item - -- name: SAP HANA Add Hosts - Make sure the additional hosts are not yet part of the exiting SAP HANA system - hdblcm checks - when: not ansible_check_mode - block: - -# Reason for noqa: We can safely fail at the last command in the pipeline. - - name: SAP HANA Add Hosts - Run 'hdblcm --list_systems' # noqa risky-shell-pipe - ansible.builtin.shell: | - ./hdblcm --list_systems | awk '/\/hana\/shared\/{{ sap_hana_install_sid }}/{a=1} - /hosts:/{if (a==1){ - gsub ("^\\s*hosts: ", "");print;a=0} - }' - args: - chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" - register: __sap_hana_install_register_hdblcm_list_systems - changed_when: false - - - name: SAP HANA Add Hosts - Show the output of hdblcm --list_systems - ansible.builtin.debug: - var: __sap_hana_install_register_hdblcm_list_systems +- name: SAP HANA - Addhosts - Update configfile with new addhosts string + ansible.builtin.lineinfile: + path: "{{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg" + regexp: '^addhosts\s*=\s*.*$' + line: "addhosts = {{ __sap_hana_install_fact_addhosts | join(',') }}" - - name: SAP HANA Add Hosts - Assert that the additional hosts are not shown in hdblcm --list_systems - ansible.builtin.assert: - that: line_item not in __sap_hana_install_register_hdblcm_list_systems.stdout - fail_msg: >- - FAIL: The host '{{ line_item }}' is already part of system '{{ sap_hana_install_sid }}' - and addhosts operation will not be performed. - success_msg: "PASS: Host '{{ line_item }}' is not yet part of system '{{ sap_hana_install_sid }}'." - loop: "{{ __sap_hana_install_addhosts_hosts }}" - loop_control: - loop_var: line_item -- name: SAP HANA Add Hosts - Set fact for hdblcm command line +- name: SAP HANA - Addhosts - Set fact for hdblcm command line ansible.builtin.set_fact: - __sap_hana_install_hdblcm_command: "./hdblcm {{ sap_hana_install_hdblcm_extraargs | d('') }} - --action=add_hosts - --password={{ sap_hana_install_sidadm_password | d(sap_hana_install_master_password) }} - --configfile={{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg - -b" + __sap_hana_install_hdblcm_command: >- + ./hdblcm {{ sap_hana_install_hdblcm_extraargs | d('') }} + --action=add_hosts + --password={{ sap_hana_install_sidadm_password | d(sap_hana_install_master_password) }} + {% if __sap_hana_install_fact_is_lss_required %} + --lss_user_password={{ sap_hana_install_lss_user_password | d(sap_hana_install_master_password) }} + {% endif %} + --configfile={{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg + -b tags: sap_hana_install_hdblcm_commandline -- name: SAP HANA Add Hosts - Show the hdblcm addhosts command line +- name: SAP HANA - Addhosts - Show the hdblcm addhosts command line ansible.builtin.debug: - msg: "SAP HANA addhosts command: '{{ __sap_hana_install_hdblcm_command }}'" + msg: >- + SAP HANA addhosts command: + ./hdblcm {{ sap_hana_install_hdblcm_extraargs | d('') }} + --action=add_hosts + --password= + {% if __sap_hana_install_fact_is_lss_required %} + --lss_user_password= + {% endif %} + --configfile={{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg + -b tags: sap_hana_install_hdblcm_commandline -- name: SAP HANA Add Hosts - Add hosts to the existing SAP HANA installation - ansible.builtin.command: "{{ __sap_hana_install_hdblcm_command }}" +- name: SAP HANA - Addhosts - Add hosts to the existing SAP HANA installation + ansible.builtin.command: + cmd: "{{ __sap_hana_install_hdblcm_command }}" register: __sap_hana_install_register_hdblcm_add_hosts args: chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" changed_when: "'SAP HANA Lifecycle Management' in __sap_hana_install_register_hdblcm_add_hosts.stdout" when: not ansible_check_mode -- name: SAP HANA Add Hosts - Show the result of hdblcm add_hosts +- name: SAP HANA - Addhosts - Show the result of hdblcm add_hosts ansible.builtin.debug: - var: __sap_hana_install_register_hdblcm_add_hosts.stdout - when: not ansible_check_mode - -- name: SAP HANA Add Hosts - 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} - /version:/{if (a==1){ - gsub ("^\\s*version: ", "");printf ("version: %s; hosts: ", $NF)} - } - /hosts?:/{if (a==1){ - gsub ("^\\s*hosts?: ", ""); print; a=0} - }' - args: - chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" - register: __sap_hana_install_register_addhosts_result - changed_when: false - when: not ansible_check_mode - -- name: SAP HANA Add Hosts - Show the HANA version and hosts - ansible.builtin.debug: - msg: "HANA system '{{ sap_hana_install_sid }}': {{ __sap_hana_install_register_addhosts_result.stdout }}" - when: not ansible_check_mode + msg: "{{ __sap_hana_install_register_hdblcm_add_hosts.stdout }}" + when: + - not ansible_check_mode + - __sap_hana_install_register_hdblcm_add_hosts.stdout is defined diff --git a/roles/sap_hana_install/tasks/hana_exists.yml b/roles/sap_hana_install/tasks/hana_exists.yml deleted file mode 100644 index 787859538..000000000 --- a/roles/sap_hana_install/tasks/hana_exists.yml +++ /dev/null @@ -1,189 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- - -# Required to reset status if the role is used multiple times in one playbook. -- name: SAP HANA Checks - Reset the status variable if defined from previous run - ansible.builtin.set_fact: - __sap_hana_install_fact_is_installed: false - when: __sap_hana_install_fact_is_installed is defined - -- name: SAP HANA Checks - Check if saphostctrl is installed - ansible.builtin.stat: - path: /usr/sap/hostctrl/exe/saphostctrl - check_mode: false - register: __sap_hana_install_register_stat_saphostctrl - failed_when: false - - -# Check 1: Use found sapcontrol to get list of SAP instances. -# Only valid combination of SID and Instance Number will pass. -- name: SAP HANA Checks - Check if SAP instances are installed with saphostctrl - when: __sap_hana_install_register_stat_saphostctrl.stat.exists - block: - - - name: SAP HANA Checks - Get list of installed SAP instances - ansible.builtin.shell: - cmd: set -o pipefail && /usr/sap/hostctrl/exe/saphostctrl -function ListInstances | cut -d":" -f2- - register: __sap_hana_install_register_instancelist - changed_when: false - - - name: SAP HANA Checks - Display instances - ansible.builtin.debug: - var: __sap_hana_install_register_instancelist.stdout_lines - verbosity: 1 - - - name: SAP HANA Checks - Desired SAP HANA is installed and running - ansible.builtin.set_fact: - __sap_hana_install_fact_is_installed: true - when: - - __sap_hana_install_loop_instance.split('-')[0] | trim == sap_hana_install_sid - - __sap_hana_install_loop_instance.split('-')[1] | trim == sap_hana_install_number - loop: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" - loop_control: - loop_var: __sap_hana_install_loop_instance - label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" - - - name: SAP HANA Checks - Fail if existing SAP 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 - SAP HANA system {{ __sap_hana_install_loop_instance.split('-')[0] | trim }}! - when: - - __sap_hana_install_loop_instance.split('-')[0] | trim != sap_hana_install_sid - - __sap_hana_install_loop_instance.split('-')[1] | trim == sap_hana_install_number - loop: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" - loop_control: - loop_var: __sap_hana_install_loop_instance - label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" - - - name: SAP HANA Checks - Fail if existing SAP HANA was detected with same SID but different instance number - ansible.builtin.fail: - msg: >- - The SAP HANA system {{ sap_hana_install_sid }} already exists with different instance number - {{ __sap_hana_install_loop_instance.split('-')[1] | trim }}!" - when: - - __sap_hana_install_loop_instance.split('-')[0] | trim == sap_hana_install_sid - - __sap_hana_install_loop_instance.split('-')[1] | trim != sap_hana_install_number - loop: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" - loop_control: - loop_var: __sap_hana_install_loop_instance - label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" - - -# Check 2: Check presence of directories if saphostctrl was not found. -# These checks do not set '__sap_hana_install_fact_is_installed' as they pass only if directories are empty. -- name: SAP HANA Checks - Check directories if no saphostctrl is found - when: not __sap_hana_install_register_stat_saphostctrl.stat.exists - block: - - - name: SAP HANA Checks - Get status of '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' - ansible.builtin.stat: - path: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}" - check_mode: false - register: __sap_hana_install_register_stat_hana_shared_sid_assert - failed_when: false - - - name: SAP HANA Checks - Get contents of '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' - ansible.builtin.find: - paths: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}" - patterns: '*' - file_type: 'any' # New install does not have files and default 'file' will ignore directories. - register: __sap_hana_install_register_files_in_hana_shared_sid_assert - when: __sap_hana_install_register_stat_hana_shared_sid_assert.stat.exists - - - name: SAP HANA Checks - Fail if the directory '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' exists and is not empty - ansible.builtin.fail: - msg: "FAIL: The directory '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' exists and is not empty!" - when: - - __sap_hana_install_register_stat_hana_shared_sid_assert.stat.exists - - __sap_hana_install_register_files_in_hana_shared_sid_assert.matched | int != 0 - - - name: SAP HANA Checks - Get status of '/usr/sap/{{ sap_hana_install_sid }}' - ansible.builtin.stat: - path: "/usr/sap/{{ sap_hana_install_sid }}" - check_mode: false - register: __sap_hana_install_register_stat_usr_sap_sid_assert - failed_when: false - - - name: SAP HANA Checks - Get contents of '/usr/sap/{{ sap_hana_install_sid }}' - ansible.builtin.find: - paths: "/usr/sap/{{ sap_hana_install_sid }}" - patterns: '*' - file_type: 'any' # New install does not have files and default 'file' will ignore directories. - register: __sap_hana_install_register_files_in_usr_sap_sid_assert - when: __sap_hana_install_register_stat_usr_sap_sid_assert.stat.exists - - - name: SAP HANA Checks - Fail if the directory '/usr/sap/{{ sap_hana_install_sid }}' exists and is not empty - ansible.builtin.fail: - msg: "FAIL: The directory '/usr/sap/{{ sap_hana_install_sid }}' exists and is not empty!" - when: - - __sap_hana_install_register_stat_usr_sap_sid_assert.stat.exists - - __sap_hana_install_register_files_in_usr_sap_sid_assert.matched | int != 0 - - -# Check 3: Check if the group 'sapsys' exists with correct ID. -# The role supports specifying the SAP HANA group id in variable `sap_hana_install_groupid`, which is the id of the sapsys group. -# The SAP HANA installation will fail if there is already a group named sapsys but with a different ID. Let's better fail before. -- name: SAP HANA Checks - Check SAP HANA admin group - when: - - sap_hana_install_groupid is defined - - sap_hana_install_groupid is string - - sap_hana_install_groupid | trim | length > 0 - - not __sap_hana_install_fact_is_installed | d(false) - block: - - # getent_groups will be populated, with fields: - # [0] - 'X' if the password is set. - # [1] - Group ID. - # [2] - Group members. - - name: SAP HANA Checks - Get details of the 'sapsys' group - ansible.builtin.getent: - database: group - key: sapsys - failed_when: false - - - name: SAP HANA Checks - In case there is a group 'sapsys', assert that its group ID is identical to 'sap_hana_install_groupid' - ansible.builtin.assert: - that: - - getent_group['sapsys'][1] | int == sap_hana_install_groupid | int - success_msg: "PASS: The group ID of 'sapsys' is identical to the value of variable - sap_hana_install_groupid, which is '{{ sap_hana_install_groupid }}'" - fail_msg: >- - FAIL: Group 'sapsys' exists but with a different group ID than '{{ sap_hana_install_groupid }}' - defined in the variable 'sap_hana_install_groupid'! - when: - - getent_group is defined - - "'sapsys' in getent_group" - - -# Check 4: Check if the user 'sidadm' exists. -- name: SAP HANA Checks - SAP HANA admin user check - when: - - sap_hana_install_check_sidadm_user | d(true) - - not __sap_hana_install_fact_is_installed | d(false) - vars: - __sap_hana_install_sidadm: "{{ sap_hana_install_sid | lower }}adm" - block: - - - name: SAP HANA Checks - Get info about user '{{ __sap_hana_install_sidadm }}' - ansible.builtin.getent: - database: passwd - key: "{{ __sap_hana_install_sidadm }}" - failed_when: false - - - name: SAP HANA Checks - Fail if the user '{{ __sap_hana_install_sidadm }}' exists - ansible.builtin.fail: - msg: "FAIL: The user '{{ __sap_hana_install_sidadm }}' already exists!" - when: - - getent_passwd is defined - - __sap_hana_install_sidadm in getent_passwd - - -- name: SAP HANA Checks - Fail if SAP HANA is not found when addhosts is used - ansible.builtin.fail: - msg: | - FAIL: The existing SAP HANA System was not detected when adding new hosts! - This is required when the variable 'sap_hana_install_new_system' is set to false. - when: - - not sap_hana_install_new_system - - not __sap_hana_install_fact_is_installed | d(false) diff --git a/roles/sap_hana_install/tasks/hana_install.yml b/roles/sap_hana_install/tasks/hana_install.yml index 66c480f0b..b6a6c9e99 100644 --- a/roles/sap_hana_install/tasks/hana_install.yml +++ b/roles/sap_hana_install/tasks/hana_install.yml @@ -3,7 +3,7 @@ # Ansible does not support streaming of stdout, so we offer a workaround. # For more information, see https://github.com/ansible/proposals/issues/92 -- name: Install SAP HANA - Copy file tail-f-hdblcm-install-trc.sh to '{{ __sap_hana_install_register_tmpdir.path }}' +- name: SAP HANA - Install - Copy file tail-f-hdblcm-install-trc.sh to '{{ __sap_hana_install_register_tmpdir.path }}' ansible.builtin.copy: src: tmp/tail-f-hdblcm-install-trc.sh dest: "{{ __sap_hana_install_register_tmpdir.path }}/tail-f-hdblcm-install-trc.sh" @@ -12,7 +12,7 @@ mode: '0755' # Show how to use the workaround: -- name: Install SAP HANA - Show how to watch the install process in real time +- name: SAP HANA - Install - Show how to watch the install process in real time ansible.builtin.debug: msg: - 'Once the task "Install SAP HANA" has started, you can use the following command' @@ -21,12 +21,12 @@ - 'Alternatively, you can run the following command on the control node:' - "ssh {{ inventory_hostname }} {{ __sap_hana_install_register_tmpdir.path }}/tail-f-hdblcm-install-trc.sh" -- name: Install SAP HANA - Set fact for the hdblcm verify_signature argument +- name: SAP HANA - Install - Set fact for the hdblcm verify_signature argument ansible.builtin.set_fact: __sap_hana_install_fact_verify_signature: '--verify_signature' when: sap_hana_install_verify_signature -- name: Install SAP HANA - Set fact for the hdblcm command line +- name: SAP HANA - Install - Set fact for the hdblcm command line ansible.builtin.set_fact: __sap_hana_install_hdblcm_command: "./hdblcm {{ sap_hana_install_hdblcm_extraargs | d('') }} {{ __sap_hana_install_fact_verify_signature | d('') }} @@ -34,12 +34,12 @@ -b" tags: sap_hana_install_hdblcm_commandline -- name: Install SAP HANA - Display the hdblcm command line +- name: SAP HANA - Install - Display the hdblcm command line ansible.builtin.debug: msg: "SAP HANA install command: '{{ __sap_hana_install_hdblcm_command }}'" tags: sap_hana_install_hdblcm_commandline -- name: Install SAP HANA - {{ sap_hana_install_sid }} {{ sap_hana_install_number }} +- name: SAP HANA - Install - {{ sap_hana_install_sid }} {{ sap_hana_install_number }} ansible.builtin.command: "{{ __sap_hana_install_hdblcm_command }}" register: __sap_hana_install_register_hdblcm_install_async_job args: @@ -49,7 +49,7 @@ changed_when: true when: not ansible_check_mode -- name: Install SAP HANA - Wait for hdblcm process to exit, poll every 60 seconds +- name: SAP HANA - Install - Wait for hdblcm process to exit, poll every 60 seconds ansible.builtin.shell: cmd: set -o pipefail && ps -ef | awk '/ hdblcm /&&/ {{ __sap_hana_install_configfile_arg }} /&&!/ awk /{print}' register: __sap_hana_install_register_pids_sapinst @@ -60,17 +60,16 @@ __sap_hana_install_configfile_arg: "{{ '--configfile=' + (__sap_hana_install_register_tmpdir.path + '/configfile.cfg') | regex_replace('/', '\\/') }}" changed_when: false -- name: Install SAP HANA - Verify if hdblcm process finished successfully +- name: SAP HANA - Install - Verify if hdblcm process finished successfully ansible.builtin.async_status: jid: "{{ __sap_hana_install_register_hdblcm_install_async_job.ansible_job_id }}" register: __sap_hana_install_register_sapinst failed_when: __sap_hana_install_register_sapinst.finished != 1 or __sap_hana_install_register_sapinst.rc != 0 -- name: Install SAP HANA - Display the hdblcm return code +- name: SAP HANA - Install - Display the hdblcm output ansible.builtin.debug: - msg: "{{ __sap_hana_install_register_sapinst.rc }}" - -- name: Install SAP HANA - Display the hdblcm output - ansible.builtin.debug: - msg: "{{ __sap_hana_install_register_sapinst.stdout_lines }}" + msg: | + Return code: {{ __sap_hana_install_register_sapinst.rc }} + Output: + {{ __sap_hana_install_register_sapinst.stdout_lines }} when: sap_hana_install_display_unattended_output diff --git a/roles/sap_hana_install/tasks/main.yml b/roles/sap_hana_install/tasks/main.yml index 6fa61915f..9b8497354 100644 --- a/roles/sap_hana_install/tasks/main.yml +++ b/roles/sap_hana_install/tasks/main.yml @@ -5,7 +5,7 @@ # Check if variable is defined and non-empty before using it, otherwise fall back to backwards # compatible variable or default empty string that will fail asserts afterwards. # NOTE: This is not __var assignment so it will not override user specified vars due to precedence! -- name: Rename some variables used by hdblcm configfile +- name: SAP HANA - Main - Set mandatory variables used by hdblcm configfile ansible.builtin.set_fact: sap_hana_install_sid: "{{ sap_hana_sid | d('') @@ -25,7 +25,7 @@ - sap_hana_install_configure_firewall # Separate task for password with no_log -- name: Rename some variables used by hdblcm configfile - passwords +- name: SAP HANA - Main - Set mandatory variables used by hdblcm configfile - passwords ansible.builtin.set_fact: sap_hana_install_master_password: "{{ sap_hana_install_common_master_password | d('') @@ -39,9 +39,9 @@ - sap_hana_install_set_log_mode - sap_hana_install_configure_firewall -- name: Validate the role variables +- name: SAP HANA - Main - Validate the role variables ansible.builtin.include_tasks: - file: assert_variables.yml + file: pre_tasks/assert_variables.yml tags: - sap_hana_install_check_hana_exists - sap_hana_install_check_installation @@ -58,9 +58,9 @@ # SAP HANA presence has to be validated for both new system and adding new hosts. -- name: Validate presence of existing SAP HANA database +- name: SAP HANA - Main - Validate presence of existing SAP HANA database ansible.builtin.include_tasks: - file: hana_exists.yml + file: pre_tasks/hana_exists.yml when: - (sap_hana_install_new_system and not sap_hana_install_force) or not sap_hana_install_new_system @@ -69,45 +69,115 @@ - sap_hana_install_preinstall -- name: Ensure SAP HANA is running for existing systems or addhosts operations +- name: SAP HANA - Main - Identify hosts in play based on addhosts ansible.builtin.include_tasks: - file: hana_start.yml - when: __sap_hana_install_fact_is_installed | d(false) + file: pre_tasks/identify_hosts.yml + + +- name: SAP HANA - Main - Ensure SAP HANA is running for existing systems or addhosts operations + ansible.builtin.include_tasks: + file: pre_tasks/hana_start.yml + when: + - __sap_hana_install_fact_is_installed + - __sap_hana_install_fact_is_main_host # Instructions for separating tasks to achieve idempotency: # - Installation - Run once for new installations, never repeated. # - Configuration - Run always to ensure idempotent outcome. -# Pre-installation currently does not contain configuration tasks, which would require idempotency. -# Executed for new installations and addhosts, because addhosts configfile creation is included. -- name: SAP HANA pre-install steps - ansible.builtin.include_tasks: - file: pre_install.yml - tags: sap_hana_install_preinstall +- name: Block for Installation tasks when: - - (sap_hana_install_new_system and not __sap_hana_install_fact_is_installed | d(false)) - or not sap_hana_install_new_system - -# Installation currently does not contain configuration tasks, which would require idempotency. -# Executed only for new installations. -- name: SAP HANA installation steps - ansible.builtin.include_tasks: - file: hana_install.yml - when: - - not __sap_hana_install_fact_is_installed | d(false) - sap_hana_install_new_system + block: + - name: SAP HANA - Install - Pre-Tasks + ansible.builtin.include_tasks: + file: pre_install.yml + tags: sap_hana_install_preinstall -# Executed only for addhosts. -- name: SAP HANA addhosts steps - ansible.builtin.include_tasks: - file: hana_addhosts.yml + - name: SAP HANA - Install + ansible.builtin.include_tasks: + file: hana_install.yml + when: + - not __sap_hana_install_fact_is_installed + - __sap_hana_install_fact_is_main_host + + - name: SAP HANA - Install - Post-tasks + ansible.builtin.include_tasks: + file: post_install.yml + + +- name: Block for Addhosts tasks when: - - __sap_hana_install_fact_is_installed | d(false) - not sap_hana_install_new_system + - __sap_hana_install_fact_is_scaleout + - __sap_hana_install_fact_is_installed + block: + # Execute only if new hosts are to be added. + - name: SAP HANA - Addhosts - Pre-Tasks + ansible.builtin.include_tasks: + file: pre_addhosts.yml + when: + - __sap_hana_install_fact_addhosts_hosts_new | d([]) | length > 0 + tags: sap_hana_install_preinstall -# Post-installation contains both installation and configuration tasks. -# Executed for new or existing installations and addhosts. -- name: SAP HANA post-install steps - ansible.builtin.include_tasks: - file: post_install.yml + - name: SAP HANA - Addhosts + ansible.builtin.include_tasks: + file: hana_addhosts.yml + when: + - __sap_hana_install_fact_addhosts_hosts_new | d([]) | length > 0 + - __sap_hana_install_fact_is_main_host + + - name: SAP HANA - Addhosts - Post-tasks + ansible.builtin.include_tasks: + file: post_addhosts.yml + + +# Show final status of SAP HANA System +# Gather details about installed database for finished message +- name: SAP HANA - Main - Run 'hdblcm --list_systems' after the completion + ansible.builtin.shell: | + set -o pipefail && ./hdblcm --list_systems | awk '/\/hana\/shared\/{{ sap_hana_install_sid }}/{a=1} + /version:/{if (a==1){ + gsub ("^\\s*version: ", "");printf ("%s;", $NF)} + } + /hosts?:/{if (a==1){ + gsub ("^\\s*hosts?: ", ""); gsub (", ", ","); print; a=0} + }' + args: + chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" + register: __sap_hana_install_register_completion_result + changed_when: false + when: + - not ansible_check_mode + - __sap_hana_install_fact_is_main_host + +- name: SAP HANA - Main - 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_new_system and __sap_hana_install_fact_is_installed and __sap_hana_install_fact_addhosts_hosts_new | length > 0 %} + The new hosts defined in the variable 'sap_hana_install_addhosts' were not added: {{ __sap_hana_install_fact_addhosts_hosts_new | join(', ') }}. + Execute this role with the variable 'sap_hana_install_new_system' set to false to add new hosts. + {% endif %} + + {% 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 %} + Fapolicyd is configured for SAP folders '{{ sap_hana_install_root_path }}' and '/usr/sap'. + {% endif %} + vars: + __sap_hana_install_fact_hana_version: "{{ __sap_hana_install_register_completion_result.stdout.split(';')[0] }}" + __sap_hana_install_fact_hana_hosts: "{{ __sap_hana_install_register_completion_result.stdout.split(';')[1] }}" + when: + - not ansible_check_mode + - __sap_hana_install_fact_is_main_host diff --git a/roles/sap_hana_install/tasks/post_addhosts.yml b/roles/sap_hana_install/tasks/post_addhosts.yml new file mode 100644 index 000000000..dee91eb6d --- /dev/null +++ b/roles/sap_hana_install/tasks/post_addhosts.yml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Execute only on new addhosts, if present. +- name: SAP HANA - Addhosts - Post-Tasks - Set user expiration + ansible.builtin.include_tasks: + file: post_tasks/user_expiration.yml + when: + - __sap_hana_install_fact_is_new_addhost_host + - sap_hana_install_set_sidadm_noexpire | d(true) + + +# Execute on all hosts in play to achieve idempotency. +- name: SAP HANA - Addhosts - Post-Tasks - Update hdbuserstore connection details + ansible.builtin.include_tasks: + file: post_tasks/hdbuserstore.yml + tags: sap_hana_install_store_connection_information + +- name: SAP HANA - Addhosts - Post-Tasks - Firewall + ansible.builtin.include_tasks: + file: post_tasks/firewall.yml + when: sap_hana_install_update_firewall + tags: sap_hana_install_configure_firewall + +- name: SAP HANA - Addhosts - Post-Tasks - SELinux + ansible.builtin.include_tasks: + file: post_tasks/selinux.yml + when: sap_hana_install_modify_selinux_labels + +- name: SAP HANA - Addhosts - Post-Tasks - Fapolicyd + ansible.builtin.include_tasks: + file: post_tasks/fapolicyd.yml + when: + # Ensure fapolicyd is checked only on supported systems. + - ansible_os_family == "RedHat" + - sap_hana_install_use_fapolicyd + tags: sap_hana_install_use_fapolicyd diff --git a/roles/sap_hana_install/tasks/post_install.yml b/roles/sap_hana_install/tasks/post_install.yml index 1e58f2f5a..2030cc7b3 100644 --- a/roles/sap_hana_install/tasks/post_install.yml +++ b/roles/sap_hana_install/tasks/post_install.yml @@ -4,46 +4,32 @@ # 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) + - not __sap_hana_install_fact_is_installed + - __sap_hana_install_fact_is_main_host block: - - name: SAP HANA Post Install - Store connection information + - name: SAP HANA - Install - Post-Tasks - Set log_mode 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: - file: post_install/log_mode.yml + file: post_tasks/log_mode.yml tags: sap_hana_install_set_log_mode - - name: SAP HANA Post Install - Apply license + - name: SAP HANA - Install - Post-Tasks - Apply license ansible.builtin.include_tasks: - file: post_install/license.yml + file: post_tasks/license.yml when: sap_hana_install_apply_license - - name: SAP HANA Post Install - Recreate the initial tenant database + - name: SAP HANA - Install - Post-Tasks - Recreate the initial tenant database ansible.builtin.include_tasks: - file: post_install/recreate_tenant_database.yml + file: post_tasks/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 + - name: SAP HANA - Install - Post-Tasks - Perform an hdblcm installation check ansible.builtin.include_tasks: - file: post_install/check_installation.yml + file: post_tasks/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 + - name: SAP HANA - Install - Post-Tasks - Generate Input File for SAP Application Deployment '{{ sap_hana_install_nw_input_location }}/{{ sap_hana_install_sid }}.info.nw.install' ansible.builtin.template: src: "{{ role_path }}/templates/sap-nw-input.j2" @@ -56,87 +42,47 @@ tags: sap_hana_install_generate_input_file # Cleanup extracted software - - name: SAP HANA Post Install - Deleting software extract directory '{{ sap_hana_install_software_extract_directory }}' + - name: SAP HANA - Install - Post-Tasks - 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 }}' + - name: SAP HANA - Install - Post-Tasks - 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 -# Idempotent tasks for new and existing HANA Systems -- name: SAP HANA Post Install - Firewall +# Execute on all hosts in play to achieve idempotency. +- name: SAP HANA - Addhosts - Post-Tasks - Set user expiration + ansible.builtin.include_tasks: + file: post_tasks/user_expiration.yml + when: + - sap_hana_install_set_sidadm_noexpire | d(true) + +- name: SAP HANA - Install - Post-Tasks - Update hdbuserstore connection details + ansible.builtin.include_tasks: + file: post_tasks/hdbuserstore.yml + tags: sap_hana_install_store_connection_information + +- name: SAP HANA - Install - Post-Tasks - Firewall ansible.builtin.include_tasks: - file: post_install/firewall.yml + file: post_tasks/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 +- name: SAP HANA - Install - Post-Tasks - SELinux + ansible.builtin.include_tasks: + file: post_tasks/selinux.yml when: sap_hana_install_modify_selinux_labels -- name: SAP HANA Post Install - Fapolicyd +- name: SAP HANA - Install - Post-Tasks - Fapolicyd ansible.builtin.include_tasks: - file: post_install/fapolicyd.yml + file: post_tasks/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 - - -# 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} - /version:/{if (a==1){ - gsub ("^\\s*version: ", "");printf ("%s;", $NF)} - } - /hosts?:/{if (a==1){ - gsub ("^\\s*hosts?: ", ""); gsub (", ", ","); print; a=0} - }' - args: - chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" - register: __sap_hana_install_register_install_result - changed_when: false - when: not ansible_check_mode - -- 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] }}" - __sap_hana_install_fact_hana_hosts: "{{ __sap_hana_install_register_install_result.stdout.split(';')[1] }}" - when: not ansible_check_mode - - -- 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: - - not ansible_check_mode diff --git a/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml b/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml deleted file mode 100644 index 2593e5384..000000000 --- a/roles/sap_hana_install/tasks/post_install/hdbuserstore.yml +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- - -- name: SAP HANA Post Install - Create and Store Connection Info in hdbuserstore - ansible.builtin.shell: | - /usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbuserstore \ - SET {{ sap_hana_install_hdbuserstore_key }} \ - {{ ansible_hostname }}:3{{ sap_hana_install_number }}13 \ - SYSTEM '{{ sap_hana_install_db_system_password | d(sap_hana_install_master_password) }}' - args: - executable: /bin/bash - become: true - become_user: "{{ sap_hana_install_sid | lower }}adm" - when: not ansible_check_mode - changed_when: false - register: __sap_hana_install_store_connection_information - tags: sap_hana_install_store_connection_information - -- name: SAP HANA Post Install - Display the output of hdbuserstore - ansible.builtin.debug: - var: __sap_hana_install_store_connection_information.stdout_lines - tags: sap_hana_install_store_connection_information diff --git a/roles/sap_hana_install/tasks/post_install/update_etchosts.yml b/roles/sap_hana_install/tasks/post_install/update_etchosts.yml deleted file mode 100644 index 79c922a33..000000000 --- a/roles/sap_hana_install/tasks/post_install/update_etchosts.yml +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- - -- name: SAP HANA Post Install - Deduplicate values from /etc/hosts - ansible.builtin.lineinfile: - path: /etc/hosts - create: false - regexp: (?i)^\s*{{ ansible_default_ipv4.address | default(ansible_all_ipv4_addresses[0]) }}\s+ - state: absent - -- name: SAP HANA Post Install - Update /etc/hosts - ansible.builtin.lineinfile: - path: /etc/hosts - line: "{{ ansible_default_ipv4.address | default(ansible_all_ipv4_addresses[0]) }} {{ ansible_fqdn }} {{ ansible_hostname }}" diff --git a/roles/sap_hana_install/tasks/post_install/update_firewall.yml b/roles/sap_hana_install/tasks/post_install/update_firewall.yml deleted file mode 100644 index d5fca3fe3..000000000 --- a/roles/sap_hana_install/tasks/post_install/update_firewall.yml +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 ---- -# This task requires the variable passed_port - -- name: Update Firewall - {{ passed_port }}/tcp - ansible.posix.firewalld: - zone: public - port: "{{ passed_port }}/tcp" - permanent: true - immediate: true - state: enabled diff --git a/roles/sap_hana_install/tasks/post_install/check_installation.yml b/roles/sap_hana_install/tasks/post_tasks/check_installation.yml similarity index 68% rename from roles/sap_hana_install/tasks/post_install/check_installation.yml rename to roles/sap_hana_install/tasks/post_tasks/check_installation.yml index 1bb100b3b..7921cf252 100644 --- a/roles/sap_hana_install/tasks/post_install/check_installation.yml +++ b/roles/sap_hana_install/tasks/post_tasks/check_installation.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA hdblcm installation check - Create a Jinja2 template from the hdblcm xml configfile template +- name: SAP HANA - Post-Tasks - Create a Jinja2 template from the hdblcm xml configfile template ansible.builtin.shell: | set -o pipefail && awk ' @@ -11,24 +11,24 @@ register: __sap_hana_install_create_jinja2_template changed_when: false -- name: SAP HANA hdblcm installation check - Display the location of the remote Jinja2 template +- name: SAP HANA - Post-Tasks - 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 +- name: SAP HANA - Post-Tasks - 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 +- name: SAP HANA - Post-Tasks - 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 +- name: SAP HANA - Post-Tasks - 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" @@ -36,7 +36,7 @@ register: __sap_hana_install_register_cftemplate when: not ansible_check_mode -- name: SAP HANA hdblcm installation check - Construct an hdbcheck command line +- name: SAP HANA - Post-Tasks - 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 @@ -45,19 +45,20 @@ -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 +- name: SAP HANA - Post-Tasks - 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 +- name: SAP HANA - Post-Tasks - Display the command line ansible.builtin.debug: - var: __sap_hana_install_fact_installation_check_command + msg: "{{ __sap_hana_install_fact_installation_check_command }}" + when: __sap_hana_install_fact_installation_check_command is defined # 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 +- name: SAP HANA - Post-Tasks - 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" @@ -65,13 +66,15 @@ changed_when: false when: sap_hana_install_use_hdbcheck | d(true) -- name: SAP HANA hdblcm installation check with hdbcheck - Display the result +- name: SAP HANA - Post-Tasks - hdbcheck - Display the result ansible.builtin.debug: - var: __sap_hana_install_register_installation_check.stdout_lines - when: sap_hana_install_use_hdbcheck | d(true) + msg: "{{ __sap_hana_install_register_installation_check.stdout_lines }}" + when: + - sap_hana_install_use_hdbcheck | d(true) + - __sap_hana_install_register_installation_check.stdout_lines is defined # 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 +- name: SAP HANA - Post-Tasks - 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" @@ -79,7 +82,9 @@ changed_when: false when: not sap_hana_install_use_hdbcheck | d(true) -- name: SAP HANA hdblcm installation check with hdblcm - Display the result +- name: SAP HANA - Post-Tasks - 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) + msg: "{{ __sap_hana_install_register_installation_check.stdout_lines }}" + when: + - not sap_hana_install_use_hdbcheck | d(true) + - __sap_hana_install_register_installation_check.stdout_lines is defined diff --git a/roles/sap_hana_install/tasks/post_install/fapolicyd.yml b/roles/sap_hana_install/tasks/post_tasks/fapolicyd.yml similarity index 67% rename from roles/sap_hana_install/tasks/post_install/fapolicyd.yml rename to roles/sap_hana_install/tasks/post_tasks/fapolicyd.yml index 7fe169ead..ddc2e90c0 100644 --- a/roles/sap_hana_install/tasks/post_install/fapolicyd.yml +++ b/roles/sap_hana_install/tasks/post_tasks/fapolicyd.yml @@ -1,16 +1,23 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Post Install, fapolicyd - Update config for desired integrity level and revert if validation fails +# This is required for addhosts pre-tasks are not run and package must be present. +- name: SAP HANA - Post-Tasks - Ensure the presence of fapolicyd + ansible.builtin.package: + name: fapolicyd + state: present + when: not sap_hana_install_new_system + +- name: SAP HANA - Post-Tasks - 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 + - name: SAP HANA - Post-Tasks - 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" + - name: SAP HANA - Post-Tasks - Ensure integrity level '{{ sap_hana_install_fapolicyd_integrity }}' is configured" ansible.builtin.lineinfile: path: /etc/fapolicyd/fapolicyd.conf regexp: '^(integrity\s*=.*)' @@ -19,13 +26,13 @@ backup: true register: __sap_hana_install_fapolicyd_conf_updated - - name: SAP HANA Post Install, fapolicyd - Validate the new version of the fapolicyd config file + - name: SAP HANA - Post-Tasks - 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 + - name: SAP HANA - Post-Tasks - Restore fapolicyd config file from backup if validation fails ansible.builtin.copy: remote_src: true dest: /etc/fapolicyd/fapolicyd.conf @@ -34,17 +41,17 @@ group: fapolicyd mode: '0644' - - name: SAP HANA Post Install, fapolicyd - Notify about failed validation + - name: SAP HANA - Post-Tasks - 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-Tasks - 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 }}' + - name: SAP HANA - Post-Tasks - 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" @@ -53,11 +60,11 @@ 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 + - name: SAP HANA - Post-Tasks - 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' + - name: SAP HANA - Post-Tasks - Display the output of the command 'fagenrules --load' ansible.builtin.debug: msg: "{{ sap_hana_install_register_fagenrules_load.stdout_lines }}" @@ -65,7 +72,7 @@ # 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 + - name: SAP HANA - Post-Tasks - 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 | @@ -86,13 +93,13 @@ regex_replace('^_', '') }}" changed_when: true - - name: SAP HANA Post Install, fapolicyd - Enable fapolicyd + - name: SAP HANA - Post-Tasks - Enable fapolicyd ansible.builtin.service: name: fapolicyd enabled: true state: started - - name: SAP HANA Post Install, fapolicyd - Restart fapolicyd + - name: SAP HANA - Post-Tasks - Restart fapolicyd ansible.builtin.service: name: fapolicyd enabled: true diff --git a/roles/sap_hana_install/tasks/post_install/firewall.yml b/roles/sap_hana_install/tasks/post_tasks/firewall.yml similarity index 59% rename from roles/sap_hana_install/tasks/post_install/firewall.yml rename to roles/sap_hana_install/tasks/post_tasks/firewall.yml index a213584ac..b81cb36dd 100644 --- a/roles/sap_hana_install/tasks/post_install/firewall.yml +++ b/roles/sap_hana_install/tasks/post_tasks/firewall.yml @@ -1,72 +1,63 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Post Install - Enable and start the firewalld service +- name: SAP HANA - Post-Tasks - Enable and start the firewalld service ansible.builtin.systemd: name: firewalld state: started enabled: true - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Construct the argument list for 'firewall-cmd --add-port' +- name: SAP HANA - Post-Tasks - Construct the argument list for 'firewall-cmd --add-port' ansible.builtin.set_fact: __sap_hana_install_fact_firewall_cmd_args: "{{ ['--add-port='] | product(sap_hana_install_firewall[0].port) | map('join') | list }}" when: sap_hana_install_firewall[0].state == 'enabled' - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Construct the argument list for 'firewall-cmd --remove-port' +- name: SAP HANA - Post-Tasks - Construct the argument list for 'firewall-cmd --remove-port' ansible.builtin.set_fact: __sap_hana_install_fact_firewall_cmd_args: "{{ ['--remove-port='] | product(sap_hana_install_firewall[0].port) | map('join') | list }}" when: sap_hana_install_firewall[0].state == 'disabled' - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Set fact for the 'firewall-cmd' command +- name: SAP HANA - Post-Tasks - Set fact for the 'firewall-cmd' command ansible.builtin.set_fact: __sap_hana_install_fact_firewall_cmd_command: "firewall-cmd --zone=public {{ __sap_hana_install_fact_firewall_cmd_args | map('quote') | join(' ') }}" - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Display the 'firewall-cmd' command +- name: SAP HANA - Post-Tasks - Display the 'firewall-cmd' command ansible.builtin.debug: - var: __sap_hana_install_fact_firewall_cmd_command - tags: sap_hana_install_configure_firewall + msg: "{{ __sap_hana_install_fact_firewall_cmd_command }}" # No matter if the ports have already been enabled or not, the changed state # of the command is always true. For avoiding ansible-lint to report a violation # of the no-changed-when rule, we just set changed_when to true here. -- name: SAP HANA Post Install - Enable the required ports immediately +- name: SAP HANA - Post-Tasks - Enable the required ports immediately ansible.builtin.command: "{{ __sap_hana_install_fact_firewall_cmd_command }}" changed_when: true - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Get the current firewall configuration of the default zone +- name: SAP HANA - Post-Tasks - Get the current firewall configuration of the default zone ansible.builtin.command: firewall-cmd --list-all changed_when: false register: __sap_hana_install_register_current_firewall_ports - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Display the current firewall configuration of the default zone +- name: SAP HANA - Post-Tasks - Display the current firewall configuration of the default zone ansible.builtin.debug: - var: __sap_hana_install_register_current_firewall_ports.stdout_lines - tags: sap_hana_install_configure_firewall + msg: "{{ __sap_hana_install_register_current_firewall_ports.stdout_lines }}" + when: __sap_hana_install_register_current_firewall_ports.stdout_lines is defined # No matter if the ports have already been enabled or not, the changed state # of the command is always true. For avoiding ansible-lint to report a violation # of the no-changed-when rule, we just set changed_when to true here. -- name: SAP HANA Post Install - Enable the required ports permanently +- name: SAP HANA - Post-Tasks - Enable the required ports permanently ansible.builtin.command: "{{ __sap_hana_install_fact_firewall_cmd_command }} --permanent" changed_when: true - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Get the permanent firewall configuration of the default zone +- name: SAP HANA - Post-Tasks - Get the permanent firewall configuration of the default zone ansible.builtin.command: firewall-cmd --list-all changed_when: false register: __sap_hana_install_register_permanent_firewall_ports - tags: sap_hana_install_configure_firewall -- name: SAP HANA Post Install - Display the permanent firewall configuration of the default zone +- name: SAP HANA - Post-Tasks - Display the permanent firewall configuration of the default zone ansible.builtin.debug: - var: __sap_hana_install_register_permanent_firewall_ports.stdout_lines - tags: sap_hana_install_configure_firewall + msg: "{{ __sap_hana_install_register_permanent_firewall_ports.stdout_lines }}" + when: __sap_hana_install_register_permanent_firewall_ports.stdout_lines is defined diff --git a/roles/sap_hana_install/tasks/post_tasks/hdbuserstore.yml b/roles/sap_hana_install/tasks/post_tasks/hdbuserstore.yml new file mode 100644 index 000000000..29ac3248f --- /dev/null +++ b/roles/sap_hana_install/tasks/post_tasks/hdbuserstore.yml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Executed only for new installations or new addhosts to avoid overwriting existing configuration. +- name: SAP HANA - Post-Tasks - hdbuserstore - Add key {{ sap_hana_install_hdbuserstore_key }} + ansible.builtin.shell: | + /usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbuserstore \ + SET {{ sap_hana_install_hdbuserstore_key }} \ + {{ ansible_hostname }}:3{{ sap_hana_install_number }}13 \ + SYSTEM '{{ sap_hana_install_db_system_password | d(sap_hana_install_master_password) }}' + args: + executable: /bin/bash + become: true + become_user: "{{ sap_hana_install_sid | lower }}adm" + changed_when: true + when: + - not ansible_check_mode + - sap_hana_install_hdbuserstore_force or __sap_hana_install_fact_is_new_addhost_host + +- name: SAP HANA - Post-Tasks - hdbuserstore - Execute 'hdbuserstore list' command + ansible.builtin.shell: + cmd: "/usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbuserstore list" + args: + executable: /bin/bash + become: true + become_user: "{{ sap_hana_install_sid | lower }}adm" + register: __sap_hana_install_register_hdbuserstore_list + changed_when: false + failed_when: false + +- name: SAP HANA - Post-Tasks - hdbuserstore - Inform if command 'hdbuserstore list' failed for existing installation + ansible.builtin.debug: + msg: | + Command '/usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbuserstore list' was not successful! + {% if not sap_hana_install_hdbuserstore_force %} + Resolve these issues or execute this role again with 'sap_hana_install_hdbuserstore_force' set to 'true'. + {% endif %} + + {{ __sap_hana_install_register_hdbuserstore_list.stdout_lines }} + when: + - __sap_hana_install_register_hdbuserstore_list.rc != 0 diff --git a/roles/sap_hana_install/tasks/post_install/license.yml b/roles/sap_hana_install/tasks/post_tasks/license.yml similarity index 83% rename from roles/sap_hana_install/tasks/post_install/license.yml rename to roles/sap_hana_install/tasks/post_tasks/license.yml index 409cfadd9..d557cdf69 100644 --- a/roles/sap_hana_install/tasks/post_install/license.yml +++ b/roles/sap_hana_install/tasks/post_tasks/license.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Post Install - Apply the SAP HANA license +- name: SAP HANA - Post-Tasks - Apply the SAP HANA license ansible.builtin.shell: | /usr/sap/{{ sap_hana_install_sid | upper }}/HDB{{ sap_hana_install_number }}/exe/hdbsql \ -i {{ sap_hana_install_number }} -u SYSTEM @@ -14,5 +14,5 @@ become_user: "{{ sap_hana_install_sid | lower }}adm" changed_when: "'0 rows affected' in addlicense.stdout" # Variable not used: -# register: __sap_hana_install_register_post_install_apply_license +# register: __sap_hana_install_register_post_tasks_apply_license when: sap_hana_install_apply_license diff --git a/roles/sap_hana_install/tasks/post_install/log_mode.yml b/roles/sap_hana_install/tasks/post_tasks/log_mode.yml similarity index 82% rename from roles/sap_hana_install/tasks/post_install/log_mode.yml rename to roles/sap_hana_install/tasks/post_tasks/log_mode.yml index b490f7be8..f5fa90b98 100644 --- a/roles/sap_hana_install/tasks/post_install/log_mode.yml +++ b/roles/sap_hana_install/tasks/post_tasks/log_mode.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Post Install - Set log_mode to overwrite, no initial tenant +- name: SAP HANA - Post-Tasks - Set log_mode to overwrite, no initial tenant ansible.builtin.shell: | LD_LIBRARY_PATH=/usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/exe \ /usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbsql \ @@ -26,16 +26,17 @@ register: __sap_hana_install_register_hdbsql_logmode_no_initial_tenant tags: sap_hana_install_set_log_mode -- name: SAP HANA Post Install - Display the output of hdbsql, no initial tenant +- name: SAP HANA - Post-Tasks - Display the output of hdbsql, no initial tenant ansible.builtin.debug: - var: __sap_hana_install_register_hdbsql_logmode_no_initial_tenant.stdout_lines + msg: "{{ __sap_hana_install_register_hdbsql_logmode_no_initial_tenant.stdout_lines }}" tags: sap_hana_install_set_log_mode when: - not ansible_check_mode - sap_hana_install_create_initial_tenant == 'n' - sap_hana_install_log_mode | d('') == 'overwrite' + - __sap_hana_install_register_hdbsql_logmode_no_initial_tenant.stdout_lines is defined -- name: SAP HANA Post Install - Set log_mode to overwrite, with initial tenant +- name: SAP HANA - Post-Tasks - Set log_mode to overwrite, with initial tenant ansible.builtin.shell: | LD_LIBRARY_PATH=/usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/exe \ /usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbsql \ @@ -61,11 +62,12 @@ register: __sap_hana_install_register_hdbsql_logmode_with_initial_tenant tags: sap_hana_install_set_log_mode -- name: SAP HANA Post Install - Display the output of hdbsql, with initial tenant +- name: SAP HANA - Post-Tasks - Display the output of hdbsql, with initial tenant ansible.builtin.debug: - var: __sap_hana_install_register_hdbsql_logmode_with_initial_tenant.stdout_lines + msg: "{{ __sap_hana_install_register_hdbsql_logmode_with_initial_tenant.stdout_lines }}" tags: sap_hana_install_set_log_mode when: - not ansible_check_mode - sap_hana_install_create_initial_tenant == 'y' - sap_hana_install_log_mode | d('') == 'overwrite' + - __sap_hana_install_register_hdbsql_logmode_with_initial_tenant.stdout_lines is defined diff --git a/roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml b/roles/sap_hana_install/tasks/post_tasks/recreate_tenant_database.yml similarity index 79% rename from roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml rename to roles/sap_hana_install/tasks/post_tasks/recreate_tenant_database.yml index e12f394fe..4108c9f13 100644 --- a/roles/sap_hana_install/tasks/post_install/recreate_tenant_database.yml +++ b/roles/sap_hana_install/tasks/post_tasks/recreate_tenant_database.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Post Install - Recreate the tenant database +- name: SAP HANA - Post-Tasks - Recreate the tenant database ansible.builtin.shell: | LD_LIBRARY_PATH=/usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/exe \ /usr/sap/{{ sap_hana_install_sid }}/SYS/exe/hdb/hdbsql \ @@ -25,6 +25,7 @@ changed_when: false register: __sap_hana_install_register_recreate_tenant_database -- name: SAP HANA Post Install - Display the result of the hdbsql command +- name: SAP HANA - Post-Tasks - Display the result of the hdbsql command ansible.builtin.debug: - var: __sap_hana_install_register_recreate_tenant_database.stdout_lines + msg: "{{ __sap_hana_install_register_recreate_tenant_database.stdout_lines }}" + when: __sap_hana_install_register_recreate_tenant_database.stdout_lines is defined diff --git a/roles/sap_hana_install/tasks/post_tasks/selinux.yml b/roles/sap_hana_install/tasks/post_tasks/selinux.yml new file mode 100644 index 000000000..bccb46bda --- /dev/null +++ b/roles/sap_hana_install/tasks/post_tasks/selinux.yml @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# This configuration includes also Pre-Tasks content to ensure they are all set same. +- name: SAP HANA - Post-Tasks - Configure 'sap_hana_install_root_path' SELinux file contexts + ansible.builtin.include_role: + name: '{{ sap_hana_install_system_roles_collection }}.selinux' + vars: + selinux_booleans: + - { name: 'selinuxuser_execmod', state: 'on' } + selinux_fcontexts: + - { target: '{{ sap_hana_install_root_path }}(/.*)?', setype: 'usr_t' } + - { target: '/usr/sap(/.*)?', setype: 'usr_t' } + selinux_restore_dirs: + - '{{ sap_hana_install_root_path }}' + - /usr/sap diff --git a/roles/sap_hana_install/tasks/post_tasks/user_expiration.yml b/roles/sap_hana_install/tasks/post_tasks/user_expiration.yml new file mode 100644 index 000000000..7dd88cb92 --- /dev/null +++ b/roles/sap_hana_install/tasks/post_tasks/user_expiration.yml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA - Post-Tasks - 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_tasks_register_sidadm_noexpire + changed_when: __sap_hana_install_post_tasks_register_sidadm_noexpire.rc == 0 diff --git a/roles/sap_hana_install/tasks/pre_addhosts.yml b/roles/sap_hana_install/tasks/pre_addhosts.yml new file mode 100644 index 000000000..f4bc4b987 --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_addhosts.yml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Get details of user 'sapadm' and group 'sapsys' on main host. +- name: Block to get OS user details from main host + when: __sap_hana_install_fact_is_main_host + block: + - name: SAP HANA - Addhosts - Pre-Tasks - Get details of the 'sapsys' group + ansible.builtin.getent: + database: group + key: sapsys + failed_when: false + + - name: SAP HANA - Addhosts - Pre-Tasks - Get info about user 'sapadm' + ansible.builtin.getent: + database: passwd + key: sapadm + failed_when: false + + # hana_exists already found existing database, this is additional check. + # getent_group['sapsys'][1] and getent_passwd['sapadm'][2] are Group ID. + - name: SAP HANA - Addhosts - Pre-Tasks - Assert that user 'sapadm' is present with group 'sapsys' + ansible.builtin.assert: + that: + - "'sapsys' in getent_group" + - "'sapadm' in getent_passwd" + # Ensure sapadm user is assigned to sapsys group + - getent_group['sapsys'][1] == getent_passwd['sapadm'][2] + fail_msg: >- + FAIL: User 'sapadm' with group 'sapsys' does not exist! + + # TODO: Issue#1123 Remove default to master + - name: SAP HANA - Addhosts - Pre-Tasks - Generate password hash for 'sap_hana_install_sapadm_password' + ansible.builtin.shell: + cmd: "set -o pipefail && echo '{{ sap_hana_install_sapadm_password | d(sap_hana_install_master_password) }}' | openssl passwd -6 -stdin" + register: __sap_hana_install_register_sapadm_password_hash + no_log: true + changed_when: false + check_mode: false + +- name: SAP HANA - Addhosts - Pre-Tasks - Create user 'sapadm' with group 'sapsys' on new hosts + ansible.builtin.include_tasks: + file: pre_tasks/create_users_groups.yml + when: __sap_hana_install_fact_is_new_addhost_host + + +- name: SAP HANA - Addhosts - Pre-Tasks - Install and disable fapolicyd + ansible.builtin.include_tasks: + file: pre_tasks/fapolicyd.yml + when: + # Ensure fapolicyd is checked only on supported systems. + - ansible_os_family == "RedHat" + - __sap_hana_install_fact_is_new_addhost_host + tags: sap_hana_install_use_fapolicyd + + +- name: SAP HANA - Addhosts - Pre-Tasks - Configure SELinux file contexts for {{ sap_hana_install_root_path }} + ansible.builtin.include_tasks: + file: pre_tasks/selinux.yml + when: + - sap_hana_install_modify_selinux_labels + - __sap_hana_install_fact_is_new_addhost_host + + +- name: SAP HANA - Addhosts - Pre-Tasks - Validate and prepare software directory + ansible.builtin.include_tasks: + file: pre_tasks/prepare_software_addhosts.yml + when: __sap_hana_install_fact_is_main_host + + +# Proper idempotency needs to check existing version, not just existence. +- name: SAP HANA - Addhosts - Pre-Tasks - Validate existing HANA version + ansible.builtin.include_tasks: + file: pre_tasks/check_version.yml + when: __sap_hana_install_fact_is_main_host + +- name: SAP HANA - Addhosts - Pre-Tasks - Check shared filesystems + ansible.builtin.include_tasks: + file: pre_tasks/check_filesystems.yml + + +# Update HANA directory permissions +- name: SAP HANA - Addhosts - Pre-Tasks - Change ownership of HANA directories + ansible.builtin.include_tasks: + file: pre_tasks/hana_directory_permissions.yml + # Execute only once for Scale-Out to avoid conflicts when updating shared file systems. + when: __sap_hana_install_fact_is_main_host + tags: sap_hana_install_chown_hana_directories + +- name: SAP HANA - Addhosts - Pre-Tasks - Process the hdblcm configfile + ansible.builtin.include_tasks: + file: pre_tasks/hdblcm_configfile.yml + when: __sap_hana_install_fact_is_main_host diff --git a/roles/sap_hana_install/tasks/pre_install.yml b/roles/sap_hana_install/tasks/pre_install.yml index c8f37f535..bbcc0fb92 100644 --- a/roles/sap_hana_install/tasks/pre_install.yml +++ b/roles/sap_hana_install/tasks/pre_install.yml @@ -1,270 +1,55 @@ # SPDX-License-Identifier: Apache-2.0 --- -################ -# Password Facts -################ -# - name: SAP HANA Pre Install - Set password facts when using master password -# ansible.builtin.set_fact: -# sap_hana_install_sapadm_password: "{{ sap_hana_install_master_password }}" -# sap_hana_install_sidadm_password: "{{ sap_hana_install_master_password }}" -# sap_hana_install_db_system_password: "{{ sap_hana_install_master_password }}" -# sap_hana_install_ase_user_password: "{{ sap_hana_install_master_password }}" -# sap_hana_install_xs_org_password: "{{ sap_hana_install_master_password }}" -# sap_hana_install_lss_user_password: "{{ sap_hana_install_master_password }}" -# sap_hana_install_lss_backup_password: "{{ sap_hana_install_master_password }}" -# when: sap_hana_install_use_master_password == 'y' - -################ -# Handle fapolicyd -################ - -- name: SAP HANA Pre Install, fapolicyd - Ensure the presence of fapolicyd - ansible.builtin.package: - name: fapolicyd - state: present +- name: SAP HANA - Install - Pre-Tasks - Install and disable fapolicyd + ansible.builtin.include_tasks: + file: pre_tasks/fapolicyd.yml when: - - sap_hana_install_use_fapolicyd - # Ensure fapolicyd is installed only on supported systems. - - ansible_os_family == 'RedHat' - tags: sap_hana_install_use_fapolicyd - -################ -# We must ensure fapolicyd is disabled before installing SAP HANA in all cases -# Otherwise, the installation of SAP HANA will fail -################ - -- name: SAP HANA Pre Install, fapolicyd - Block to disable fapolicyd - when: - - sap_hana_install_new_system # Don't disable for existing installations during addhosts. # Ensure fapolicyd is checked only on supported systems. - ansible_os_family == "RedHat" + - not __sap_hana_install_fact_is_installed tags: sap_hana_install_use_fapolicyd - block: - - name: SAP HANA Pre Install, fapolicyd - Gather package facts - ansible.builtin.package_facts: - - - name: SAP HANA Pre Install, fapolicyd - Disable fapolicyd - ansible.builtin.service: - name: fapolicyd - enabled: false - state: stopped - when: - - '"fapolicyd" in ansible_facts.packages' - -################ -# Prepare software path -################ - -- name: Prepare the HANA software for installation, new system - when: sap_hana_install_new_system - block: - - - name: SAP HANA Pre Install - Normalize directory path - ansible.builtin.set_fact: - __sap_hana_install_fact_software_directory: "{{ sap_hana_install_software_directory | regex_replace('\\/$', '') }}" - - - name: SAP HANA Pre Install - Check availability of software directory '{{ __sap_hana_install_fact_software_directory }}' - ansible.builtin.stat: - path: "{{ __sap_hana_install_fact_software_directory }}" - check_mode: false - register: __sap_hana_install_register_stat_software_directory - failed_when: false - - - name: SAP HANA Pre Install - Assert that the software directory exists - ansible.builtin.assert: - that: __sap_hana_install_register_stat_software_directory.stat.exists - fail_msg: "FAIL: The software directory '{{ __sap_hana_install_fact_software_directory }}' does not exist!" - success_msg: "PASS: The software directory '{{ __sap_hana_install_fact_software_directory }}' exist." - - - name: > - SAP HANA Pre Install - Assert directory permissions in case `sap_hana_install_software_extract_directory` - is below `sap_hana_install_software_extract_directory` - when: sap_hana_install_software_extract_directory is search(sap_hana_install_software_directory) - block: - - - name: SAP HANA Pre Install - Set fact for number of directory levels of the software directory - ansible.builtin.set_fact: - __sap_hana_install_fact_software_directory_levels: "{{ __sap_hana_install_fact_software_directory | regex_findall('/') | length }}" - - - name: SAP HANA Pre Install - Assert directory permissions - ansible.builtin.include_tasks: ./pre_install-loop-block.yml - loop: "{{ range(1, __sap_hana_install_fact_software_directory_levels | int + 1, 1) | list }}" - loop_control: - loop_var: line_item - - - name: SAP HANA Pre Install - Change ownership of HANA directories - ansible.builtin.file: - path: "{{ item }}" - state: directory - mode: '0755' - owner: root - group: root - loop: - - '{{ sap_hana_install_root_path }}' - - '{{ sap_hana_install_shared_path }}' - - '{{ sap_hana_install_root_path }}/log' - - '{{ sap_hana_install_root_path }}/data' - tags: sap_hana_install_chown_hana_directories - - - name: SAP HANA Pre Install - Configure 'sap_hana_install_root_path' SELinux file contexts - ansible.builtin.include_role: - name: '{{ sap_hana_install_system_roles_collection }}.selinux' - vars: - selinux_booleans: - - { name: 'selinuxuser_execmod', state: 'on' } - selinux_fcontexts: - - { target: '{{ sap_hana_install_root_path }}(/.*)?', setype: 'usr_t' } - selinux_restore_dirs: - - '{{ sap_hana_install_root_path }}' - when: sap_hana_install_modify_selinux_labels - - name: SAP HANA Pre Install - Get info about software extract directory '{{ sap_hana_install_software_extract_directory }}' - ansible.builtin.stat: - path: "{{ sap_hana_install_software_extract_directory }}" - check_mode: false - register: __sap_hana_install_register_stat_software_extract_directory - failed_when: false - - name: SAP HANA Pre Install - Change ownership of software extract directory '{{ sap_hana_install_software_extract_directory }}' - ansible.builtin.file: - path: "{{ sap_hana_install_software_extract_directory }}" - state: directory - recurse: true - mode: '0755' - owner: root - group: root - when: __sap_hana_install_register_stat_software_extract_directory.stat.exists - - # In case more than one installation is ongoing and extracting to the same shared directory, wait until the extraction has completed: - - name: SAP HANA Pre Install - Suspending if extraction status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' exists - ansible.builtin.wait_for: - path: "{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__" - state: absent - failed_when: false - - - name: SAP HANA Pre Install - Find directory 'SAP_HANA_DATABASE' if '{{ sap_hana_install_software_extract_directory }}' exists - ansible.builtin.find: - paths: "{{ sap_hana_install_software_extract_directory }}" - recurse: true - file_type: directory - patterns: 'SAP_HANA_DATABASE' - register: __sap_hana_install_register_find_directory_sap_hana_database_initial - when: __sap_hana_install_register_stat_software_extract_directory.stat.exists - - # All SAPCAR and SAR files pre_install steps will be skipped if role `sap_install_media_detect` successfully extracts software. - - name: SAP HANA Pre Install - Set directory of 'hdblcm' from successful find result - when: - - __sap_hana_install_register_stat_software_extract_directory.stat.exists - - __sap_hana_install_register_find_directory_sap_hana_database_initial.files[0] is defined - block: - - - name: SAP HANA Pre Install - Set fact for 'hdblcm' installer directory if found initially - ansible.builtin.set_fact: - __sap_hana_install_fact_hdblcm_path: "{{ __sap_hana_install_register_find_directory_sap_hana_database_initial.files[0].path }}" - - - name: SAP HANA Pre Install - Get info about '{{ __sap_hana_install_fact_hdblcm_path }}/hdblcm' if found initially - ansible.builtin.stat: - path: "{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}" - check_mode: false - register: __sap_hana_install_register_stat_hdblcm_initial - failed_when: false - - - name: SAP HANA Pre Install - Assert that file 'hdblcm' is available if found initially - ansible.builtin.assert: - that: __sap_hana_install_register_stat_hdblcm_initial.stat.exists - fail_msg: "FAIL: File '{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}' could not be found. Installation of SAP HANA is not possible." - success_msg: "Using '{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}' for the installation of SAP HANA." - - - name: SAP HANA Pre Install - Extract SAR files if file 'hdblcm' was not found initially - when: __sap_hana_install_register_find_directory_sap_hana_database_initial.files[0] is not defined - block: - - - name: SAP HANA Pre Install - Run hdblcm prepare - ansible.builtin.include_tasks: pre_install/hdblcm_prepare.yml - - - name: SAP HANA Pre Install - Display 'hdblcm' installer directory - ansible.builtin.debug: - var: __sap_hana_install_fact_hdblcm_path - - - name: SAP HANA Pre Install - Set __sap_hana_install_fact_hdblcm_path in case of check mode - ansible.builtin.set_fact: - __sap_hana_install_fact_hdblcm_path: '/software/hana/extracted' - when: ansible_check_mode - - - name: SAP HANA Pre Install - Get info about '{{ __sap_hana_install_fact_hdblcm_path }}/hdblcm' - ansible.builtin.stat: - path: "{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}" - check_mode: false - register: __sap_hana_install_register_stat_hdblcm - failed_when: false - - - name: SAP HANA Pre Install - Assert that file 'hdblcm' is available - ansible.builtin.assert: - that: __sap_hana_install_register_stat_hdblcm.stat.exists - fail_msg: "FAIL: File 'hdblcm' could not be found. Installation of SAP HANA is not possible." - success_msg: "Using file '{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}' for the installation of SAP HANA." - when: not ansible_check_mode - - -# For an addhosts operation, we first use the hdblcm command for creating a new configfile template, which -# we then process with the templating engine. The actual addhosts installation is done via the resident hdblcm. -# Non-resident hdblcm is used to avoid issues when attempting to generate configfile with resident hdblcm. -- name: Set the path to hdblcm, addhosts - when: not sap_hana_install_new_system - block: - - # 'sap_hana_install_software_extract_directory' is required for configfile creation. - - name: SAP HANA Pre Install - Addhosts - Get status of the directory '{{ sap_hana_install_software_extract_directory }}' - ansible.builtin.stat: - path: "{{ sap_hana_install_software_extract_directory }}" - check_mode: false - register: __sap_hana_install_register_stat_extract_directory - failed_when: false +- name: SAP HANA - Install - Pre-Tasks - Configure SELinux file contexts for {{ sap_hana_install_root_path }} + ansible.builtin.include_tasks: + file: pre_tasks/selinux.yml + when: + - sap_hana_install_modify_selinux_labels + - not __sap_hana_install_fact_is_installed - - name: SAP HANA Pre Install - Addhosts - Fail if '{{ sap_hana_install_software_extract_directory }}' does not exist - ansible.builtin.fail: - msg: | - FAIL: The directory {{ sap_hana_install_software_extract_directory }} does not exist. - Path must be defined in the variable 'sap_hana_install_software_extract_directory'. - when: not __sap_hana_install_register_stat_extract_directory.stat.exists - - name: SAP HANA Pre Install - Addhosts - Find directory 'SAP_HANA_DATABASE' in '{{ sap_hana_install_software_extract_directory }}' - ansible.builtin.find: - paths: "{{ sap_hana_install_software_extract_directory }}" - recurse: true - file_type: directory - patterns: 'SAP_HANA_DATABASE' - register: __sap_hana_install_register_find_directory_sap_hana_database_addhosts +# This task will run on existing system because we need to validate version from manifest file. +- name: SAP HANA - Install - Pre-Tasks - Validate and prepare software directory + ansible.builtin.include_tasks: + file: pre_tasks/prepare_software_install.yml + when: __sap_hana_install_fact_is_main_host - - name: SAP HANA Pre Install - Addhosts - Fail if directory 'SAP_HANA_DATABASE' does not exist in '{{ sap_hana_install_software_extract_directory }}' - ansible.builtin.fail: - msg: | - FAIL: The directory {{ sap_hana_install_software_extract_directory }} does not contain directory 'SAP_HANA_DATABASE'. - when: __sap_hana_install_register_find_directory_sap_hana_database_addhosts.files | length == 0 - - name: SAP HANA Pre Install - Addhosts - Set fact for 'hdblcm' installer directory, addhosts - ansible.builtin.set_fact: - __sap_hana_install_fact_hdblcm_path: "{{ __sap_hana_install_register_find_directory_sap_hana_database_addhosts.files[0].path }}" +# Proper idempotency needs to check existing version, not just existence. +- name: SAP HANA - Install - Pre-Tasks - Validate existing HANA version + ansible.builtin.include_tasks: + file: pre_tasks/check_version.yml + when: __sap_hana_install_fact_is_main_host -################ -# Pre Install Steps -################ +- name: SAP HANA - Install - Pre-Tasks - Check shared filesystems + ansible.builtin.include_tasks: + file: pre_tasks/check_filesystems.yml + when: __sap_hana_install_fact_is_scaleout -- name: SAP HANA Pre Install - Create temporary directory to store various files - ansible.builtin.tempfile: - state: directory - suffix: hanaconfig - register: __sap_hana_install_register_tmpdir - tags: - - sap_hana_install_hdblcm_commandline - - sap_hana_install_check_installation -- name: SAP HANA Pre Install - Fill variable __sap_hana_install_register_tmpdir for check mode only - ansible.builtin.set_fact: - __sap_hana_install_register_tmpdir: - path: '/tmp' - when: ansible_check_mode +# We need to change permissions only after filesystem check has passed. +- name: SAP HANA - Install - Pre-Tasks - Change ownership of HANA directories + ansible.builtin.include_tasks: + file: pre_tasks/hana_directory_permissions.yml + # Execute only once for Scale-Out to avoid conflicts when updating shared file systems. + run_once: "{{ __sap_hana_install_fact_is_scaleout }}" + when: not __sap_hana_install_fact_is_installed + tags: sap_hana_install_chown_hana_directories -- name: SAP HANA Pre Install - Process the hdblcm configfile - ansible.builtin.include_tasks: pre_install/hdblcm_configfile.yml +- name: SAP HANA - Install - Pre-Tasks - Process the hdblcm configfile + ansible.builtin.include_tasks: + file: pre_tasks/hdblcm_configfile.yml + when: + - __sap_hana_install_fact_is_main_host + - not __sap_hana_install_fact_is_installed diff --git a/roles/sap_hana_install/tasks/assert_variables.yml b/roles/sap_hana_install/tasks/pre_tasks/assert_variables.yml similarity index 54% rename from roles/sap_hana_install/tasks/assert_variables.yml rename to roles/sap_hana_install/tasks/pre_tasks/assert_variables.yml index c5b9b1f44..1d606bdab 100644 --- a/roles/sap_hana_install/tasks/assert_variables.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/assert_variables.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: Assert that the variable 'sap_hana_install_sid' is defined as String consisting of 3 characters +- name: SAP HANA - Pre-Tasks - Assert that the variable 'sap_hana_install_sid' is defined as String consisting of 3 characters ansible.builtin.assert: that: - sap_hana_install_sid is defined @@ -18,7 +18,7 @@ FAIL: The length of SAP HANA System ID '{{ sap_hana_install_sid }}' is not 3 characters! {% endif %} -- name: Assert that the variable 'sap_hana_install_sid' is not in the list of reserved SAP SIDs +- name: SAP HANA - Pre-Tasks - Assert that the variable 'sap_hana_install_sid' is not in the list of reserved SAP SIDs ansible.builtin.assert: that: sap_hana_install_sid not in __sap_hana_install_sid_prohibited success_msg: | @@ -44,7 +44,7 @@ FAIL: The SAP HANA Instance Number '{{ sap_hana_install_number }}' is not 2 digits! {% endif %} -- name: Assert that the variable 'sap_hana_install_master_password' is defined as String and not empty +- name: SAP HANA - Pre-Tasks - Assert that the variable 'sap_hana_install_master_password' is defined as String and not empty ansible.builtin.assert: that: - sap_hana_install_master_password is defined @@ -62,7 +62,7 @@ {% endif %} -- name: Assert that the variable 'sap_hana_install_addhosts' is defined as String and not empty +- name: SAP HANA - Pre-Tasks - Assert that the variable 'sap_hana_install_addhosts' is defined as String and not empty ansible.builtin.assert: that: - sap_hana_install_addhosts is defined @@ -78,5 +78,48 @@ {% else %} FAIL: The variable 'sap_hana_install_addhosts' is empty. {% endif %} + This variable is required when 'sap_hana_install_new_system' is set to false. when: - not sap_hana_install_new_system + +# TODO: Issue#1123 Uncomment and update when fixing issue with use_master_password +# Master Password cannot be used in combination with other initial passwords +# Mandatory parameter 'password' (Password) is missing or invalid + +# # This will not replace user defined variables due to variable precedence. +# - name: SAP HANA - Pre-Tasks - Set password facts when using master password +# ansible.builtin.set_fact: +# sap_hana_install_sapadm_password: "{{ sap_hana_install_master_password }}" +# sap_hana_install_sidadm_password: "{{ sap_hana_install_master_password }}" +# sap_hana_install_db_system_password: "{{ sap_hana_install_master_password }}" +# sap_hana_install_ase_user_password: "{{ sap_hana_install_master_password }}" +# sap_hana_install_xs_org_password: "{{ sap_hana_install_master_password }}" +# sap_hana_install_lss_user_password: "{{ sap_hana_install_master_password }}" +# sap_hana_install_lss_backup_password: "{{ sap_hana_install_master_password }}" +# no_log: true +# when: +# - sap_hana_install_use_master_password is defined +# - sap_hana_install_use_master_password == 'y' + + +# - name: SAP HANA - Pre-Tasks - Assert that the variable 'sap_hana_install_sapadm_password' is defined as String and not empty +# ansible.builtin.assert: +# that: +# - sap_hana_install_sapadm_password is defined +# - sap_hana_install_sapadm_password is string +# - sap_hana_install_sapadm_password | trim | length > 0 +# success_msg: | +# PASS: The variable 'sap_hana_install_sapadm_password' is defined as String and not empty. +# fail_msg: | +# {% if sap_hana_install_sapadm_password is not defined %} +# FAIL: The variable 'sap_hana_install_sapadm_password' is not defined. +# {% elif sap_hana_install_sapadm_password is not string %} +# FAIL: The variable 'sap_hana_install_sapadm_password' is not String. +# {% else %} +# FAIL: The variable 'sap_hana_install_sapadm_password' is empty. +# {% endif %} +# This variable is required when 'sap_hana_install_new_system' is set to false. +# when: +# - not sap_hana_install_new_system +# - sap_hana_install_use_master_password is undefined +# or sap_hana_install_use_master_password != 'y' diff --git a/roles/sap_hana_install/tasks/pre_tasks/check_filesystems.yml b/roles/sap_hana_install/tasks/pre_tasks/check_filesystems.yml new file mode 100644 index 000000000..54a6d7eb5 --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/check_filesystems.yml @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# We need to ensure that Scale-Out system has filesystems shared to avoid failure in hdblcm. +# We cannot fully test with 'touch' as it can be blocked by SElinux or Fapolicyd. + +# NOTE: We cannot validate shared filesystems for Scale-Up! + +- name: SAP HANA - Install - Pre-Tasks - Gather mount facts + ansible.builtin.setup: + filter: ansible_mounts + +# /hana/shared +- name: SAP HANA - Install - Pre-Tasks - Set fact with mount details of {{ sap_hana_install_shared_path }} + ansible.builtin.set_fact: + __sap_hana_install_fact_mount_hana_shared: + "{{ ansible_mounts | selectattr('mount', 'equalto', sap_hana_install_shared_path) | list | first }}" + when: ansible_mounts | selectattr('mount', 'equalto', sap_hana_install_shared_path) | list | length > 0 + +- name: SAP HANA - Install - Pre-Tasks - Assert that filesystem is shared - {{ sap_hana_install_shared_path }} + ansible.builtin.assert: + that: + - __sap_hana_install_fact_mount_hana_shared is defined + - __sap_hana_install_fact_mount_hana_shared.fstype is defined + - __sap_hana_install_fact_mount_hana_shared.fstype in __sap_hana_install_shared_filesystem_types + success_msg: >- + PASS: The directory {{ sap_hana_install_shared_path }} is mounted as one of supported + filesystem types {{ __sap_hana_install_shared_filesystem_types | join(', ') }}. + fail_msg: | + FAIL: The directory {{ sap_hana_install_shared_path }} is not mounted as shared filesystem. + This is required for SAP HANA Scale-Out systems. + + Please ensure this is a correctly mounted shared filesystem before proceeding. + This role validates prerequisites but does not configure system mounts. + + {% if __sap_hana_install_fact_mount_hana_shared.fstype is defined %} + Detected filesystem type: {{ __sap_hana_install_fact_mount_hana_shared.fstype }} + {% endif %} + Supported filesystem types: {{ __sap_hana_install_shared_filesystem_types | join(', ') }} + + +# /lss/shared - Required for SAP HANA 2.0 SPS08 and higher. +- name: Block to run if revision version was gathered. + when: + - hostvars[__sap_hana_install_fact_main_host]['__sap_hana_install_fact_is_lss_required'] is defined + - hostvars[__sap_hana_install_fact_main_host]['__sap_hana_install_fact_is_lss_required'] + block: + - name: SAP HANA - Install - Pre-Tasks - Set fact for 'lss_inst_path' + ansible.builtin.set_fact: + __sap_hana_install_lss_inst_path: "{{ sap_hana_install_lss_inst_path }}" + when: + - sap_hana_install_lss_inst_path is defined + - sap_hana_install_lss_inst_path is string + - sap_hana_install_lss_inst_path | trim | length > 0 + + - name: SAP HANA - Install - Pre-Tasks - Set fact with mount details of {{ __sap_hana_install_lss_inst_path }} + ansible.builtin.set_fact: + __sap_hana_install_fact_mount_lss_shared: + "{{ ansible_mounts | selectattr('mount', 'equalto', __sap_hana_install_lss_inst_path) | list | first }}" + when: ansible_mounts | selectattr('mount', 'equalto', __sap_hana_install_lss_inst_path) | list | length > 0 + + - name: SAP HANA - Install - Pre-Tasks - Assert that filesystem is shared - {{ __sap_hana_install_lss_inst_path }} + ansible.builtin.assert: + that: + - __sap_hana_install_fact_mount_lss_shared is defined + - __sap_hana_install_fact_mount_lss_shared.fstype is defined + - __sap_hana_install_fact_mount_lss_shared.fstype in __sap_hana_install_shared_filesystem_types + success_msg: >- + PASS: The directory {{ __sap_hana_install_lss_inst_path }} is mounted as one of supported + filesystem types {{ __sap_hana_install_shared_filesystem_types | join(', ') }}. + fail_msg: | + FAIL: Directory {{ __sap_hana_install_lss_inst_path }} is not mounted as shared filesystem. + This is required for SAP HANA 2.0 SPS08 and higher. + + Please ensure this is a correctly mounted shared filesystem before proceeding. + This role validates prerequisites but does not configure system mounts. + + {% if __sap_hana_install_fact_mount_lss_shared.fstype is defined %} + Detected filesystem type: {{ __sap_hana_install_fact_mount_lss_shared.fstype }} + {% endif %} + Supported filesystem types: {{ __sap_hana_install_shared_filesystem_types | join(', ') }} diff --git a/roles/sap_hana_install/tasks/pre_tasks/check_version.yml b/roles/sap_hana_install/tasks/pre_tasks/check_version.yml new file mode 100644 index 000000000..618fc80bb --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/check_version.yml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# Check if existing installation has expected version. +# manifest file is located at SAP_HANA_DATABASE/server/manifest +- name: SAP HANA - Pre-Tasks - Check availability of manifest file + ansible.builtin.stat: + path: "{{ __sap_hana_install_fact_hdblcm_path }}/server/manifest" + register: __sap_hana_install_register_stat_manifest + +# Execute version checks only if manifest file is present. +- name: Block for manifest file + when: __sap_hana_install_register_stat_manifest.stat.exists + block: + - name: SAP HANA - Pre-Tasks - Get contents of manifest file + ansible.builtin.slurp: + src: "{{ __sap_hana_install_fact_hdblcm_path }}/server/manifest" + register: __sap_hana_install_register_slurp_manifest + + - name: SAP HANA - Pre-Tasks - Parse manifest file into facts + ansible.builtin.set_fact: + __sap_hana_install_fact_manifest_revision: "{{ __revision.split(':')[1] | trim | int }}" + __sap_hana_install_fact_manifest_version: "{{ (__version.split(' ')[1]).split('.')[:4] | join('.') }}" + vars: + __manifest_lines: "{{ __sap_hana_install_register_slurp_manifest['content'] | b64decode | split('\n') }}" + __revision: "{{ __manifest_lines | select('match', '^rev-number:') | first | default('') }}" + __version: "{{ __manifest_lines | select('match', '^fullversion:') | first | default('') }}" + + - name: SAP HANA - Pre-Tasks - Assert that existing installation has correct version + ansible.builtin.assert: + that: + - __sap_hana_install_fact_manifest_version == __existing_version + success_msg: | + PASS: Existing installation has expected version. + Expected version: {{ __sap_hana_install_fact_manifest_version }}. + fail_msg: | + FAIL: Existing installation does not have expected version! + Existing version: {{ __existing_version }} + Expected version: {{ __sap_hana_install_fact_manifest_version }} + vars: + __existing_version: "{{ __sap_hana_install_fact_existing_hana_version.split('.')[:4] | join('.') }}" + when: __sap_hana_install_fact_is_installed + + # Revision number follows SPS, where first digit designates SPS. + - name: SAP HANA - Pre-Tasks - Set fact if LSS is required for SAP HANA 2.0 SPS08 or higher + ansible.builtin.set_fact: + __sap_hana_install_fact_is_lss_required: true + when: + - __sap_hana_install_fact_manifest_revision is defined + - __sap_hana_install_fact_manifest_revision is integer + - __sap_hana_install_fact_manifest_revision >= 80 diff --git a/roles/sap_hana_install/tasks/pre_tasks/create_users_groups.yml b/roles/sap_hana_install/tasks/pre_tasks/create_users_groups.yml new file mode 100644 index 000000000..0dc44017b --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/create_users_groups.yml @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# This task is required only for addhosts operation, because it requires +# user 'sapadm' to be present on addhosts with correct password. +# Addhosts operation does not use root SSH, but sapadm SSH instead. + +- name: SAP HANA - Addhosts - Pre-Tasks - Create 'sapsys' group on new host + ansible.builtin.group: + name: sapsys + gid: "{{ hostvars[__sap_hana_install_fact_main_host]['getent_group']['sapsys'][1] }}" + state: present + become: true + +# User 'sidadm' is not required for addhosts, only sapadm user. +- name: SAP HANA - Addhosts - Pre-Tasks - Create 'sapadm' user on new host + ansible.builtin.user: + name: sapadm + uid: "{{ hostvars[__sap_hana_install_fact_main_host]['getent_passwd']['sapadm'][1] }}" + home: "{{ hostvars[__sap_hana_install_fact_main_host]['getent_passwd']['sapadm'][4] }}" + shell: "{{ hostvars[__sap_hana_install_fact_main_host]['getent_passwd']['sapadm'][5] }}" + groups: sapsys + append: true + state: present + password: "{{ hostvars[__sap_hana_install_fact_main_host]['__sap_hana_install_register_sapadm_password_hash'].stdout }}" + become: true diff --git a/roles/sap_hana_install/tasks/pre_install/extract_sarfile.yml b/roles/sap_hana_install/tasks/pre_tasks/extract_sarfile.yml similarity index 70% rename from roles/sap_hana_install/tasks/pre_install/extract_sarfile.yml rename to roles/sap_hana_install/tasks/pre_tasks/extract_sarfile.yml index 041fc08dd..137726b29 100644 --- a/roles/sap_hana_install/tasks/pre_install/extract_sarfile.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/extract_sarfile.yml @@ -1,17 +1,17 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA hdblcm prepare - Set fact for temporary extraction directory, default +- name: SAP HANA - Pre-Tasks - Set fact for temporary extraction directory, default ansible.builtin.set_fact: __sap_hana_install_tmp_software_extract_directory: "{{ sap_hana_install_software_extract_directory }}/tmp" when: "'SAPHOST' not in __sap_hana_install_passed_sarfile" -- name: SAP HANA hdblcm prepare - Set fact for temporary extraction directory, SAP Host Agent +- name: SAP HANA - Pre-Tasks - Set fact for temporary extraction directory, SAP Host Agent ansible.builtin.set_fact: __sap_hana_install_tmp_software_extract_directory: "{{ sap_hana_install_software_extract_directory }}/tmp/SAP_HOST_AGENT" when: "'SAPHOST' in __sap_hana_install_passed_sarfile" -- name: SAP HANA hdblcm prepare - Create temporary extraction directory '{{ __sap_hana_install_tmp_software_extract_directory }}' +- name: SAP HANA - Pre-Tasks - Create temporary extraction directory '{{ __sap_hana_install_tmp_software_extract_directory }}' ansible.builtin.file: path: "{{ __sap_hana_install_tmp_software_extract_directory }}" state: directory @@ -19,7 +19,7 @@ owner: root group: root -- name: SAP HANA hdblcm prepare - Extract file '{{ __sap_hana_install_fact_sar_dir }}/{{ __sap_hana_install_passed_sarfile }}' +- name: SAP HANA - Pre-Tasks - Extract file '{{ __sap_hana_install_fact_sar_dir }}/{{ __sap_hana_install_passed_sarfile }}' ansible.builtin.command: >- {{ sap_hana_install_software_extract_directory }}/sapcar/{{ __sap_hana_install_fact_selected_sapcar_filename }} \ -R {{ __sap_hana_install_tmp_software_extract_directory }} \ @@ -30,7 +30,7 @@ chdir: "{{ sap_hana_install_software_extract_directory }}" changed_when: "'SAPCAR: processing archive' in __sap_hana_install_register_extract.stdout" -- name: SAP HANA hdblcm prepare - Move files into the correct place, default +- name: SAP HANA - Pre-Tasks - Move files into the correct place, default ansible.builtin.shell: | extracted_dir=$(ls -d */) mv SIGNATURE.SMF ${extracted_dir} @@ -40,14 +40,14 @@ changed_when: true when: "'SAPHOST' not in __sap_hana_install_passed_sarfile" -- name: SAP HANA hdblcm prepare - Move files into the correct place, SAP Host Agent +- name: SAP HANA - Pre-Tasks - Move files into the correct place, SAP Host Agent ansible.builtin.command: mv ./tmp/SAP_HOST_AGENT . args: chdir: "{{ sap_hana_install_software_extract_directory }}" changed_when: true when: "'SAPHOST' in __sap_hana_install_passed_sarfile" -- name: SAP HANA hdblcm prepare - Remove temporary extraction directory '{{ sap_hana_install_software_extract_directory }}/tmp' +- name: SAP HANA - Pre-Tasks - Remove temporary extraction directory '{{ sap_hana_install_software_extract_directory }}/tmp' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/tmp/" state: absent diff --git a/roles/sap_hana_install/tasks/pre_tasks/fapolicyd.yml b/roles/sap_hana_install/tasks/pre_tasks/fapolicyd.yml new file mode 100644 index 000000000..e77bf5980 --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/fapolicyd.yml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA - Pre-Tasks - Ensure the presence of fapolicyd + ansible.builtin.package: + name: fapolicyd + state: present + when: sap_hana_install_use_fapolicyd + +# We must ensure fapolicyd is disabled before installing SAP HANA in all cases. +# Otherwise, the installation of SAP HANA will fail. + +- name: SAP HANA - Pre-Tasks - Disable fapolicyd if it exists + ansible.builtin.shell: # noqa command-instead-of-module + # This command only runs the second part if the first part succeeds + cmd: "rpm -q fapolicyd && systemctl disable --now fapolicyd" + register: __sap_hana_install_register_disable_fapolicy + changed_when: >- + "Removed" in __sap_hana_install_register_disable_fapolicy.stderr or + "Stopping" in __sap_hana_install_register_disable_fapolicy.stdout + failed_when: >- + __sap_hana_install_register_disable_fapolicy.rc != 0 and + "package fapolicyd is not installed" not in __sap_hana_install_register_disable_fapolicy.stdout diff --git a/roles/sap_hana_install/tasks/pre_tasks/hana_directory_permissions.yml b/roles/sap_hana_install/tasks/pre_tasks/hana_directory_permissions.yml new file mode 100644 index 000000000..05870deed --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/hana_directory_permissions.yml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA - Pre-Tasks - Change ownership of HANA directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: '0755' + owner: root + group: root + loop: + - '{{ sap_hana_install_root_path }}' + - '{{ sap_hana_install_shared_path }}' + - '{{ sap_hana_install_root_path }}/log' + - '{{ sap_hana_install_root_path }}/data' diff --git a/roles/sap_hana_install/tasks/pre_tasks/hana_exists.yml b/roles/sap_hana_install/tasks/pre_tasks/hana_exists.yml new file mode 100644 index 000000000..50822e6dd --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/hana_exists.yml @@ -0,0 +1,242 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA - Pre-Tasks - Check if saphostctrl is installed + ansible.builtin.stat: + path: /usr/sap/hostctrl/exe/saphostctrl + check_mode: false + register: __sap_hana_install_register_stat_saphostctrl + failed_when: false + + +# Check 1: Use found saphostctrl to get list of SAP instances. +# Only valid combination of SID and Instance Number will pass. +- name: SAP HANA - Pre-Tasks - Check if SAP instances are installed with saphostctrl + when: __sap_hana_install_register_stat_saphostctrl.stat.exists + block: + + - name: SAP HANA - Pre-Tasks - Get list of installed SAP instances + ansible.builtin.shell: + cmd: set -o pipefail && /usr/sap/hostctrl/exe/saphostctrl -function ListInstances | cut -d":" -f2- + register: __sap_hana_install_register_instancelist + changed_when: false + + - name: SAP HANA - Pre-Tasks - Display instances + ansible.builtin.debug: + msg: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" + verbosity: 1 + when: __sap_hana_install_register_instancelist.stdout_lines is defined + + - name: SAP HANA - Pre-Tasks - Desired SAP HANA is installed and running + ansible.builtin.set_fact: + __sap_hana_install_fact_is_installed: true + when: + - __sap_hana_install_loop_instance.split('-')[0] | trim == sap_hana_install_sid + - __sap_hana_install_loop_instance.split('-')[1] | trim == sap_hana_install_number + loop: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" + loop_control: + loop_var: __sap_hana_install_loop_instance + label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" + + - name: SAP HANA - Pre-Tasks - Fail if existing SAP 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 + SAP HANA system {{ __sap_hana_install_loop_instance.split('-')[0] | trim }}! + when: + - __sap_hana_install_loop_instance.split('-')[0] | trim != sap_hana_install_sid + - __sap_hana_install_loop_instance.split('-')[1] | trim == sap_hana_install_number + loop: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" + loop_control: + loop_var: __sap_hana_install_loop_instance + label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" + + - name: SAP HANA - Pre-Tasks - Fail if existing SAP HANA was detected with same SID but different instance number + ansible.builtin.fail: + msg: >- + The SAP HANA system {{ sap_hana_install_sid }} already exists with different instance number + {{ __sap_hana_install_loop_instance.split('-')[1] | trim }}! + when: + - __sap_hana_install_loop_instance.split('-')[0] | trim == sap_hana_install_sid + - __sap_hana_install_loop_instance.split('-')[1] | trim != sap_hana_install_number + loop: "{{ __sap_hana_install_register_instancelist.stdout_lines }}" + loop_control: + loop_var: __sap_hana_install_loop_instance + label: "{{ __sap_hana_install_loop_instance.split('-')[0] | trim }}" + + +# Check 2: Check presence of directories if saphostctrl was not found. +# hdblcm installs 'saphostctrl' by default unless executed with 'install_hostagent=n'. +# These checks do not set '__sap_hana_install_fact_is_installed' as they pass only if directories are empty. +- name: SAP HANA - Pre-Tasks - Check directories if no saphostctrl is found + when: not __sap_hana_install_register_stat_saphostctrl.stat.exists + block: + + - name: SAP HANA - Pre-Tasks - Get status of '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' + ansible.builtin.stat: + path: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}" + check_mode: false + register: __sap_hana_install_register_stat_hana_shared_sid_assert + failed_when: false + + - name: SAP HANA - Pre-Tasks - Get contents of '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' + ansible.builtin.find: + paths: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}" + patterns: '*' + file_type: 'any' # New install does not have files and default 'file' will ignore directories. + register: __sap_hana_install_register_files_in_hana_shared_sid_assert + when: __sap_hana_install_register_stat_hana_shared_sid_assert.stat.exists + + - name: SAP HANA - Pre-Tasks - Fail if the directory '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' exists and is not empty + ansible.builtin.fail: + msg: | + FAIL: The directory '{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}' exists and is not empty! + Cleanup existing files in directory to install new system + or execute this role with 'sap_hana_install_new_system: false' to add new hosts to existing installation. + when: + - __sap_hana_install_register_stat_hana_shared_sid_assert.stat.exists + - __sap_hana_install_register_files_in_hana_shared_sid_assert.matched | int != 0 + # Fail for new Install, but proceed for Addhosts + - sap_hana_install_new_system + + - name: SAP HANA - Pre-Tasks - Get status of '/usr/sap/{{ sap_hana_install_sid }}' + ansible.builtin.stat: + path: "/usr/sap/{{ sap_hana_install_sid }}" + check_mode: false + register: __sap_hana_install_register_stat_usr_sap_sid_assert + failed_when: false + + - name: SAP HANA - Pre-Tasks - Get contents of '/usr/sap/{{ sap_hana_install_sid }}' + ansible.builtin.find: + paths: "/usr/sap/{{ sap_hana_install_sid }}" + patterns: '*' + file_type: 'any' # New install does not have files and default 'file' will ignore directories. + register: __sap_hana_install_register_files_in_usr_sap_sid_assert + when: __sap_hana_install_register_stat_usr_sap_sid_assert.stat.exists + + - name: SAP HANA - Pre-Tasks - Fail if the directory '/usr/sap/{{ sap_hana_install_sid }}' exists and is not empty + ansible.builtin.fail: + msg: | + FAIL: The directory '/usr/sap/{{ sap_hana_install_sid }}' exists and is not empty! + Cleanup existing files in directory to install new system + or execute this role with 'sap_hana_install_new_system: false' to add new hosts to existing installation. + when: + - __sap_hana_install_register_stat_usr_sap_sid_assert.stat.exists + - __sap_hana_install_register_files_in_usr_sap_sid_assert.matched | int != 0 + # Fail for new Install, but proceed for Addhosts + - sap_hana_install_new_system + + # SAP HANA was detected without SAP Host Agent and we will validate if it can be started in next task. + - name: SAP HANA - Pre-Tasks - Desired SAP HANA is installed without SAP Host Agent + ansible.builtin.set_fact: + __sap_hana_install_fact_is_installed: true + when: + - not sap_hana_install_new_system + - (__sap_hana_install_register_stat_hana_shared_sid_assert.stat.exists + and __sap_hana_install_register_files_in_hana_shared_sid_assert.matched | int != 0) + or (__sap_hana_install_register_stat_usr_sap_sid_assert.stat.exists + and __sap_hana_install_register_files_in_usr_sap_sid_assert.matched | int != 0 ) + + +# Check 3: Check if the group 'sapsys' exists with correct ID. +# The role supports specifying the SAP HANA group id in variable `sap_hana_install_groupid`, which is the id of the sapsys group. +# The SAP HANA installation will fail if there is already a group named sapsys but with a different ID. Let's better fail before. +- name: SAP HANA - Pre-Tasks - Check SAP HANA admin group + when: + - sap_hana_install_groupid is defined + - sap_hana_install_groupid is string + - sap_hana_install_groupid | trim | length > 0 + - not __sap_hana_install_fact_is_installed + block: + + # getent_groups will be populated, with fields: + # [0] - 'X' if the password is set. + # [1] - Group ID. + # [2] - Group members. + - name: SAP HANA - Pre-Tasks - Get details of the 'sapsys' group + ansible.builtin.getent: + database: group + key: sapsys + failed_when: false + + - name: SAP HANA - Pre-Tasks - In case there is a group 'sapsys', assert that its group ID is identical to 'sap_hana_install_groupid' + ansible.builtin.assert: + that: + - getent_group['sapsys'][1] | int == sap_hana_install_groupid | int + success_msg: "PASS: The group ID of 'sapsys' is identical to the value of variable + sap_hana_install_groupid, which is '{{ sap_hana_install_groupid }}'" + fail_msg: >- + FAIL: Group 'sapsys' exists but with a different group ID than '{{ sap_hana_install_groupid }}' + defined in the variable 'sap_hana_install_groupid'! + when: + - getent_group is defined + - "'sapsys' in getent_group" + + +# Check 4: Check if the user 'sidadm' exists. +- name: SAP HANA - Pre-Tasks - SAP HANA admin user check + when: + - sap_hana_install_check_sidadm_user | d(true) + - not __sap_hana_install_fact_is_installed + vars: + __sap_hana_install_sidadm: "{{ sap_hana_install_sid | lower }}adm" + block: + + - name: SAP HANA - Pre-Tasks - Get info about user '{{ __sap_hana_install_sidadm }}' + ansible.builtin.getent: + database: passwd + key: "{{ __sap_hana_install_sidadm }}" + failed_when: false + + - name: SAP HANA - Pre-Tasks - Fail if the user '{{ __sap_hana_install_sidadm }}' exists + ansible.builtin.fail: + msg: | + FAIL: The user '{{ __sap_hana_install_sidadm }}' already exists! + Cleanup existing '{{ __sap_hana_install_sidadm }}' user to install new system + or execute this role with 'sap_hana_install_new_system: false' to add new hosts to existing installation. + when: + - getent_passwd is defined + - __sap_hana_install_sidadm in getent_passwd + # Fail for new Install, but proceed for Addhosts + - sap_hana_install_new_system + + +- name: Block to prepare status message + when: + - __sap_hana_install_fact_is_installed + - not ansible_check_mode + block: + - name: SAP HANA - Pre-Tasks - Run 'hdblcm --list_systems' for existing database + ansible.builtin.shell: | + set -o pipefail && ./hdblcm --list_systems | awk '/\/hana\/shared\/{{ sap_hana_install_sid }}/{a=1} + /version:/{if (a==1){ + gsub ("^\\s*version: ", "");printf ("%s;", $NF)} + } + /hosts?:/{if (a==1){ + gsub ("^\\s*hosts?: ", ""); gsub (", ", ","); print; a=0} + }' + args: + chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm" + register: __sap_hana_install_register_existing_systems + changed_when: false + + # Scale-Out will show as installed because of filesystem check so we need to + # ensure that we show output only if it is valid. + - name: Block to show only if output is valid + when: __sap_hana_install_register_existing_systems.stdout.split(';') | length == 2 + block: + - name: SAP HANA - Pre-Tasks - Set facts for existing SAP HANA + ansible.builtin.set_fact: + __sap_hana_install_fact_existing_hana_version: + "{{ __sap_hana_install_register_existing_systems.stdout.split(';')[0] }}" + __sap_hana_install_fact_existing_hana_hosts: + "{{ __sap_hana_install_register_existing_systems.stdout.split(';')[1] }}" + + - name: SAP HANA - Pre-Tasks - Display details of existing SAP HANA + ansible.builtin.debug: + msg: | + SAP HANA database is installed and running: + HANA Version - {{ __sap_hana_install_fact_existing_hana_version }} + Hosts - {{ __sap_hana_install_fact_existing_hana_hosts }} + SID - {{ sap_hana_install_sid }} + NR - {{ sap_hana_install_number }} diff --git a/roles/sap_hana_install/tasks/hana_start.yml b/roles/sap_hana_install/tasks/pre_tasks/hana_start.yml similarity index 75% rename from roles/sap_hana_install/tasks/hana_start.yml rename to roles/sap_hana_install/tasks/pre_tasks/hana_start.yml index 49c4d2a5a..833024a5f 100644 --- a/roles/sap_hana_install/tasks/hana_start.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/hana_start.yml @@ -1,12 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: Ensure SAP HANA is running - Set path to sapcontrol +- name: SAP HANA - Pre-Tasks - Start HANA - 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 +- name: SAP HANA - Pre-Tasks - Start HANA - Check for sapcontrol executable ansible.builtin.stat: path: "{{ __sap_hana_install_sapcontrol_path }}" register: __sap_hana_install_stat_sapcontrol @@ -15,7 +15,7 @@ when: __sap_hana_install_stat_sapcontrol.stat.exists block: - - name: Ensure SAP HANA is running - Start instance + - name: SAP HANA - Pre-Tasks - Start HANA - Start instance ansible.builtin.command: cmd: "{{ __sap_hana_install_sapcontrol_path }} -nr {{ sap_hana_install_number }} -function StartSystem" become: true @@ -23,7 +23,7 @@ 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 + - name: SAP HANA - Pre-Tasks - Start HANA - 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 @@ -38,3 +38,8 @@ delay: 10 changed_when: false failed_when: false # command module will fail with non-zero return code + + rescue: + - name: SAP HANA - Pre-Tasks - Start HANA - Fail if SAP HANA Start was not successful + ansible.builtin.fail: + msg: "FAIL: Start of existing SAP HANA was not successful!" diff --git a/roles/sap_hana_install/tasks/pre_install/hdblcm_configfile.yml b/roles/sap_hana_install/tasks/pre_tasks/hdblcm_configfile.yml similarity index 87% rename from roles/sap_hana_install/tasks/pre_install/hdblcm_configfile.yml rename to roles/sap_hana_install/tasks/pre_tasks/hdblcm_configfile.yml index 8dfba5261..9b736fed0 100644 --- a/roles/sap_hana_install/tasks/pre_install/hdblcm_configfile.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/hdblcm_configfile.yml @@ -1,24 +1,24 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Pre Install - Create the hdblcm configfile directory '{{ sap_hana_install_configfile_directory }}' if it does not exist +- name: SAP HANA - Pre-Tasks - Create the hdblcm configfile directory '{{ sap_hana_install_configfile_directory }}' if it does not exist ansible.builtin.file: path: "{{ sap_hana_install_configfile_directory }}" state: directory mode: '0755' -- name: SAP HANA Pre Install - Check if file '{{ sap_hana_install_configfile_directory }}/configfile.cfg' exists +- name: SAP HANA - Pre-Tasks - Check if file '{{ sap_hana_install_configfile_directory }}/configfile.cfg' exists ansible.builtin.stat: path: "{{ sap_hana_install_configfile_directory }}/configfile.cfg" check_mode: false register: __sap_hana_install_register_stat_hdblcm_configfile -- name: SAP HANA Pre Install - Notify about existing hdblcm configfile +- name: SAP HANA - Pre-Tasks - Notify about existing hdblcm configfile ansible.builtin.debug: msg: "INFO: Using existing static hdblcm configfile '{{ sap_hana_install_configfile_directory }}/configfile.cfg'." when: __sap_hana_install_register_stat_hdblcm_configfile.stat.exists -- name: SAP HANA Pre Install - Make the existing static hdblcm configfile available for the SAP HANA installation +- name: SAP HANA - Pre-Tasks - Make the existing static hdblcm configfile available for the SAP HANA installation ansible.builtin.copy: src: "{{ sap_hana_install_configfile_directory }}/configfile.cfg" dest: "{{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg" @@ -32,13 +32,13 @@ when: not __sap_hana_install_register_stat_hdblcm_configfile.stat.exists block: - - name: SAP HANA Pre Install - Create the hdblcm configfile template '{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.cfg' + - name: SAP HANA - Pre-Tasks - Create the hdblcm configfile template '{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.cfg' ansible.builtin.command: cmd: "{{ __sap_hana_install_fact_hdblcm_path }}/hdblcm --dump_configfile_template={{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.cfg" register: __sap_hana_install_register_hdblcm_output changed_when: false - - name: SAP HANA Pre Install - Display the output of the hdblcm command + - name: SAP HANA - Pre-Tasks - Display the output of the hdblcm command ansible.builtin.debug: msg: "Output of hdblcm command: {{ __sap_hana_install_register_hdblcm_output.stdout_lines }}" @@ -57,7 +57,7 @@ # will be used to override the corresponding hdblcm configfile parameter (e.g. "max_mem"). # 2) If a role variable for the hdblcm configfile is not set in the playbook or inventory, either the default value which is set # in the hdblcm configfile template will be used, or an empty string. - - name: SAP HANA Pre Install - Create a Jinja2 template from the hdblcm configfile template + - name: SAP HANA - Pre-Tasks - Create a Jinja2 template from the hdblcm configfile template ansible.builtin.shell: | set -o pipefail && awk 'BEGIN{FS="="; printf ("\{\{ ansible_managed | comment \}\}\n# File created on: \{\{ template_host \}\}\n# Template file: \{\{ template_path \}\}\n#\n")} @@ -66,24 +66,24 @@ register: __sap_hana_install_create_jinja2_template changed_when: false - - name: SAP HANA Pre Install - Display the location of the remote Jinja2 template + - name: SAP HANA - Pre-Tasks - 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'. - - name: SAP HANA Pre Install - Download the Jinja2 template + - name: SAP HANA - Pre-Tasks - Download the Jinja2 template ansible.builtin.fetch: src: "{{ sap_hana_install_configfile_directory }}/{{ sap_hana_install_configfile_template_prefix }}.j2" dest: "{{ sap_hana_install_local_configfile_directory }}" register: __sap_hana_install_register_fetch_hdblcm_configfile_jinja2_template - - name: SAP HANA Pre Install - Display the location of the local Jinja2 template + - name: SAP HANA - Pre-Tasks - 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_jinja2_template.dest }}'." when: not ansible_check_mode - - name: SAP HANA Pre Install - Process the Jinja2 template to create the hdblcm configfile + - name: SAP HANA - Pre-Tasks - Process the Jinja2 template to create the hdblcm configfile ansible.builtin.template: src: "{{ __sap_hana_install_register_fetch_hdblcm_configfile_jinja2_template.dest }}" dest: "{{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg" @@ -91,6 +91,6 @@ register: __sap_hana_install_register_cftemplate when: not ansible_check_mode -- name: SAP HANA Pre Install - Display the path name of the hdblcm configfile +- name: SAP HANA - Pre-Tasks - Display the path name of the hdblcm configfile ansible.builtin.debug: msg: "The hdblcm configfile is: '{{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg'" diff --git a/roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml b/roles/sap_hana_install/tasks/pre_tasks/hdblcm_prepare.yml similarity index 67% rename from roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml rename to roles/sap_hana_install/tasks/pre_tasks/hdblcm_prepare.yml index 0b0e0f165..969ab309b 100644 --- a/roles/sap_hana_install/tasks/pre_install/hdblcm_prepare.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/hdblcm_prepare.yml @@ -5,7 +5,7 @@ # Create directory {{ sap_hana_install_software_extract_directory }} # This is where all extracted .SAR files will be stored -- name: SAP HANA hdblcm prepare - Remove directory '{{ sap_hana_install_software_extract_directory }}' +- name: SAP HANA - Pre-Tasks - Remove directory '{{ sap_hana_install_software_extract_directory }}' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}" state: absent @@ -13,7 +13,7 @@ - sap_hana_install_prepare_sapcar - sap_hana_install_prepare_sarfiles -- name: SAP HANA hdblcm prepare - Create directory '{{ sap_hana_install_software_extract_directory }}' +- name: SAP HANA - Pre-Tasks - Create directory '{{ sap_hana_install_software_extract_directory }}' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}" state: directory @@ -22,7 +22,7 @@ - sap_hana_install_prepare_sapcar - sap_hana_install_prepare_sarfiles -- name: SAP HANA hdblcm prepare - Create SAPCAR directory '{{ sap_hana_install_software_extract_directory }}/sapcar' +- name: SAP HANA - Pre-Tasks - Create SAPCAR directory '{{ sap_hana_install_software_extract_directory }}/sapcar' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/sapcar" state: directory @@ -31,7 +31,7 @@ - sap_hana_install_prepare_sapcar - sap_hana_install_prepare_sarfiles -- name: SAP HANA hdblcm prepare - Create status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' +- name: SAP HANA - Pre-Tasks - Create status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__" state: touch @@ -40,34 +40,34 @@ # Ensure that temporary file __EXTRACTION_ONGOING__ is removed if fail occurs. - name: Rescue block for SAPCAR and SAR file preparation block: - - name: SAP HANA hdblcm prepare - Prepare SAPCAR + - name: SAP HANA - Pre-Tasks - Prepare SAPCAR 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 + - name: SAP HANA - Pre-Tasks - Prepare SAR files 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__' + - name: SAP HANA - Pre-Tasks - Remove status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__" state: absent - - name: SAP HANA hdblcm prepare - Preparation tasks failed + - name: SAP HANA - Pre-Tasks - Preparation tasks failed ansible.builtin.fail: msg: | Preparation steps failed. Please see details of failed task above. Cleanup of temporary files was completed. -- name: SAP HANA hdblcm prepare - Remove status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' +- name: SAP HANA - Pre-Tasks - Remove status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__" state: absent -- name: SAP HANA hdblcm prepare - Find 'SAP_HANA_DATABASE' in '{{ sap_hana_install_software_extract_directory }}' +- name: SAP HANA - Pre-Tasks - Find 'SAP_HANA_DATABASE' in '{{ sap_hana_install_software_extract_directory }}' ansible.builtin.find: paths: "{{ sap_hana_install_software_extract_directory }}" recurse: true @@ -75,7 +75,7 @@ patterns: 'SAP_HANA_DATABASE' register: __sap_hana_install_register_find_directory_sap_hana_database -- name: SAP HANA hdblcm prepare - Set fact for 'hdblcm' installer path +- name: SAP HANA - Pre-Tasks - Set fact for 'hdblcm' installer path ansible.builtin.set_fact: __sap_hana_install_fact_hdblcm_path: "{{ __sap_hana_install_register_find_directory_sap_hana_database.files[0].path }}" diff --git a/roles/sap_hana_install/tasks/pre_tasks/identify_hosts.yml b/roles/sap_hana_install/tasks/pre_tasks/identify_hosts.yml new file mode 100644 index 000000000..89b03855a --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/identify_hosts.yml @@ -0,0 +1,244 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# This file is responsible for all pre-flight identification and validation tasks required for an 'addhosts' (scale-out) installation. +# It begins by parsing the 'addhosts' variable on the first host, then sets facts and validates the configuration across all hosts in the play. + +- name: Block to process addhosts string on first host + when: + - sap_hana_install_addhosts is defined + - sap_hana_install_addhosts is string + - sap_hana_install_addhosts | trim | length > 0 + - ansible_play_hosts_all[0] in [ansible_hostname, inventory_hostname, inventory_hostname_short] + block: + + # Difference ensures that our addhosts list does not contain Managed node. + - name: SAP HANA - Addhosts - Pre-Tasks - Set fact with list of additional hostnames + ansible.builtin.set_fact: + __sap_hana_install_fact_addhosts_hosts: + "{{ sap_hana_install_addhosts.split(',') | map('trim') | reject('equalto', '') + | map('regex_replace', ':.*$', '') | list | difference([ansible_hostname, inventory_hostname, inventory_hostname_short]) }}" + + - name: SAP HANA - Addhosts - Pre-Tasks - Assert that the variable 'sap_hana_install_addhosts' is valid addhosts string + ansible.builtin.assert: + that: + - __sap_hana_install_fact_addhosts_hosts | length > 0 + success_msg: | + PASS: The variable 'sap_hana_install_addhosts' contains valid addhosts string. + Additional hosts: {{ __sap_hana_install_fact_addhosts_hosts | join(', ') }} + fail_msg: | + FAIL: The 'sap_hana_install_addhosts' variable did not result in any valid hosts to be added. + Value provided: '{{ sap_hana_install_addhosts }}' + This can happen if the variable is empty, or if it only contains the main host ('{{ ansible_hostname }}'), which is automatically filtered out. + Please provide a comma-separated list of worker hostnames. + Examples: + sap_hana_install_addhosts: "hanaworker1,hanaworker2" + sap_hana_install_addhosts: "hanaworker1:role=worker,hanaworker2:role=worker" + + # We need to ensure that Addhosts operation is run only when role is executed with correct amount of hosts. + - name: SAP HANA - Addhosts - Pre-Tasks - Assert that the inventory and 'sap_hana_install_addhosts' are aligned + ansible.builtin.assert: + that: + - __inventory_diff_addhosts | length == 0 + - __addhosts_diff_inventory | length == 0 + success_msg: | + PASS: The variable 'sap_hana_install_addhosts' and inventory are aligned. + fail_msg: | + FAIL: The variable 'sap_hana_install_addhosts' and inventory are not aligned. + The variable 'sap_hana_install_addhosts' should not contain Master host {{ ansible_hostname }} and validation is done without it. + + Inventory hosts: {{ ansible_play_hosts_all | join(', ') }} + Addhosts hosts: {{ __sap_hana_install_fact_addhosts_hosts | join(', ') }} + {% if __inventory_diff_addhosts | length > 0 %} + + Ensure that missing hosts are added to the 'sap_hana_install_addhosts' or removed from inventory. + Hosts missing in the 'sap_hana_install_addhosts': {{ __inventory_diff_addhosts | join(', ') }} + {% endif %} + {% if __addhosts_diff_inventory | length > 0 %} + + Ensure that missing hosts are added to the inventory or removed from 'sap_hana_install_addhosts'. + Hosts missing in the inventory: {{ __addhosts_diff_inventory | join(', ') }} + {% endif %} + vars: + __addhosts_hosts_with_main: + "{{ __sap_hana_install_fact_addhosts_hosts + [ansible_hostname, inventory_hostname, inventory_hostname_short] | unique }}" + __inventory_diff_addhosts: + "{{ ansible_play_hosts_all | difference(__addhosts_hosts_with_main) }}" + __addhosts_diff_inventory: + "{{ __addhosts_hosts_with_main | difference(ansible_play_hosts_all) }}" + + +# If previous step did not fail, we have valid string of addhosts. +# Identify Master host from which hdblcm will be executed from. +- name: SAP HANA - Addhosts - Pre-Tasks - Set facts for Scale-Out + when: + - sap_hana_install_addhosts is defined + - sap_hana_install_addhosts is string + - sap_hana_install_addhosts | trim | length > 0 + - hostvars[ansible_play_hosts_all[0]]['__sap_hana_install_fact_addhosts_hosts'] | length > 0 + ansible.builtin.set_fact: + __sap_hana_install_fact_is_scaleout: true + + __sap_hana_install_fact_main_host: >- + {%- if sap_hana_install_scaleout_master is defined + and sap_hana_install_scaleout_master is string + and sap_hana_install_scaleout_master | trim | length > 0 + and sap_hana_install_scaleout_master in ansible_play_hosts_all -%} + {{ sap_hana_install_scaleout_master }} + {%- else -%} + {{ ansible_play_hosts_all[0] }} + {%- endif -%} + + __sap_hana_install_fact_addhosts_hosts: + "{{ hostvars[ansible_play_hosts_all[0]]['__sap_hana_install_fact_addhosts_hosts'] }}" + +# Check that Scale-Out is executed on all hosts without conditional. +# Solves execution with: when: inventory_hostname_short == (groups['hana_primary'] | first) +- name: Block for Scale-Out hosts validation + when: __sap_hana_install_fact_is_scaleout + block: + # Set a fact on each host to confirm it participated in the pre-tasks. + # This allows a central check to detect if the playbook was improperly limited to a subset of hosts. + - name: SAP HANA - Addhosts - Pre-Tasks - Set facts for Scale-Out host presence + ansible.builtin.set_fact: + __sap_hana_install_fact_is_present: true + + - name: SAP HANA - Addhosts - Pre-Tasks - Assert that role is not executed only from Master + ansible.builtin.assert: + that: + - __missing_hosts | length == 0 + success_msg: | + PASS: The role is not executed with host restriction. + fail_msg: | + FAIL: The scale-out task must run on all hosts in the play, but it was restricted. + This commonly occurs when using 'limit' or a 'when' condition in your ansible-playbook command. + Please ensure the role executes on all target hosts. + + Expected hosts: {{ ansible_play_hosts_all | join(', ') }} + Actual hosts that ran pre-tasks: {{ __present_hosts | join(', ') }} + Missing hosts: {{ __missing_hosts | join(', ') }} + run_once: true + vars: + __present_hosts: "{{ hostvars | dict2items | selectattr('value.__sap_hana_install_fact_is_present', 'defined') | map(attribute='key') }}" + __missing_hosts: "{{ ansible_play_hosts_all | difference(__present_hosts) }}" + +# Fail if existing HANA was found on worker without master host. +- name: SAP HANA - Addhosts - Pre-Tasks - Fail if non-main host has HANA installed without master + when: + - __sap_hana_install_fact_is_scaleout + - not __sap_hana_install_fact_is_main_host + - __sap_hana_install_fact_is_installed + - __sap_hana_install_fact_existing_hana_hosts is defined + ansible.builtin.assert: + that: + - __sap_hana_install_fact_main_host in __sap_hana_install_fact_existing_hana_hosts + fail_msg: | + FAIL: A conflicting SAP HANA installation was found on worker host '{{ inventory_hostname }}'. + This host is being added to a scale-out system managed by '{{ __sap_hana_install_fact_main_host }}', + but it already runs a HANA system whose members are: '{{ __sap_hana_install_fact_existing_hana_hosts }}'. + To prevent data corruption or an inconsistent state, the 'addhosts' operation is blocked. + + Please choose one of the following actions: + - Decommission the conflicting HANA system on '{{ inventory_hostname }}'. + - Remove this host from the Ansible inventory for this play. + - Remove this host from the 'sap_hana_install_addhosts' variable. + + +# Set a fact on each host to confirm it participated in the pre-tasks. +# This allows a central check to detect if the playbook was improperly limited to a subset of hosts. +- name: SAP HANA - Pre-Tasks - Set fact with boolean flags for each host + ansible.builtin.set_fact: + __sap_hana_install_fact_is_main_host: + "{{ __sap_hana_install_fact_main_host + in [ansible_hostname, inventory_hostname, inventory_hostname_short] }}" + + __sap_hana_install_fact_is_addhost_host: + "{{ ([ansible_hostname, inventory_hostname, inventory_hostname_short] + | intersect(__sap_hana_install_fact_addhosts_hosts | d([]))) | length > 0 }}" + + +- name: Block for validating existing hosts on main + when: __sap_hana_install_fact_is_main_host + block: + + # Check for existing addhosts profiles and folders before removing them from list. + - name: SAP HANA - Addhosts - Pre-Tasks - Find existing instance profiles for all hosts + ansible.builtin.find: + paths: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/profile/" + patterns: "{{ sap_hana_install_sid }}_HDB{{ sap_hana_install_number }}_*" + file_type: file + register: __sap_hana_install_register_existing_profiles + + - name: SAP HANA - Addhosts - Pre-Tasks - Set fact with list of existing hosts with instance profiles + ansible.builtin.set_fact: + __sap_hana_install_fact_existing_hosts_profile: + "{{ __sap_hana_install_register_existing_profiles.files | map(attribute='path') | map('basename') + | map('regex_replace', '^' + sap_hana_install_sid + '_HDB' + sap_hana_install_number + '_', '') | list }}" + + - name: SAP HANA - Addhosts - Pre-Tasks - Find existing instance directories for all hosts + ansible.builtin.find: + paths: "/usr/sap/{{ sap_hana_install_sid }}/HDB{{ sap_hana_install_number }}/" + patterns: "*" + file_type: directory + register: __sap_hana_install_register_existing_dirs + + - name: SAP HANA - Addhosts - Pre-Tasks - Set fact with list of existing hosts with instance directories + ansible.builtin.set_fact: + __sap_hana_install_fact_existing_hosts_dirs: + "{{ __sap_hana_install_register_existing_dirs.files | map(attribute='path') | map('basename') | list }}" + + - name: SAP HANA - Addhosts - Pre-Tasks - Set fact with list of new hosts without existing profiles or directories + ansible.builtin.set_fact: + __sap_hana_install_fact_addhosts_hosts_new: >- + {{ + __sap_hana_install_fact_addhosts_hosts | + difference( + __sap_hana_install_fact_existing_hosts_profile | union(__sap_hana_install_fact_existing_hosts_dirs) + ) + }} + + # We need to reset hosts list and remove new, if HANA is installed and 'sap_hana_install_new_system' is 'true'. + # This ensures that post-tasks are idempotent for those hosts that already exist, not new. + - name: SAP HANA - Addhosts - Pre-Tasks - Reset fact with list of new hosts if Add + ansible.builtin.set_fact: + __sap_hana_install_fact_addhosts_hosts: + "{{ __sap_hana_install_fact_addhosts_hosts | difference(__sap_hana_install_fact_addhosts_hosts_new) }}" + when: + - sap_hana_install_new_system + - __sap_hana_install_fact_is_installed + - __sap_hana_install_fact_addhosts_hosts_new | length > 0 + + - name: SAP HANA - Addhosts - Pre-Tasks - Show lists of hosts to be added + ansible.builtin.debug: + msg: "New hosts will be added: {{ __sap_hana_install_fact_addhosts_hosts_new | join(', ') }}" + when: + - __sap_hana_install_fact_addhosts_hosts_new | length > 0 + - not (sap_hana_install_new_system and __sap_hana_install_fact_is_installed) + + +- name: SAP HANA - Addhosts - Pre-Tasks - Set addhosts facts on remaining hosts + ansible.builtin.set_fact: + __sap_hana_install_fact_addhosts_hosts_new: + "{{ hostvars[__sap_hana_install_fact_main_host]['__sap_hana_install_fact_addhosts_hosts_new'] }}" + __sap_hana_install_fact_addhosts_hosts: + "{{ hostvars[__sap_hana_install_fact_main_host]['__sap_hana_install_fact_addhosts_hosts'] }}" + when: + - __sap_hana_install_fact_is_scaleout + - not __sap_hana_install_fact_is_main_host + +- name: SAP HANA - Addhosts - Pre-Tasks - Set fact with boolean flag for new hosts + ansible.builtin.set_fact: + __sap_hana_install_fact_is_new_addhost_host: + "{{ ([ansible_hostname, inventory_hostname, inventory_hostname_short] + | intersect(__sap_hana_install_fact_addhosts_hosts_new | d([]))) | length > 0 }}" + + +- name: SAP HANA - Addhosts - Pre-Tasks - Fail if SAP HANA is not found when addhosts is used + ansible.builtin.fail: + msg: | + FAIL: The existing SAP HANA System was not detected when adding new hosts! + This is required when the variable 'sap_hana_install_new_system' is set to false. + when: + - not sap_hana_install_new_system + - not __sap_hana_install_fact_is_installed + - __sap_hana_install_fact_is_main_host diff --git a/roles/sap_hana_install/tasks/pre_install/prepare_sapcar.yml b/roles/sap_hana_install/tasks/pre_tasks/prepare_sapcar.yml similarity index 92% rename from roles/sap_hana_install/tasks/pre_install/prepare_sapcar.yml rename to roles/sap_hana_install/tasks/pre_tasks/prepare_sapcar.yml index 32045bfb5..b8d3ea95a 100644 --- a/roles/sap_hana_install/tasks/pre_install/prepare_sapcar.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/prepare_sapcar.yml @@ -2,16 +2,16 @@ --- # hdblcm prepare SAPCAR -- name: SAP HANA hdblcm prepare - SAPCAR defined - Prepare the SAPCAR executable if 'sap_hana_install_sapcar_filename' is defined +- name: SAP HANA - Pre-Tasks - Prepare the SAPCAR executable if 'sap_hana_install_sapcar_filename' is defined when: sap_hana_install_sapcar_filename is defined block: - - name: SAP HANA hdblcm prepare - SAPCAR defined - Check if the SAPCAR executable exists + - name: SAP HANA - Pre-Tasks - Check if the SAPCAR executable exists ansible.builtin.stat: path: "{{ __sap_hana_install_fact_software_directory }}/{{ sap_hana_install_sapcar_filename }}" register: __sap_hana_install_register_sapcar_stat - - name: SAP HANA hdblcm prepare - SAPCAR defined - Fail if the SAPCAR executable does not exist + - name: SAP HANA - Pre-Tasks - Fail if the SAPCAR executable does not exist ansible.builtin.fail: msg: "FAIL: The SAPCAR EXE file '{{ __sap_hana_install_fact_software_directory }}/{{ sap_hana_install_sapcar_filename }}' does not exist!" when: not __sap_hana_install_register_sapcar_stat.stat.exists @@ -19,7 +19,7 @@ # We cannot always use the SAPCAR executable in __sap_hana_install_fact_software_directory because there are # some configurations in which executing files in this directory is not possible. So we always copy SAPCAR # to directory 'sapcar' in sap_hana_install_software_extract_directory. We do not copy the SAPCAR checksum file. - - name: SAP HANA hdblcm prepare - SAPCAR defined - Copy the SAPCAR executable to '{{ sap_hana_install_software_extract_directory }}/sapcar' + - name: SAP HANA - Pre-Tasks - Copy the SAPCAR executable to '{{ sap_hana_install_software_extract_directory }}/sapcar' ansible.builtin.copy: src: "{{ __sap_hana_install_fact_software_directory }}/{{ sap_hana_install_sapcar_filename }}" dest: "{{ sap_hana_install_software_extract_directory }}/sapcar/{{ sap_hana_install_sapcar_filename }}" @@ -28,7 +28,7 @@ group: 'root' mode: '0755' - - name: SAP HANA hdblcm prepare - SAPCAR defined - Separate file from directory names and add the global checksum file path + - name: SAP HANA - Pre-Tasks - Separate file from directory names and add the global checksum file path ansible.builtin.set_fact: __sap_hana_install_fact_sapcar_dict_tmp: { dir: "{{ sap_hana_install_software_extract_directory }}/sapcar", @@ -37,7 +37,7 @@ } when: sap_hana_install_global_checksum_file is defined - - name: SAP HANA hdblcm prepare - SAPCAR defined - Separate file from directory names and add the specific checksum file path + - name: SAP HANA - Pre-Tasks - Separate file from directory names and add the specific checksum file path ansible.builtin.set_fact: __sap_hana_install_fact_sapcar_dict_tmp: { dir: "{{ sap_hana_install_software_extract_directory }}/sapcar", @@ -46,11 +46,11 @@ } when: sap_hana_install_global_checksum_file is not defined - - name: SAP HANA hdblcm prepare - SAPCAR defined - Create a list of one dict for checksum verification + - name: SAP HANA - Pre-Tasks - Create a list of one dict for checksum verification ansible.builtin.set_fact: __sap_hana_install_fact_sapcar_dict: "{{ __sap_hana_install_fact_sapcar_dict | d([]) + [__sap_hana_install_fact_sapcar_dict_tmp] }}" - - name: SAP HANA hdblcm prepare - SAPCAR defined - Verify checksum for the SAPCAR executable + - name: SAP HANA - Pre-Tasks - Verify checksum for the SAPCAR executable ansible.builtin.include_tasks: verify_checksum.yml loop: "{{ __sap_hana_install_fact_sapcar_dict }}" loop_control: @@ -59,7 +59,7 @@ - __sap_hana_install_fact_sapcar_dict | length > 0 - sap_hana_install_verify_checksums - - name: SAP HANA hdblcm prepare - SAPCAR defined - Set fact for the SAPCAR executable from variable + - name: SAP HANA - Pre-Tasks - Set fact for the SAPCAR executable from variable ansible.builtin.set_fact: __sap_hana_install_fact_selected_sapcar_filename: "{{ sap_hana_install_sapcar_filename }}" diff --git a/roles/sap_hana_install/tasks/pre_install/prepare_sarfiles.yml b/roles/sap_hana_install/tasks/pre_tasks/prepare_sarfiles.yml similarity index 72% rename from roles/sap_hana_install/tasks/pre_install/prepare_sarfiles.yml rename to roles/sap_hana_install/tasks/pre_tasks/prepare_sarfiles.yml index f9693d3a9..b41a33448 100644 --- a/roles/sap_hana_install/tasks/pre_install/prepare_sarfiles.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/prepare_sarfiles.yml @@ -2,19 +2,19 @@ --- # hdblcm prepare sarfiles -- name: SAP HANA hdblcm prepare - Set fact for final location of SAR files, default +- name: SAP HANA - Pre-Tasks - Set fact for final location of SAR files, default ansible.builtin.set_fact: __sap_hana_install_fact_sar_dir: "{{ __sap_hana_install_fact_software_directory }}" -- name: SAP HANA hdblcm prepare - Set fact list of SAR files if 'sap_hana_install_sarfiles' is defined +- name: SAP HANA - Pre-Tasks - Set fact list of SAR files if 'sap_hana_install_sarfiles' is defined ansible.builtin.set_fact: __sap_hana_install_fact_sarfiles: "{{ sap_hana_install_sarfiles | d([]) }}" -- name: SAP HANA hdblcm prepare - Find all SAR files if 'sap_hana_install_sarfiles' is undefined +- name: SAP HANA - Pre-Tasks - Find all SAR files if 'sap_hana_install_sarfiles' is undefined when: sap_hana_install_sarfiles is not defined block: - - name: SAP HANA hdblcm prepare - Find all SAR files in '{{ __sap_hana_install_fact_software_directory }}' + - name: SAP HANA - Pre-Tasks - Find all SAR files in '{{ __sap_hana_install_fact_software_directory }}' ansible.builtin.find: paths: "{{ __sap_hana_install_fact_software_directory }}" recurse: false @@ -22,7 +22,7 @@ patterns: '*.SAR' register: __sap_hana_install_register_find_sarfiles - - name: SAP HANA hdblcm prepare - Create list of file names from the find result + - name: SAP HANA - Pre-Tasks - Create list of file names from the find result ansible.builtin.set_fact: __sap_hana_install_fact_sarfiles: "{{ __sap_hana_install_fact_sarfiles | d([]) + [item.path | basename] }}" loop: "{{ __sap_hana_install_register_find_sarfiles.files }}" @@ -31,13 +31,13 @@ when: sap_hana_install_copy_sarfiles block: - - name: SAP HANA hdblcm prepare - Create directory '{{ sap_hana_install_software_extract_directory }}/sarfiles' + - name: SAP HANA - Pre-Tasks - Create directory '{{ sap_hana_install_software_extract_directory }}/sarfiles' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/sarfiles" state: directory mode: '0755' - - name: SAP HANA hdblcm prepare - Copy SAR files to '{{ sap_hana_install_software_extract_directory }}/sarfiles' + - name: SAP HANA - Pre-Tasks - Copy SAR files to '{{ sap_hana_install_software_extract_directory }}/sarfiles' ansible.builtin.copy: src: "{{ __sap_hana_install_fact_software_directory }}/{{ item }}" dest: "{{ sap_hana_install_software_extract_directory }}/sarfiles/{{ item }}" @@ -47,11 +47,11 @@ group: root with_items: "{{ __sap_hana_install_fact_sarfiles }}" - - name: SAP HANA hdblcm prepare - Set fact for final location of SAR files, copy_sarfiles + - name: SAP HANA - Pre-Tasks - Set fact for final location of SAR files, copy_sarfiles ansible.builtin.set_fact: __sap_hana_install_fact_sar_dir: "{{ sap_hana_install_software_extract_directory }}/sarfiles" -- name: SAP HANA hdblcm prepare - Fail if no SAR files were found +- name: SAP HANA - Pre-Tasks - Fail if no SAR files were found ansible.builtin.fail: msg: | {% if sap_hana_install_sarfiles is defined -%} @@ -65,9 +65,10 @@ - name: Display the resulting list of SAR file names ansible.builtin.debug: - var: __sap_hana_install_fact_sarfiles + msg: "{{ __sap_hana_install_fact_sarfiles }}" + when: __sap_hana_install_fact_sarfiles is defined -- name: SAP HANA hdblcm prepare - Fill list of dicts containing dir, file, and global checksum file +- name: SAP HANA - Pre-Tasks - Fill list of dicts containing dir, file, and global checksum file ansible.builtin.set_fact: __sap_hana_install_fact_sarfiles_dict: "{{ __sap_hana_install_fact_sarfiles_dict | d([]) + [__sap_hana_install_tmp_sarfiles_dict] }}" with_items: "{{ __sap_hana_install_fact_sarfiles }}" @@ -78,7 +79,7 @@ checksum_file: "{{ sap_hana_install_global_checksum_file }}" when: sap_hana_install_global_checksum_file is defined -- name: SAP HANA hdblcm prepare - Fill list of dicts containing dir, file, and specific checksum file +- name: SAP HANA - Pre-Tasks - Fill list of dicts containing dir, file, and specific checksum file ansible.builtin.set_fact: __sap_hana_install_fact_sarfiles_dict: "{{ __sap_hana_install_fact_sarfiles_dict | d([]) + [__sap_hana_install_tmp_sarfiles_dict] }}" with_items: "{{ __sap_hana_install_fact_sarfiles }}" @@ -89,7 +90,7 @@ checksum_file: "{{ __sap_hana_install_fact_software_directory }}/{{ item }}.sha256" when: sap_hana_install_global_checksum_file is not defined -- name: SAP HANA hdblcm prepare - Verify checksums for all SAR files in folder '{{ __sap_hana_install_fact_sar_dir }}' +- name: SAP HANA - Pre-Tasks - Verify checksums for all SAR files in folder '{{ __sap_hana_install_fact_sar_dir }}' ansible.builtin.include_tasks: verify_checksum.yml loop: "{{ __sap_hana_install_fact_sarfiles_dict }}" loop_control: @@ -99,7 +100,7 @@ - not ansible_check_mode - sap_hana_install_verify_checksums -- name: SAP HANA hdblcm prepare - Extract all SAR files in folder '{{ __sap_hana_install_fact_software_directory }}' +- name: SAP HANA - Pre-Tasks - Extract all SAR files in folder '{{ __sap_hana_install_fact_software_directory }}' ansible.builtin.include_tasks: extract_sarfile.yml loop: "{{ __sap_hana_install_fact_sarfiles }}" loop_control: @@ -109,7 +110,7 @@ - not ansible_check_mode tags: sap_hana_install_extract_sarfiles -- name: SAP HANA hdblcm prepare - Remove temporary SAR file directory '{{ sap_hana_install_software_extract_directory }}/sarfiles' +- name: SAP HANA - Pre-Tasks - Remove temporary SAR file directory '{{ sap_hana_install_software_extract_directory }}/sarfiles' ansible.builtin.file: path: "{{ sap_hana_install_software_extract_directory }}/sarfiles/" state: absent diff --git a/roles/sap_hana_install/tasks/pre_tasks/prepare_software_addhosts.yml b/roles/sap_hana_install/tasks/pre_tasks/prepare_software_addhosts.yml new file mode 100644 index 000000000..cdeb51062 --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/prepare_software_addhosts.yml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +# For an addhosts operation, we first use the hdblcm command for creating a new configfile template, which +# we then process with the templating engine. The actual addhosts installation is done via the resident hdblcm. +# Non-resident hdblcm is used to avoid issues when attempting to generate configfile with resident hdblcm. + +# 'sap_hana_install_software_extract_directory' is required for configfile creation. +- name: SAP HANA - Addhosts - Pre-Tasks - Get status of the directory '{{ sap_hana_install_software_extract_directory }}' + ansible.builtin.stat: + path: "{{ sap_hana_install_software_extract_directory }}" + check_mode: false + register: __sap_hana_install_register_stat_extract_directory + failed_when: false + +- name: SAP HANA - Addhosts - Pre-Tasks - Fail if '{{ sap_hana_install_software_extract_directory }}' does not exist + ansible.builtin.fail: + msg: | + FAIL: The directory {{ sap_hana_install_software_extract_directory }} does not exist. + Path must be defined in the variable 'sap_hana_install_software_extract_directory'. + when: not __sap_hana_install_register_stat_extract_directory.stat.exists + +- name: SAP HANA - Addhosts - Pre-Tasks - Find directory 'SAP_HANA_DATABASE' in '{{ sap_hana_install_software_extract_directory }}' + ansible.builtin.find: + paths: "{{ sap_hana_install_software_extract_directory }}" + recurse: true + file_type: directory + patterns: 'SAP_HANA_DATABASE' + register: __sap_hana_install_register_find_directory_sap_hana_database_addhosts + +- name: SAP HANA - Addhosts - Pre-Tasks - Fail if directory 'SAP_HANA_DATABASE' does not exist in '{{ sap_hana_install_software_extract_directory }}' + ansible.builtin.fail: + msg: | + FAIL: The directory {{ sap_hana_install_software_extract_directory }} does not contain directory 'SAP_HANA_DATABASE'. + when: __sap_hana_install_register_find_directory_sap_hana_database_addhosts.files | length == 0 + +- name: SAP HANA - Addhosts - Pre-Tasks - Set fact for 'hdblcm' installer directory, addhosts + ansible.builtin.set_fact: + __sap_hana_install_fact_hdblcm_path: + "{{ __sap_hana_install_register_find_directory_sap_hana_database_addhosts.files[0].path }}" + + +# Create temporary directory and hdblcm configuration file. +- name: SAP HANA - Addhosts - Pre-Tasks - Create temporary directory to store various files + ansible.builtin.tempfile: + state: directory + suffix: hanaconfig + register: __sap_hana_install_register_tmpdir + tags: + - sap_hana_install_hdblcm_commandline + - sap_hana_install_check_installation + +- name: SAP HANA - Addhosts - Pre-Tasks - Fill variable __sap_hana_install_register_tmpdir for check mode only + ansible.builtin.set_fact: + __sap_hana_install_register_tmpdir: + path: '/tmp' + when: ansible_check_mode diff --git a/roles/sap_hana_install/tasks/pre_tasks/prepare_software_install.yml b/roles/sap_hana_install/tasks/pre_tasks/prepare_software_install.yml new file mode 100644 index 000000000..6a92ba6b8 --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/prepare_software_install.yml @@ -0,0 +1,142 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA - Install - Pre-Tasks - Normalize directory path + ansible.builtin.set_fact: + __sap_hana_install_fact_software_directory: "{{ sap_hana_install_software_directory | regex_replace('\\/$', '') }}" + +- name: SAP HANA - Install - Pre-Tasks - Check availability of software directory '{{ __sap_hana_install_fact_software_directory }}' + ansible.builtin.stat: + path: "{{ __sap_hana_install_fact_software_directory }}" + check_mode: false + register: __sap_hana_install_register_stat_software_directory + failed_when: false + +- name: SAP HANA - Install - Pre-Tasks - Assert that the software directory exists + ansible.builtin.assert: + that: __sap_hana_install_register_stat_software_directory.stat.exists + fail_msg: "FAIL: The software directory '{{ __sap_hana_install_fact_software_directory }}' does not exist!" + success_msg: "PASS: The software directory '{{ __sap_hana_install_fact_software_directory }}' exist." + +- name: > + SAP HANA - Install - Pre-Tasks - Assert directory permissions in case `sap_hana_install_software_extract_directory` + is below `sap_hana_install_software_extract_directory` + when: sap_hana_install_software_extract_directory is search(sap_hana_install_software_directory) + block: + + - name: SAP HANA - Install - Pre-Tasks - Set fact for number of directory levels of the software directory + ansible.builtin.set_fact: + __sap_hana_install_fact_software_directory_levels: "{{ __sap_hana_install_fact_software_directory | regex_findall('/') | length }}" + + - name: SAP HANA - Install - Pre-Tasks - Assert directory permissions + ansible.builtin.include_tasks: + file: pre_tasks/software_directory_permissions.yml + loop: "{{ range(1, __sap_hana_install_fact_software_directory_levels | int + 1, 1) | list }}" + loop_control: + loop_var: line_item + +- name: SAP HANA - Install - Pre-Tasks - Get info about software extract directory '{{ sap_hana_install_software_extract_directory }}' + ansible.builtin.stat: + path: "{{ sap_hana_install_software_extract_directory }}" + check_mode: false + register: __sap_hana_install_register_stat_software_extract_directory + failed_when: false + +- name: SAP HANA - Install - Pre-Tasks - Change ownership of software extract directory '{{ sap_hana_install_software_extract_directory }}' + ansible.builtin.file: + path: "{{ sap_hana_install_software_extract_directory }}" + state: directory + recurse: true + mode: '0755' + owner: root + group: root + when: __sap_hana_install_register_stat_software_extract_directory.stat.exists + +# In case more than one installation is ongoing and extracting to the same shared directory, wait until the extraction has completed: +- name: SAP HANA - Install - Pre-Tasks - Suspending if extraction status file '{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__' exists + ansible.builtin.wait_for: + path: "{{ sap_hana_install_software_extract_directory }}/__EXTRACTION_ONGOING__" + state: absent + failed_when: false + +- name: SAP HANA - Install - Pre-Tasks - Find directory 'SAP_HANA_DATABASE' if '{{ sap_hana_install_software_extract_directory }}' exists + ansible.builtin.find: + paths: "{{ sap_hana_install_software_extract_directory }}" + recurse: true + file_type: directory + patterns: 'SAP_HANA_DATABASE' + register: __sap_hana_install_register_find_directory_sap_hana_database_initial + when: __sap_hana_install_register_stat_software_extract_directory.stat.exists + +# All SAPCAR and SAR files pre_tasks steps will be skipped if role `sap_install_media_detect` successfully extracts software. +- name: SAP HANA - Install - Pre-Tasks - Set directory of 'hdblcm' from successful find result + when: + - __sap_hana_install_register_stat_software_extract_directory.stat.exists + - __sap_hana_install_register_find_directory_sap_hana_database_initial.files[0] is defined + block: + + - name: SAP HANA - Install - Pre-Tasks - Set fact for 'hdblcm' installer directory if found initially + ansible.builtin.set_fact: + __sap_hana_install_fact_hdblcm_path: "{{ __sap_hana_install_register_find_directory_sap_hana_database_initial.files[0].path }}" + + - name: SAP HANA - Install - Pre-Tasks - Get info about '{{ __sap_hana_install_fact_hdblcm_path }}/hdblcm' if found initially + ansible.builtin.stat: + path: "{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}" + check_mode: false + register: __sap_hana_install_register_stat_hdblcm_initial + failed_when: false + + - name: SAP HANA - Install - Pre-Tasks - Assert that file 'hdblcm' is available if found initially + ansible.builtin.assert: + that: __sap_hana_install_register_stat_hdblcm_initial.stat.exists + fail_msg: "FAIL: File '{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}' could not be found. Installation of SAP HANA is not possible." + success_msg: "Using '{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}' for the installation of SAP HANA." + +- name: SAP HANA - Install - Pre-Tasks - Extract SAR files if file 'hdblcm' was not found initially + when: __sap_hana_install_register_find_directory_sap_hana_database_initial.files[0] is not defined + block: + + - name: SAP HANA - Install - Pre-Tasks - Run hdblcm prepare + ansible.builtin.include_tasks: pre_tasks/hdblcm_prepare.yml + + - name: SAP HANA - Install - Pre-Tasks - Display 'hdblcm' installer directory + ansible.builtin.debug: + msg: "{{ __sap_hana_install_fact_hdblcm_path }}" + when: __sap_hana_install_fact_hdblcm_path is defined + + - name: SAP HANA - Install - Pre-Tasks - Set __sap_hana_install_fact_hdblcm_path in case of check mode + ansible.builtin.set_fact: + __sap_hana_install_fact_hdblcm_path: '/software/hana/extracted' + when: ansible_check_mode + + - name: SAP HANA - Install - Pre-Tasks - Get info about '{{ __sap_hana_install_fact_hdblcm_path }}/hdblcm' + ansible.builtin.stat: + path: "{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}" + check_mode: false + register: __sap_hana_install_register_stat_hdblcm + failed_when: false + + - name: SAP HANA - Install - Pre-Tasks - Assert that file 'hdblcm' is available + ansible.builtin.assert: + that: __sap_hana_install_register_stat_hdblcm.stat.exists + fail_msg: "FAIL: File 'hdblcm' could not be found. Installation of SAP HANA is not possible." + success_msg: "Using file '{{ __sap_hana_install_fact_hdblcm_path + '/hdblcm' }}' for the installation of SAP HANA." + when: not ansible_check_mode + + +# Create temporary directory and hdblcm configuration file. +- name: SAP HANA - Install - Pre-Tasks - Create temporary directory to store various files + ansible.builtin.tempfile: + state: directory + suffix: hanaconfig + register: __sap_hana_install_register_tmpdir + when: not __sap_hana_install_fact_is_installed + tags: + - sap_hana_install_hdblcm_commandline + - sap_hana_install_check_installation + +- name: SAP HANA - Install - Pre-Tasks - Fill variable __sap_hana_install_register_tmpdir for check mode only + ansible.builtin.set_fact: + __sap_hana_install_register_tmpdir: + path: '/tmp' + when: ansible_check_mode diff --git a/roles/sap_hana_install/tasks/pre_tasks/selinux.yml b/roles/sap_hana_install/tasks/pre_tasks/selinux.yml new file mode 100644 index 000000000..3260a4459 --- /dev/null +++ b/roles/sap_hana_install/tasks/pre_tasks/selinux.yml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +--- + +- name: SAP HANA - Pre-Tasks - Configure 'sap_hana_install_root_path' SELinux file contexts + ansible.builtin.include_role: + name: '{{ sap_hana_install_system_roles_collection }}.selinux' + vars: + selinux_booleans: + - { name: 'selinuxuser_execmod', state: 'on' } + selinux_fcontexts: + - { target: '{{ sap_hana_install_root_path }}(/.*)?', setype: 'usr_t' } + selinux_restore_dirs: + - '{{ sap_hana_install_root_path }}' diff --git a/roles/sap_hana_install/tasks/pre_install-loop-block.yml b/roles/sap_hana_install/tasks/pre_tasks/software_directory_permissions.yml similarity index 71% rename from roles/sap_hana_install/tasks/pre_install-loop-block.yml rename to roles/sap_hana_install/tasks/pre_tasks/software_directory_permissions.yml index c27dbdc57..dff53a946 100644 --- a/roles/sap_hana_install/tasks/pre_install-loop-block.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/software_directory_permissions.yml @@ -1,27 +1,23 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA Pre Install - Set __sap_hana_install_fact_tmp_dirname +- name: SAP HANA - Pre-Tasks - Set the software directory name ansible.builtin.set_fact: __sap_hana_install_fact_tmp_dirname: "{{ (__sap_hana_install_fact_tmp_dirname + '/' + __sap_hana_install_fact_software_directory.split(\"/\")[line_item | int]) | string }}" -- name: SAP HANA Pre Install - Get directory info +- name: SAP HANA - Pre-Tasks - Get directory info ansible.builtin.stat: path: "{{ __sap_hana_install_fact_tmp_dirname }}" register: __sap_hana_install_register_stat_dirname -- name: SAP HANA Pre Install - Display all users permissions for the directory +- name: SAP HANA - Pre-Tasks - Display all users permissions for the directory ansible.builtin.debug: msg: "'{{ __sap_hana_install_fact_tmp_dirname }}' has all users permissions '{{ __sap_hana_install_register_stat_dirname.stat.mode[-1] }}'." -- name: SAP HANA Pre Install - Assert that the directory is world executable +- name: SAP HANA - Pre-Tasks - Assert that the directory is world executable ansible.builtin.assert: that: __sap_hana_install_register_stat_dirname.stat.mode[-1] == '1' or __sap_hana_install_register_stat_dirname.stat.mode[-1] == '5' or __sap_hana_install_register_stat_dirname.stat.mode[-1] == '7' fail_msg: "FAIL: The directory {{ __sap_hana_install_fact_tmp_dirname }} has all users permission '{{ __sap_hana_install_register_stat_dirname.stat.mode[-1] }}' but needs to be world executable! Either change the all users execute permissions or use a separate directory for 'sap_hana_install_software_extract_directory'." success_msg: "PASS: The directory {{ __sap_hana_install_fact_tmp_dirname }} is world executable." - -#- name: SAP HANA Pre Install - Set __sap_hana_install_fact_software_directories -# ansible.builtin.set_fact: -# __sap_hana_install_fact_software_directories: "{{ __sap_hana_install_fact_software_directories | d([]) + [__sap_hana_install_fact_tmp_dirname] }}" diff --git a/roles/sap_hana_install/tasks/pre_install/verify_checksum.yml b/roles/sap_hana_install/tasks/pre_tasks/verify_checksum.yml similarity index 80% rename from roles/sap_hana_install/tasks/pre_install/verify_checksum.yml rename to roles/sap_hana_install/tasks/pre_tasks/verify_checksum.yml index 125e25a65..7838a543d 100644 --- a/roles/sap_hana_install/tasks/pre_install/verify_checksum.yml +++ b/roles/sap_hana_install/tasks/pre_tasks/verify_checksum.yml @@ -1,12 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: SAP HANA hdblcm prepare - Check if checksum file exists +- name: SAP HANA - Pre-Tasks - Check if checksum file exists ansible.builtin.stat: path: "{{ __sap_hana_install_passed_file_dict.checksum_file }}" register: __sap_hana_install_register_stat_checksum_file -- name: SAP HANA hdblcm prepare - Fail if the checksum file is missing +- name: SAP HANA - Pre-Tasks - Fail if the checksum file is missing ansible.builtin.fail: msg: "FAIL: Missing checksum file '{{ __sap_hana_install_passed_file_dict.checksum_file }}'!" when: not __sap_hana_install_register_stat_checksum_file.stat.exists @@ -18,25 +18,25 @@ # We are using awk to search for the file name in the checksum file. If there is no entry for the file, instead of # displaying the checksum for the file, we display the string 'Missing entry' on stdout. # 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] + - name: SAP HANA - Pre-Tasks - 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: false register: __sap_hana_install_register_checksum_from_file 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 }}' + - name: SAP HANA - Pre-Tasks - 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: msg: "FAIL: Missing entry for file '{{ __sap_hana_install_passed_file_dict.file }}' in '{{ __sap_hana_install_passed_file_dict.checksum_file }}'!" when: __sap_hana_install_register_checksum_from_file.stdout == 'Missing entry' - - name: SAP HANA hdblcm prepare - Calculate checksum of '{{ __sap_hana_install_passed_file_dict.file }}' + - name: SAP HANA - Pre-Tasks - Calculate checksum of '{{ __sap_hana_install_passed_file_dict.file }}' ansible.builtin.stat: path: "{{ __sap_hana_install_passed_file_dict.dir }}/{{ __sap_hana_install_passed_file_dict.file }}" checksum_algorithm: "{{ sap_hana_install_checksum_algorithm }}" register: __sap_hana_install_register_stat_file when: __sap_hana_install_register_checksum_from_file.stdout != 'Missing entry' - - name: SAP HANA hdblcm prepare - Assert that the checksum of the SAR file is correct + - name: SAP HANA - Pre-Tasks - Assert that the checksum of the SAR file is correct ansible.builtin.assert: that: __sap_hana_install_register_stat_file.stat.checksum == __sap_hana_install_register_checksum_from_file.stdout.split(' ').0 diff --git a/roles/sap_hana_install/vars/main.yml b/roles/sap_hana_install/vars/main.yml index e2173a862..6be591363 100644 --- a/roles/sap_hana_install/vars/main.yml +++ b/roles/sap_hana_install/vars/main.yml @@ -38,3 +38,45 @@ __sap_hana_install_architecture_matrix: # Example: SAPCAR_1400-80008313.EXE: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked, # interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=f40042b59e928aacfff753e59686be4d6e242998, for GNU/Linux 3.7.0, not stripped - ['aarch64'] + +# Sets the default host which will run all non-addhosts tasks. +__sap_hana_install_fact_main_host: "{{ ansible_hostname }}" + +# Sets default value of Scale-Out detection. +# Detection for scaleout is based on addhosts string. +__sap_hana_install_fact_is_scaleout: false + +# Sets default value of HANA exists detection. +__sap_hana_install_fact_is_installed: false + +# The list of all valid hostnames in addhosts string including Managed node. +# - Used for running all configuration tasks for idempotency. +__sap_hana_install_fact_all_hosts: [] + +# The list of all valid hostnames in addhosts string. +# - Used only for setting '__sap_hana_install_fact_addhosts_hosts_new' and '__sap_hana_install_fact_all_hosts'. +__sap_hana_install_fact_addhosts_hosts: [] + +# The list of all valid hostnames in addhosts string without host with existing profiles or directories. +# - Used for replacing addhosts string in hdblcm configfile. +__sap_hana_install_fact_addhosts_hosts_new: [] + +# The flags used for separation of tasks between hosts +# This is main host where hdblcm is executed. +__sap_hana_install_fact_is_main_host: false +# This is for hosts defined in addhosts string. +__sap_hana_install_fact_is_addhost_host: false +# This is for hosts defined in addhosts string that is not installed yet. +__sap_hana_install_fact_is_new_addhost_host: false + +# Path to LSS shared directory. +__sap_hana_install_lss_inst_path: /lss/shared + +# Flag for SPS08+ systems where LSS is required. +__sap_hana_install_fact_is_lss_required: false + +# List of support shared filesystem types. +__sap_hana_install_shared_filesystem_types: + - nfs + - nfs4 + - cifs diff --git a/roles/sap_swpm/tasks/pre_install.yml b/roles/sap_swpm/tasks/pre_install.yml index 6f2f36b37..fb88f1202 100644 --- a/roles/sap_swpm/tasks/pre_install.yml +++ b/roles/sap_swpm/tasks/pre_install.yml @@ -228,7 +228,7 @@ - name: SAP SWPM Pre Install - Identify FAIL in the templating output ansible.builtin.set_fact: __sap_swpm_fact_inifile_vars_validation_failures: | - {{ (__sap_swpm_register_inifile_vars_validation_test_result.content | b64decode).splitlines() + {{ __sap_swpm_register_inifile_vars_validation_test_result.content | b64decode | split('\n') | select('match', '^(?!#).*ERROR:.*') | unique | d([])