Skip to content

Commit 731e65b

Browse files
authored
Merge pull request sap-linuxlab#1213 from marcelmamula/swpm_idempotent
sap_swpm: Add Pseudo-Idempotency
2 parents 8712ba5 + bb9a969 commit 731e65b

13 files changed

Lines changed: 1249 additions & 215 deletions

roles/sap_swpm/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,13 @@ Define UID of Linux user SIDADM.
685685

686686
### Miscellaneous Variables
687687

688+
#### sap_swpm_force
689+
- _Type:_ `bool`
690+
- _Default:_ `false`
691+
692+
Optional override that forces execution of installation tasks if existing SAP instance is detected.<br>
693+
This variable should be used with caution as running SWPM installation with active SAP instances can lead to corruption of existing SAP installation.
694+
688695
#### sap_swpm_ascs_install_gateway
689696
- _Type:_ `string`
690697
- _Default:_ `true`

roles/sap_swpm/defaults/main.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,20 @@ sap_swpm_display_unattended_output: false
508508

509509
# Set which Ansible Collection to use when calling sap_install roles.
510510
sap_swpm_sap_install_collection: 'community.sap_install'
511+
512+
# Optional override that forces execution of installation tasks if existing SAP instance is detected (Boolean).
513+
# WARNING: This variable should be used with caution
514+
# as running SWPM installation with active SAP instances can lead to corruption of existing SAP installation.
515+
sap_swpm_force: false
516+
517+
# Skip all detection checks. Use ONLY for testing/development on clean systems.
518+
# WARNING: Skipping detection can lead to data loss if installation already exists!
519+
# This will bypass all safety checks including saphostctrl, sapcontrol, and file existence checks.
520+
# sap_swpm_skip_detection: false
521+
522+
# Explicit acknowledgement required for Database Load products (NW_ABAP_DB, NW_Java_DB, etc.) (Boolean).
523+
# These products cannot be detected by this role on empty managed hosts, because no local instance files are created.
524+
# Running SWPM against an existing database WILL DROP and recreate the schema user, causing DATA LOSS on existing systems.
525+
# Set to 'true' only after confirming the target database is empty or intended to be overwritten.
526+
# WARNING: sap_swpm_force does NOT cover this scenario and it only applies to detection of existing instances.
527+
sap_swpm_db_load_force: false

roles/sap_swpm/tasks/main.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,22 @@
4040
tags: always
4141

4242
- name: SAP SWPM - Run pre_install tasks
43-
ansible.builtin.import_tasks: pre_install.yml
43+
ansible.builtin.import_tasks:
44+
file: pre_install.yml
4445
tags:
4546
- sap_swpm_pre_install
4647
- sap_swpm_install
4748

4849
- name: SAP SWPM - Run swpm
49-
ansible.builtin.import_tasks: swpm.yml
50-
when: sap_swpm_run_sapinst
50+
ansible.builtin.import_tasks:
51+
file: swpm.yml
52+
when:
53+
- sap_swpm_run_sapinst
54+
- not __sap_swpm_sap_detected | d(false) or sap_swpm_force | d(false)
5155
tags:
5256
- sap_swpm_install
5357

54-
- name: SAP SWPM - Run postinstall task
55-
ansible.builtin.import_tasks: post_install.yml
58+
- name: SAP SWPM - Run post_install task
59+
ansible.builtin.import_tasks:
60+
file: post_install.yml
5661
when: sap_swpm_run_sapinst
Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,25 @@
11
# SPDX-License-Identifier: Apache-2.0
22
---
33

4-
# Reason for noqa: The command might change things but we do not yet attempt to find out
5-
- name: SAP SWPM Post Install - ensure password expiry disabled {{ sap_swpm_sid | lower + 'adm' }}
6-
ansible.builtin.shell: |
7-
chage -m 0 -M 99999 -I -1 -E -1 {{ sap_swpm_sid | lower }}adm
8-
chage -m 0 -M 99999 -I -1 -E -1 sapadm
9-
args:
10-
executable: /bin/bash
11-
become: true
12-
register: __sap_swpm_post_install_register_sidadm_noexpire
13-
changed_when: __sap_swpm_post_install_register_sidadm_noexpire is succeeded
14-
when: sap_swpm_set_sidadm_noexpire | default(true)
4+
# Set user expiration update
5+
- name: SAP SWPM Post Install - Get list of available OS users
6+
ansible.builtin.getent:
7+
database: passwd
158

16-
# Firewall steps are part of pre_tasks to ensure that ports are open before installation.
17-
18-
########################################################################################################################
9+
# New task file includes detailed steps to set each parameter, instead of all at same time.
10+
- name: SAP SWPM Post Install - Execute user expiration task file
11+
ansible.builtin.include_tasks:
12+
file: post_install/set_password_expiration.yml
13+
loop:
14+
- "{{ sap_swpm_sid | lower }}adm"
15+
- "sapadm"
16+
loop_control:
17+
loop_var: user_item
18+
when:
19+
- user_item in ansible_facts['getent_passwd']
20+
- sap_swpm_set_sidadm_noexpire | d(true)
1921

20-
- name: SAP SWPM Deployment - Finished
21-
ansible.builtin.debug:
22-
msg: |
23-
" SAP SWPM deployment successfully completed "
24-
" "
25-
" SAP Product - {{ sap_swpm_product_catalog_id }} "
26-
" SID - {{ sap_swpm_sid | d('') }} "
27-
" Primary Instance - {{ sap_swpm_pas_instance_nr | d('') }} "
28-
" Host - {{ ansible_facts['hostname'] }} "
29-
" FQDN - {{ ansible_facts['fqdn'] }} "
30-
" IP - {{ ansible_facts['default_ipv4'].address | d(ansible_facts['all_ipv4_addresses'][0]) }} "
31-
# " Master Password - {{ sap_swpm_master_password }} "
32-
# " DDIC 000 Password - {{ sap_swpm_ddic_000_password }} "
22+
# Firewall steps are part of pre_tasks to ensure that ports are open before installation.
3323

3424
# SAP HANA Client will not be installed for any installation with SAP AnyDB
3525
# and will only be installed alongside SAP NWAS PAS or AAS (not NWAS ASCS)
@@ -55,6 +45,49 @@
5545
register: __sap_swpm_post_install_register_hdbuserstore_connection
5646
changed_when: __sap_swpm_post_install_register_hdbuserstore_connection is succeeded
5747

48+
49+
# Restart saphostctrl process to ensure it loads information about newly installed SAP system.
50+
- name: SAP SWPM Post Install - Restart saphostctrl process
51+
ansible.builtin.command:
52+
cmd: /usr/sap/hostctrl/exe/saphostexec -restart
53+
become: true
54+
when:
55+
- sap_swpm_install_saphostagent | d(true)
56+
# Restart only for freshly installed SAP system.
57+
- not __sap_swpm_sap_detected | d(false) or sap_swpm_force | d(false)
58+
# Restart can be always considered changed.
59+
changed_when: true
60+
61+
62+
########################################################################################################################
63+
64+
- name: SAP SWPM Deployment - Display SAP System details after completion
65+
ansible.builtin.debug:
66+
msg: |
67+
SAP System or Instance is deployed.
68+
{% if __sap_swpm_sap_detected | d(false) and not sap_swpm_force | d(false) %}
69+
70+
NOTE: SAP Instance(s) were detected before installation.
71+
SWPM installation steps were skipped to avoid potential issues with existing installation.
72+
73+
If you intend to proceed with the installation despite this warning,
74+
set 'sap_swpm_force' variable to 'true' and execute this Ansible Role again.
75+
{% endif %}
76+
{% if __sap_swpm_sap_detected | d(false) and sap_swpm_force | d(false) %}
77+
78+
NOTE: SAP Instance(s) were detected before installation.
79+
SWPM installation steps were executed regardless,
80+
because 'sap_swpm_force' variable is set to 'true' (default is 'false').
81+
{% endif %}
82+
83+
SAP Product - {{ sap_swpm_product_catalog_id }}
84+
SID - {{ sap_swpm_sid | d('') }}
85+
Primary Instance - {{ sap_swpm_pas_instance_nr | d('') }}
86+
Host - {{ ansible_facts['hostname'] }}
87+
FQDN - {{ ansible_facts['fqdn'] }}
88+
IP - {{ ansible_facts['default_ipv4'].address | d(ansible_facts['all_ipv4_addresses'][0]) }}
89+
90+
5891
# Now that SWPM finished we may need to deal with SUM before continuing when sap_swpm_sum_start: 'true'
5992
# and if we are doing OneHost or CI/PAS installation
6093
# If observer mode is enabled, SWPM will wait for SUM to finish before continuing so we can't do anything here
@@ -65,3 +98,4 @@
6598
- not __sap_swpm_fact_observer_mode
6699
- "'NW_ABAP_CI:' in sap_swpm_product_catalog_id | string or
67100
'NW_ABAP_OneHost:' in sap_swpm_product_catalog_id | string"
101+
- not __sap_swpm_sap_detected | d(false) or sap_swpm_force | d(false)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
---
3+
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+
14+
- name: SAP SWPM Post Install - Get current chage status for user {{ user_item }}
15+
ansible.builtin.command:
16+
cmd: chage -l {{ user_item }}
17+
register: __sap_swpm_register_post_install_change
18+
changed_when: false
19+
become: true
20+
21+
# Reason for noqa: Command 'chage' does not have stdout to check against so we let module decide what is considered change.
22+
- name: SAP SWPM Post Install - Ensure min days is 0 for {{ user_item }} # noqa no-changed-when
23+
ansible.builtin.command:
24+
cmd: chage -m 0 {{ user_item }}
25+
become: true
26+
when: not __sap_swpm_register_post_install_change.stdout
27+
| regex_search('Minimum number of days between password change\\s+:\\s+0')
28+
29+
# Reason for noqa: Command 'chage' does not have stdout to check against so we let module decide what is considered change.
30+
- name: SAP SWPM Post Install - Ensure max days is 99999 for {{ user_item }} # noqa no-changed-when
31+
ansible.builtin.command:
32+
cmd: chage -M 99999 {{ user_item }}
33+
become: true
34+
when: not __sap_swpm_register_post_install_change.stdout
35+
| regex_search('Maximum number of days between password change\\s+:\\s+99999')
36+
37+
# Reason for noqa: Command 'chage' does not have stdout to check against so we let module decide what is considered change.
38+
- name: SAP SWPM Post Install - Ensure password inactive is disabled (-1) for {{ user_item }} # noqa no-changed-when
39+
ansible.builtin.command:
40+
cmd: chage -I -1 {{ user_item }}
41+
become: true
42+
when: not __sap_swpm_register_post_install_change.stdout
43+
| regex_search('Password inactive\\s+:\\s+never')
44+
45+
# Reason for noqa: Command 'chage' does not have stdout to check against so we let module decide what is considered change.
46+
- name: SAP SWPM Post Install - Ensure account expiration is disabled (-1) for {{ user_item }} # noqa no-changed-when
47+
ansible.builtin.command:
48+
cmd: chage -E -1 {{ user_item }}
49+
become: true
50+
when: not __sap_swpm_register_post_install_change.stdout
51+
| regex_search('Account expires\\s+:\\s+never')

0 commit comments

Comments
 (0)