Skip to content

Commit e122126

Browse files
authored
Merge pull request sap-linuxlab#1090 from marcelmamula/hanabackup
sap_ha_install_hana_hsr: Add backup location detection and user variable
2 parents f78dc6c + c9589ea commit e122126

4 files changed

Lines changed: 210 additions & 19 deletions

File tree

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,43 @@
11
# SPDX-License-Identifier: Apache-2.0
22
---
3-
sap_ha_install_hana_hsr_sid: "{{ sap_hana_sid }}"
3+
# SAP HANA Database SID in capital letters (String). Example: 'H02'
4+
sap_ha_install_hana_hsr_sid: "{{ sap_hana_sid | upper }}"
5+
6+
# SAP HANA Database Instance Number (String). Example: '90'
47
sap_ha_install_hana_hsr_instance_number: "{{ sap_hana_instance_number }}"
8+
9+
# Dictionary with cluster nodes. Same dictionary is used by LSR ha_cluster.
10+
# sap_hana_cluster_nodes:
11+
# - node_name: "hana0"
12+
# node_ip: "10.0.0.1"
13+
# node_role: primary
14+
# hana_site: DC01
15+
# - node_name: "hana1"
16+
# node_ip: "10.0.0.2"
17+
# node_role: secondary
18+
# hana_site: DC02
519
sap_ha_install_hana_hsr_cluster_nodes: "{{ sap_hana_cluster_nodes }}"
620

21+
# Name of database user for backups (String).
722
sap_ha_install_hana_hsr_hdbuserstore_system_backup_user: HDB_SYSTEMDB
23+
24+
# Master password for database (String).
825
sap_ha_install_hana_hsr_db_system_password: "{{ sap_hana_install_master_password }}"
26+
27+
# Fully qualified domain name (String).
928
sap_ha_install_hana_hsr_fqdn: "{{ sap_domain }}"
29+
30+
# HSR Replication mode (String).
1031
sap_ha_install_hana_hsr_rep_mode: sync
32+
33+
# HSR Operation mode (String).
1134
sap_ha_install_hana_hsr_oper_mode: logreplay
1235

36+
# Set to true to update /etc/hosts (Boolean).
1337
sap_ha_install_hana_hsr_update_etchosts: true
38+
39+
# Define the directory path where database backup will be created (String).
40+
# Required sub-directories will be created in this path: SYSTEMDB and DB_<SID>.
41+
# Default: /usr/sap/<SID>/HDB<INST_NR>/backup/data/
42+
# Backup will be created with name: <SID>_PRE_HSR_<TIMESTAMP> (e.g. H02_PRE_HSR_20250729_1426)
43+
# sap_ha_install_hana_hsr_backup_path: ''

roles/sap_ha_install_hana_hsr/tasks/log_mode.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
changed_when: false
1313

1414
# CHECK, if ansible_hostname needs to be replaced with interface name
15+
# This task will fail when HSR is already configured, because secondary node nameserver is not running with port 3XX13.
1516
- name: "SAP HSR - Set log_mode to normal"
1617
tags: hsr_logmode
1718
become: true

roles/sap_ha_install_hana_hsr/tasks/main.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@
3232
that:
3333
- sap_ha_install_hana_hsr_cluster_nodes | selectattr('node_role', '==', 'primary') | length == 1
3434
- sap_ha_install_hana_hsr_cluster_nodes | selectattr('node_role', '==', 'secondary') | length >= 1
35-
fail_msg: "Node roles not valid. There must be 1 primary and at least 1 node defined with the secondary role."
35+
fail_msg: "Node roles are not valid. There must be 1 primary and at least 1 node defined with the secondary role."
3636

3737
- name: SAP HSR - Check that hsr interface is configured on host
3838
ansible.builtin.assert:
3939
that:
4040
- __sap_ha_install_hana_hsr_connection.node_ip is defined
4141
- __sap_ha_install_hana_hsr_connection.node_ip != ""
42+
- __sap_ha_install_hana_hsr_connection.node_ip in ansible_all_ipv4_addresses
4243
fail_msg: "The IP address configured for HSR does not exist on this host"
4344
success_msg: "The IP address for HSR is configured on this host"
4445
tags: always
Lines changed: 176 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,190 @@
11
# SPDX-License-Identifier: Apache-2.0
22
---
3+
# Define default path to backups that will be either used or validated against.
4+
# Backups are not stored there directly, but in sub-directories.
5+
# Example: /usr/sap/H02/HDB90/backup/data
6+
- name: "SAP HSR - Set the default backup location path"
7+
ansible.builtin.set_fact:
8+
__sap_ha_install_hana_hsr_basepath_databackup_default:
9+
"{{ '/usr/sap/' ~ sap_ha_install_hana_hsr_sid ~ '/HDB' ~ sap_ha_install_hana_hsr_instance_number ~ '/backup/data' }}"
10+
11+
12+
# Ensure that we create same folder structure inside of user provided path.
13+
- name: "SAP HSR - Create sub-directories in the path provided in variable 'sap_ha_install_hana_hsr_backup_path'"
14+
ansible.builtin.file:
15+
path: "{{ sap_ha_install_hana_hsr_backup_path | regex_replace('/$', '') ~ '/' ~ item }}"
16+
state: directory
17+
mode: "0755"
18+
owner: "{{ sap_ha_install_hana_hsr_sid | lower }}adm"
19+
group: sapsys
20+
loop:
21+
- SYSTEMDB
22+
- "{{ 'DB_' ~ sap_ha_install_hana_hsr_sid }}"
23+
when:
24+
- sap_ha_install_hana_hsr_backup_path is defined
25+
- sap_ha_install_hana_hsr_backup_path | string | length > 0
26+
27+
28+
- name: Block to find basepath_databackup
29+
when:
30+
- sap_ha_install_hana_hsr_backup_path is not defined
31+
or sap_ha_install_hana_hsr_backup_path | string | length == 0
32+
block:
33+
34+
# Getting data from global.ini file is not accurate and we will get it from database.
35+
# The value is stored either in 'SYSTEM' layer or 'DEFAULT' layer. It will default to "NONE" if nothing was found.
36+
- name: "SAP HSR - Get value of the 'basepath_databackup' parameter from database"
37+
become: true
38+
become_user: "{{ sap_ha_install_hana_hsr_sid | lower }}adm"
39+
ansible.builtin.shell:
40+
cmd: |
41+
/usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbsql \
42+
-U {{ sap_ha_install_hana_hsr_hdbuserstore_system_backup_user }} \
43+
-m -a -quiet \
44+
-c ';' \
45+
<<EOF
46+
SELECT COALESCE(
47+
(SELECT VALUE FROM M_INIFILE_CONTENTS WHERE LAYER_NAME = 'SYSTEM' AND SECTION = 'persistence' AND KEY = 'basepath_databackup'),
48+
(SELECT VALUE FROM M_INIFILE_CONTENTS WHERE LAYER_NAME = 'DEFAULT' AND SECTION = 'persistence' AND KEY = 'basepath_databackup'),
49+
'NONE'
50+
) FROM DUMMY;
51+
EOF
52+
register: __sap_ha_install_hana_hsr_register_basepath_databackup
53+
changed_when: false
54+
ignore_errors: true
55+
56+
57+
# Proceed with preparation of command output only when valid.
58+
# Default path '$(DIR_INSTANCE)/backup/data' requires expansion of $DIR_INSTANCE variable.
59+
- name: "SAP HSR - Block to process obtained 'basepath_databackup'"
60+
when:
61+
- not __sap_ha_install_hana_hsr_register_basepath_databackup.failed
62+
- __sap_ha_install_hana_hsr_register_basepath_databackup.stdout_lines | length > 0
63+
- __sap_ha_install_hana_hsr_register_basepath_databackup.stdout_lines[0] != '"NONE"'
64+
vars:
65+
# Remove double quotes around query result.
66+
__basepath_databackup_trimmed:
67+
"{{ __sap_ha_install_hana_hsr_register_basepath_databackup.stdout_lines[0] | replace('\"', '') }}"
68+
# Identify if ENV variable is present by searching for $.
69+
__basepath_databackup_expansion_needed:
70+
"{{ __basepath_databackup_trimmed is search('\\$\\(') }}"
71+
# Finds text inside parentheses and then strips them.
72+
__basepath_databackup_expand_var:
73+
"{{ __basepath_databackup_trimmed | regex_search('\\((.*?)\\)') | regex_replace('\\(|\\)', '') | d('') }}"
74+
75+
block:
76+
# Ansible become is not enough to load ENV so we have to use source.
77+
- name: "SAP HSR - Get value of the expanded variable"
78+
become: true
79+
become_user: "{{ sap_ha_install_hana_hsr_sid | lower }}adm"
80+
ansible.builtin.shell:
81+
cmd: |
82+
source /usr/sap/{{ sap_ha_install_hana_hsr_sid }}/home/.profile && \
83+
echo ${{ __basepath_databackup_expand_var }}
84+
executable: /bin/bash
85+
register: __sap_ha_install_hana_hsr_register_expansion_result
86+
changed_when: false
87+
check_mode: false
88+
ignore_errors: true
89+
when: __basepath_databackup_expansion_needed
90+
91+
# Either expand variable or fall back to value, as it does not contain ENV variable.
92+
- name: "SAP HSR - Create full path of 'basepath_databackup' directory"
93+
ansible.builtin.set_fact:
94+
__sap_ha_install_hana_hsr_basepath_databackup_expanded:
95+
"{{ __basepath_databackup_trimmed | replace('$(' + __basepath_databackup_expand_var + ')', __sap_ha_install_hana_hsr_register_expansion_result.stdout)
96+
if __basepath_databackup_expansion_needed and not __sap_ha_install_hana_hsr_register_expansion_result.failed
97+
else __basepath_databackup_trimmed }}"
98+
99+
# Identify if path is same as default and set fact only if it is different.
100+
- name: "SAP HSR - Set fact 'basepath_databackup' when different from default path"
101+
ansible.builtin.set_fact:
102+
__sap_ha_install_hana_hsr_basepath_databackup: "{{ __sap_ha_install_hana_hsr_basepath_databackup_expanded }}"
103+
when: (__sap_ha_install_hana_hsr_basepath_databackup_expanded | regex_replace('/$', '')) != __sap_ha_install_hana_hsr_basepath_databackup_default
104+
105+
106+
# Combine final path to backup directory in order:
107+
# 1. User defined 'sap_ha_install_hana_hsr_backup_path' if defined and not empty.
108+
# 2. Generated '__sap_ha_install_hana_hsr_basepath_databackup' or empty.
109+
- name: "SAP HSR - Set variable with path to backup directory"
110+
ansible.builtin.set_fact:
111+
__sap_ha_install_hana_hsr_backup_path:
112+
"{{ sap_ha_install_hana_hsr_backup_path
113+
if sap_ha_install_hana_hsr_backup_path is defined and sap_ha_install_hana_hsr_backup_path | string | length > 0
114+
else __sap_ha_install_hana_hsr_basepath_databackup | d('') }}"
115+
116+
- name: "SAP HSR - Set variable with backup file prefix"
117+
ansible.builtin.set_fact:
118+
# Prepare backup name as <SID>_PRE_HSR_<TIMESTAMP>. Example: H02_PRE_HSR_20250729_1444
119+
__sap_ha_install_hana_hsr_backup_prefix:
120+
"{{ (sap_ha_install_hana_hsr_sid | upper) ~ '_PRE_HSR_' ~ now(utc=False).strftime('%Y%m%d_%H%M') }}"
121+
122+
123+
# 'USING FILE' parameter accepts range of inputs:
124+
# - ('name') - Backup 'name' will be created in default basepath_databackup.
125+
# - ('','name') - Backup 'name' will be created in default basepath_databackup.
126+
# - ('/backup/name') - Backup 'name' will be created in /backup/ folder, but it has to exist with correct permissions.
127+
# - ('/backup/','name') - Backup 'name' will be created in /backup/ folder, but it has to exist with correct permissions.
128+
# Using full path requires us to specify sub-directories to avoid mixing up SYSTEMDB and TENANTDB backups.
3129
- name: "SAP HSR - Run backup for SYSTEMDB"
4-
ansible.builtin.shell: |
5-
/usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbsql -quiet \
6-
-U {{ sap_ha_install_hana_hsr_hdbuserstore_system_backup_user }} \
7-
-m <<EOF
8-
BACKUP DATA FOR SYSTEMDB USING FILE ('data_bck');
9-
EOF
130+
ansible.builtin.shell:
131+
cmd: |
132+
/usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbsql -quiet \
133+
-U {{ sap_ha_install_hana_hsr_hdbuserstore_system_backup_user }} \
134+
-m <<EOF
135+
BACKUP DATA FOR SYSTEMDB USING FILE ('{{ __systemdb_path }}','{{ __sap_ha_install_hana_hsr_backup_prefix }}');
136+
EOF
10137
changed_when: true
138+
vars:
139+
# Ensure that backup goes into sub-directory, when path is not default.
140+
__systemdb_path:
141+
"{{ __sap_ha_install_hana_hsr_backup_path | regex_replace('/$', '') ~ '/SYSTEMDB/'
142+
if __sap_ha_install_hana_hsr_backup_path != ''
143+
else '' }}"
11144

12145
- name: "SAP HSR - Run backup in TENANTDB {{ sap_ha_install_hana_hsr_sid }}"
13-
ansible.builtin.shell: |
14-
/usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbsql -quiet \
15-
-U {{ sap_ha_install_hana_hsr_hdbuserstore_system_backup_user }} \
16-
-m <<EOF
17-
BACKUP DATA FOR {{ sap_ha_install_hana_hsr_sid }} USING FILE ('data_bck');
18-
EOF
146+
ansible.builtin.shell:
147+
cmd: |
148+
/usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbsql -quiet \
149+
-U {{ sap_ha_install_hana_hsr_hdbuserstore_system_backup_user }} \
150+
-m <<EOF
151+
BACKUP DATA FOR {{ sap_ha_install_hana_hsr_sid }} USING FILE ('{{ __tenantdb_path }}','{{ __sap_ha_install_hana_hsr_backup_prefix }}');
152+
EOF
19153
changed_when: true
154+
vars:
155+
# Ensure that backup goes into sub-directory, when path is not default.
156+
__tenantdb_path:
157+
"{{ __sap_ha_install_hana_hsr_backup_path | regex_replace('/$', '') ~ '/DB_' ~ sap_ha_install_hana_hsr_sid ~ '/'
158+
if __sap_ha_install_hana_hsr_backup_path != ''
159+
else '' }}"
160+
161+
162+
# This is final configuration of backup path, because find command cannot proceed with
163+
# empty string '' like hdbsql.
164+
- name: "SAP HSR - Set variable with final path to backup directory"
165+
ansible.builtin.set_fact:
166+
__sap_ha_install_hana_hsr_backup_path_final:
167+
"{{ __sap_ha_install_hana_hsr_backup_path
168+
if __sap_ha_install_hana_hsr_backup_path != ''
169+
else __sap_ha_install_hana_hsr_basepath_databackup_default }}"
20170

21171
- name: "SAP HSR - Verify backup files"
22-
ansible.builtin.shell: |
23-
source /usr/sap/{{ sap_ha_install_hana_hsr_sid }}/home/.sapenv.sh && \
24-
find /usr/sap/{{ sap_ha_install_hana_hsr_sid }}/HDB{{ sap_ha_install_hana_hsr_instance_number }}/backup/data/ \
25-
-type f -name data_bck* \
26-
-exec /usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbbackupcheck {} \;
172+
ansible.builtin.shell:
173+
cmd: |
174+
source /usr/sap/{{ sap_ha_install_hana_hsr_sid }}/home/.profile && \
175+
find {{ __sap_ha_install_hana_hsr_backup_path_final }} \
176+
-type f -name {{ __sap_ha_install_hana_hsr_backup_prefix }}* \
177+
-exec /usr/sap/{{ sap_ha_install_hana_hsr_sid }}/SYS/exe/hdb/hdbbackupcheck {} \;
27178
register: __sap_ha_install_hana_hsr_verify_backup
28179
failed_when:
29180
- __sap_ha_install_hana_hsr_verify_backup.rc == '1' or
30181
__sap_ha_install_hana_hsr_verify_backup.stderr != ""
31182
changed_when: false
183+
184+
185+
- name: "SAP HSR - Show backup details"
186+
ansible.builtin.debug:
187+
msg: |
188+
Database backup was successfully completed.
189+
Location: {{ __sap_ha_install_hana_hsr_backup_path_final}}
190+
File prefix: {{ __sap_ha_install_hana_hsr_backup_prefix }}

0 commit comments

Comments
 (0)