Skip to content

Commit 8712ba5

Browse files
authored
Merge pull request sap-linuxlab#1215 from marcelmamula/hana-fix
sap_hana_install: Update Pseudo-Idempotency
2 parents 45c153d + 8427e59 commit 8712ba5

17 files changed

Lines changed: 751 additions & 425 deletions

roles/sap_hana_install/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ Installs SAP HANA on `host1` and `host2`, while running on host `host0` where ex
377377
```yaml
378378
---
379379
- name: Ansible Play for SAP HANA installation - Add hosts
380-
hosts: host0, host1
380+
hosts: host0, host1, host2
381381
become: true
382382
tasks:
383383
- name: Execute Ansible Role sap_hana_install

roles/sap_hana_install/defaults/main.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,9 @@ sap_hana_install_keep_copied_sarfiles: false
3434
# For installing SAP HANA with fapolicyd support, set the following variable to `true`:
3535
sap_hana_install_configure_fapolicyd: false
3636

37-
# (RedHat specific) desired fapolicyd service status (only if sap_hana_install_configure_fapolicyd is 'true')
38-
# For not enabling and not starting the fapolicyd service after the installation has finished, set the following
39-
# variable to `false`:
40-
sap_hana_install_enable_fapolicyd: true
37+
# (RedHat specific) desired fapolicyd service status (only if 'sap_hana_install_configure_fapolicyd' is set to 'true').
38+
# For enabling and starting the fapolicyd service after the installation has finished, set the following variable to 'true'.
39+
sap_hana_install_enable_fapolicyd: false
4140

4241
# (RedHat specific) fapolicyd integrity level
4342
# When using fapolicyd, you can set the following variable to one of `none`, `size`, `sha256`, or `ima`. Note that before setting
@@ -274,3 +273,7 @@ sap_hana_install_create_initial_tenant: 'y'
274273

275274
# Display SAP HANA hdblcm unattended mode output (hdblcm stdout)
276275
sap_hana_install_display_unattended_output: false
276+
277+
# (Optional) Set to `true` to skip the filesystem check during SAP HANA installation.
278+
# This is not recommended, but can be used in case of a non-Production environment.
279+
sap_hana_install_skip_filesystem_check: false

roles/sap_hana_install/tasks/hana_addhosts.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
cmd: "{{ __sap_hana_install_hdblcm_command }}"
5353
register: __sap_hana_install_register_hdblcm_add_hosts
5454
args:
55-
chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm"
55+
chdir: "{{ __sap_hana_install_shared_path }}/hdblcm"
5656
changed_when: "'SAP HANA Lifecycle Management' in __sap_hana_install_register_hdblcm_add_hosts.stdout"
5757
when: not ansible_check_mode
5858

roles/sap_hana_install/tasks/main.yml

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,34 @@
4545
tags: always
4646
tags: always
4747

48+
49+
# Process all hosts in play and define flag facts based on their intended role during installation.
50+
# - Detect Scale-Out and Addhosts operations.
51+
# - Set host identification flags
52+
# - Validate addhosts list against hosts in the play.
53+
- name: SAP HANA - Main - Identify hosts in play
54+
ansible.builtin.include_tasks:
55+
file: pre_tasks/identify_hosts.yml
56+
57+
4858
# SAP HANA presence has to be validated for both new system and adding new hosts.
59+
# - Detection is executed even in force mode, but fails are skipped to allow execution of the role.
60+
# - Host identification flags are used to ignore /hana/shared file detection check for Scale-Out addhosts hosts.
4961
- name: SAP HANA - Main - Validate presence of existing SAP HANA database
5062
ansible.builtin.include_tasks:
51-
file: pre_tasks/hana_exists.yml
63+
file: pre_tasks/detect_hana.yml
5264
apply:
5365
tags:
5466
- sap_hana_install_check_hana_exists
55-
when:
56-
- (sap_hana_install_new_system and not sap_hana_install_force)
57-
or not sap_hana_install_new_system
5867
tags:
5968
- sap_hana_install_check_hana_exists
6069

6170

62-
- name: SAP HANA - Main - Identify hosts in play based on addhosts
71+
# Validate detected SAP installations against allowed Scale-Out scenarios.
72+
- name: SAP HANA - Main - Validate hosts in play
6373
ansible.builtin.include_tasks:
64-
file: pre_tasks/identify_hosts.yml
74+
file: pre_tasks/validate_hosts.yml
75+
when: __sap_hana_install_fact_is_scaleout
6576

6677

6778
- name: SAP HANA - Main - Ensure SAP HANA is running for existing systems or addhosts operations
@@ -77,10 +88,18 @@
7788
# - Configuration - Run always to ensure idempotent outcome.
7889

7990
- name: Block for Installation tasks
80-
when: sap_hana_install_new_system or
81-
('sap_hana_install_create_configfile' in ansible_run_tags | d([])) or
82-
('sap_hana_install_hdblcm_commandline' in ansible_run_tags | d([]))
91+
# Stop execution of remaining tasks in the role, if any task in the block failed on any host.
92+
# This ensures that the role does not proceed skipping failed host, but fails the entire role execution.
93+
# 'any_errors_fatal' is not documented to work on task level, therefore we use simple block.
94+
# http://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_error_handling.html#aborting-on-the-first-error-any-errors-fatal
95+
# Runs on all hosts in Scale-Out scenario, but allows independent failures for single host installations.
96+
any_errors_fatal: "{{ true if __sap_hana_install_fact_is_scaleout else false }}"
97+
when:
98+
- sap_hana_install_new_system
99+
or (ansible_run_tags | d([])
100+
| intersect(['sap_hana_install_create_configfile', 'sap_hana_install_hdblcm_commandline'])) | length > 0
83101
block:
102+
# Task file contains pseudo-idempotency checks and cannot be skipped for installed system.
84103
- name: SAP HANA - Install - Pre-Tasks
85104
ansible.builtin.include_tasks:
86105
file: pre_install.yml
@@ -91,9 +110,9 @@
91110
- name: SAP HANA - Install
92111
ansible.builtin.include_tasks:
93112
file: hana_install.yml
94-
when: >
95-
(not __sap_hana_install_fact_is_installed and __sap_hana_install_fact_is_main_host) or
96-
('sap_hana_install_hdblcm_commandline' in ansible_run_tags | d([]))
113+
when:
114+
- (not __sap_hana_install_fact_is_installed and __sap_hana_install_fact_is_main_host)
115+
or (ansible_run_tags | d([]) | intersect(['sap_hana_install_hdblcm_commandline'])) | length > 0
97116
tags: sap_hana_install_hdblcm_commandline
98117

99118
- name: SAP HANA - Install - Post-tasks
@@ -102,20 +121,26 @@
102121

103122

104123
- name: Block for Addhosts tasks
105-
when: >
106-
not sap_hana_install_new_system and
107-
((__sap_hana_install_fact_is_scaleout and __sap_hana_install_fact_is_installed) or
108-
('sap_hana_install_hdblcm_commandline' in ansible_run_tags | d([])) or
109-
('sap_hana_install_create_configfile' in ansible_run_tags | d([])))
124+
# Stop execution of remaining tasks in the role, if any task in the block failed on any host.
125+
# This ensures that the role does not proceed skipping failed host, but fails the entire role execution.
126+
# 'any_errors_fatal' is not documented to work on task level, therefore we use simple block.
127+
# http://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_error_handling.html#aborting-on-the-first-error-any-errors-fatal
128+
# Runs on all hosts in addhosts scenario.
129+
any_errors_fatal: true
130+
when:
131+
- not sap_hana_install_new_system
132+
and (__sap_hana_install_fact_is_scaleout
133+
or (ansible_run_tags | d([])
134+
| intersect(['sap_hana_install_create_configfile', 'sap_hana_install_hdblcm_commandline'])) | length > 0)
110135
block:
111136
# Execute only if new hosts are to be added.
112137
- name: SAP HANA - Addhosts - Pre-Tasks
113138
ansible.builtin.include_tasks:
114139
file: pre_addhosts.yml
115-
when: >
116-
(__sap_hana_install_fact_addhosts_hosts_new | d([]) | length > 0) or
117-
('sap_hana_install_hdblcm_commandline' in ansible_run_tags | d([])) or
118-
('sap_hana_install_create_configfile' in ansible_run_tags | d([]))
140+
when:
141+
- __sap_hana_install_fact_addhosts_hosts_new | d([]) | length > 0
142+
or (ansible_run_tags | d([])
143+
| intersect(['sap_hana_install_create_configfile', 'sap_hana_install_hdblcm_commandline'])) | length > 0
119144
tags:
120145
- sap_hana_install_hdblcm_commandline
121146
- sap_hana_install_create_configfile
@@ -124,9 +149,9 @@
124149
ansible.builtin.include_tasks:
125150
file: hana_addhosts.yml
126151
when:
127-
(__sap_hana_install_fact_addhosts_hosts_new | d([]) | length > 0 and __sap_hana_install_fact_is_main_host) or
128-
('sap_hana_install_hdblcm_commandline' in ansible_run_tags | d([])) or
129-
('sap_hana_install_create_configfile' in ansible_run_tags | d([]))
152+
- (__sap_hana_install_fact_addhosts_hosts_new | d([]) | length > 0 and __sap_hana_install_fact_is_main_host)
153+
or (ansible_run_tags | d([])
154+
| intersect(['sap_hana_install_create_configfile', 'sap_hana_install_hdblcm_commandline'])) | length > 0
130155
tags:
131156
- sap_hana_install_hdblcm_commandline
132157
- sap_hana_install_create_configfile
@@ -148,7 +173,7 @@
148173
gsub ("^\\s*hosts?: ", ""); gsub (", ", ","); print; a=0}
149174
}'
150175
args:
151-
chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm"
176+
chdir: "{{ __sap_hana_install_shared_path }}/hdblcm"
152177
register: __sap_hana_install_register_completion_result
153178
changed_when: false
154179
when:
@@ -164,11 +189,6 @@
164189
SID - {{ sap_hana_install_sid }}
165190
NR - {{ sap_hana_install_number }}
166191
167-
{% if sap_hana_install_new_system and __sap_hana_install_fact_is_installed and __sap_hana_install_fact_addhosts_hosts_new | length > 0 %}
168-
The new hosts defined in the variable 'sap_hana_install_addhosts' were not added: {{ __sap_hana_install_fact_addhosts_hosts_new | join(', ') }}.
169-
Execute this role with the variable 'sap_hana_install_new_system' set to false to add new hosts.
170-
{% endif %}
171-
172192
{% if sap_hana_install_configure_firewall %}
173193
Firewall is enabled and SAP HANA ports are open.
174194
{% endif %}
@@ -179,8 +199,8 @@
179199
Fapolicyd is configured for SAP folders ({{ sap_hana_install_directories | map('quote') | join(', ') }}).
180200
{% endif %}
181201
vars:
182-
__sap_hana_install_fact_hana_version: "{{ __sap_hana_install_register_completion_result.stdout.split(';')[0] }}"
183-
__sap_hana_install_fact_hana_hosts: "{{ __sap_hana_install_register_completion_result.stdout.split(';')[1] }}"
202+
__sap_hana_install_fact_hana_version: "{{ __sap_hana_install_register_completion_result.stdout.split(';')[0] | d('N/A') }}"
203+
__sap_hana_install_fact_hana_hosts: "{{ __sap_hana_install_register_completion_result.stdout.split(';')[1] | d('N/A') }}"
184204
when:
185205
- not ansible_check_mode
186206
- __sap_hana_install_fact_is_main_host

roles/sap_hana_install/tasks/post_addhosts.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@
2727
# Ensure fapolicyd is checked only on supported systems.
2828
- ansible_facts['os_family'] == "RedHat"
2929
- __sap_hana_install_configure_fapolicyd
30+
# Added to ensure that fapolicyd is configured only on new installations
31+
# to avoid trusting potentially compromised files in existing installation.
32+
- __sap_hana_install_fact_is_new_addhost_host

roles/sap_hana_install/tasks/post_install.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- name: Block with tasks for new HANA Systems
66
when:
77
- not __sap_hana_install_fact_is_installed
8+
# Execute only on main host and skip execution on addhosts.
89
- __sap_hana_install_fact_is_main_host
910
block:
1011

@@ -75,3 +76,6 @@
7576
# Ensure fapolicyd is checked only on supported systems.
7677
- ansible_facts['os_family'] == "RedHat"
7778
- __sap_hana_install_configure_fapolicyd
79+
# Added to ensure that fapolicyd is configured only on new installations
80+
# to avoid trusting potentially compromised files in existing installation.
81+
- not __sap_hana_install_fact_is_installed

roles/sap_hana_install/tasks/post_tasks/check_installation.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
- name: SAP HANA - Post-Tasks - Construct an hdbcheck command line
4040
ansible.builtin.set_fact:
4141
__sap_hana_install_fact_installation_check_command: "set -o pipefail && ./hdbcheck -b --read_password_from_stdin=xml
42-
--property_file={{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/global/hdb/install/support/hdbcheck.xml
42+
--property_file={{ __sap_hana_install_shared_path }}/global/hdb/install/support/hdbcheck.xml
4343
--remote_execution=ssh
4444
--scope=system
4545
-b < {{ __sap_hana_install_register_tmpdir.path }}/configfile.cfg.xml"
@@ -61,7 +61,7 @@
6161
- name: SAP HANA - Post-Tasks - hdbcheck - Perform the check # noqa command-instead-of-shell
6262
ansible.builtin.shell: "{{ __sap_hana_install_fact_installation_check_command }}"
6363
args:
64-
chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/global/hdb/install/bin"
64+
chdir: "{{ __sap_hana_install_shared_path }}/global/hdb/install/bin"
6565
register: __sap_hana_install_register_installation_check
6666
changed_when: false
6767
when: sap_hana_install_use_hdbcheck | d(true)
@@ -77,7 +77,7 @@
7777
- name: SAP HANA - Post-Tasks - hdblcm - Perform the check # noqa command-instead-of-shell
7878
ansible.builtin.shell: "{{ __sap_hana_install_fact_installation_check_command }}"
7979
args:
80-
chdir: "{{ sap_hana_install_shared_path }}/{{ sap_hana_install_sid }}/hdblcm"
80+
chdir: "{{ __sap_hana_install_shared_path }}/hdblcm"
8181
register: __sap_hana_install_register_installation_check
8282
changed_when: false
8383
when: not sap_hana_install_use_hdbcheck | d(true)

roles/sap_hana_install/tasks/post_tasks/user_expiration.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# SPDX-License-Identifier: Apache-2.0
22
---
33

4+
# NOTE: This can be replaced completely by 'ansible.builtin.user' module when we increase minimum ansible version to 2.18!
5+
# Argument '-I' is set by module parameter 'password_expire_account_disable' added in 2.18.
6+
# ansible.builtin.user:
7+
# name: "{{ user_item }}"
8+
# password_expire_min: 0 # chage -m 0
9+
# password_expire_max: 99999 # chage -M 99999
10+
# password_expire_account_disable: -1 # chage -I -1
11+
# expires: -1 # chage -E -1
12+
13+
# Current use of 'chage' will always be marked as change in Ansible logs, regardless of outcome.
414
- name: SAP HANA - Post-Tasks - Set '{{ sap_hana_install_sid | lower }}adm' to not expire
515
ansible.builtin.shell: |
616
chage -m 0 -M 99999 -I -1 -E -1 {{ sap_hana_install_sid | lower }}adm

roles/sap_hana_install/tasks/pre_addhosts.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,16 @@
1717
key: sapadm
1818
failed_when: false
1919

20-
# hana_exists already found existing database, this is additional check.
21-
# getent_group['sapsys'][1] and getent_passwd['sapadm'][2] are Group ID.
22-
- name: SAP HANA - Addhosts - Pre-Tasks - Assert that user 'sapadm' is present with group 'sapsys'
23-
ansible.builtin.assert:
24-
that:
25-
- "'sapsys' in getent_group"
26-
- "'sapadm' in getent_passwd"
27-
# Ensure sapadm user is assigned to sapsys group
28-
- getent_group['sapsys'][1] == getent_passwd['sapadm'][2]
29-
fail_msg: >-
30-
FAIL: User 'sapadm' with group 'sapsys' does not exist!
20+
# detect_hana already found existing database, this is additional check.
21+
# ansible_facts["getent_group"]['sapsys'][1] and ansible_facts["getent_passwd"]['sapadm'][2] are Group ID.
22+
- name: SAP HANA - Addhosts - Pre-Tasks - Fail if user 'sapadm' is not present with group 'sapsys'
23+
ansible.builtin.fail:
24+
msg: |
25+
FAIL: User 'sapadm' with group 'sapsys' does not exist or it has incorrect group ID!
26+
when:
27+
- ansible_facts["getent_group"]['sapsys'] is not defined
28+
or ansible_facts["getent_passwd"]['sapadm'] is not defined
29+
or ansible_facts["getent_group"]['sapsys'][1] != ansible_facts["getent_passwd"]['sapadm'][2]
3130

3231
# TODO: Issue#1123 Remove default to master
3332
- name: SAP HANA - Addhosts - Pre-Tasks - Generate password hash for 'sap_hana_install_sapadm_password'
@@ -82,6 +81,7 @@
8281
- name: SAP HANA - Addhosts - Pre-Tasks - Check shared filesystems
8382
ansible.builtin.include_tasks:
8483
file: pre_tasks/check_filesystems.yml
84+
when: not sap_hana_install_skip_filesystem_check | d(false)
8585

8686

8787
# Update HANA directory permissions

roles/sap_hana_install/tasks/pre_install.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
- name: SAP HANA - Install - Pre-Tasks - Check shared filesystems
4343
ansible.builtin.include_tasks:
4444
file: pre_tasks/check_filesystems.yml
45-
when: __sap_hana_install_fact_is_scaleout
45+
when:
46+
- __sap_hana_install_fact_is_scaleout
47+
- not sap_hana_install_skip_filesystem_check | d(false)
4648

4749

4850
# We need to change permissions only after filesystem check has passed.

0 commit comments

Comments
 (0)