-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Replaced shell with ansible tasks
Dynamic execution based on groups Calculation of missing inputs Idempotency checks before execution
- Loading branch information
1 parent
eef145f
commit 278602f
Showing
7 changed files
with
413 additions
and
339 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
## Input Parameters for sap_vm_temp_vip Ansible Role | ||
<!-- BEGIN Role Input Parameters --> | ||
### sap_vm_temp_vip_primary_ip | ||
|
||
- _Type:_ `string` | ||
- _Default:_ `ansible_default_ipv4.address` | ||
|
||
Primary IP on default network interface is obtained from Ansible Facts and it is used for calculation of missing input parameters. | ||
|
||
### sap_vm_temp_vip_primary_netmask | ||
|
||
- _Type:_ `string` | ||
- _Default:_ `ansible_default_ipv4.netmask` | ||
|
||
Netmask of primary IP on default network interface is obtained from Ansible Facts and it is used for calculation of missing input parameters. | ||
|
||
### sap_vm_temp_vip_primary_prefix | ||
|
||
- _Type:_ `string` | ||
- _Default:_ `ansible_default_ipv4.prefix` | ||
|
||
Prefix of primary IP on default network interface is obtained from Ansible Facts and it is used for calculation of missing input parameters. | ||
|
||
### sap_vm_temp_vip_primary_broadcast | ||
|
||
- _Type:_ `string` | ||
- _Default:_ `ansible_default_ipv4.broadcast` | ||
|
||
Broadcast of primary IP on default network interface is obtained from Ansible Facts and it is used for calculation of missing input parameters.</br> | ||
This parameter is empty on some cloud platforms and VIP is created without broadcast if attempt to calculate fails. | ||
|
||
### sap_vm_temp_vip_hana_primary | ||
- _Type:_ `string` | ||
- _Default:_ `sap_ha_pacemaker_cluster_vip_hana_primary_ip_address` | ||
|
||
Mandatory for SAP HANA cluster setup.</br> | ||
VIP address is by default assigned from `sap_ha_pacemaker_cluster_vip_hana_primary_ip_address` input parameter used by [sap_ha_pacemaker_cluster](https://github.com/sap-linuxlab/community.sap_install/tree/main/roles/sap_ha_pacemaker_cluster) role. | ||
|
||
### sap_vm_temp_vip_nwas_abap_ascs | ||
- _Type:_ `string` | ||
- _Default:_ `sap_ha_pacemaker_cluster_vip_nwas_abap_ascs_ip_address` | ||
|
||
Mandatory for SAP ASCS/ERS cluster setup.</br> | ||
VIP address is by default assigned from `sap_ha_pacemaker_cluster_vip_nwas_abap_ascs_ip_address` input parameter used by [sap_ha_pacemaker_cluster](https://github.com/sap-linuxlab/community.sap_install/tree/main/roles/sap_ha_pacemaker_cluster) role. | ||
|
||
### sap_vm_temp_vip_nwas_abap_ers | ||
- _Type:_ `string` | ||
- _Default:_ `sap_ha_pacemaker_cluster_vip_nwas_abap_ers_ip_address` | ||
|
||
Mandatory for SAP ASCS/ERS cluster setup.</br> | ||
VIP address is by default assigned from `sap_ha_pacemaker_cluster_vip_hana_primary_ip_address` input parameter used by [sap_ha_pacemaker_cluster](https://github.com/sap-linuxlab/community.sap_install/tree/main/roles/sap_ha_pacemaker_cluster) role. | ||
|
||
### sap_vm_temp_vip_anydb_primary | ||
- _Type:_ `string` | ||
|
||
Mandatory for SAP AnyDB cluster setup. | ||
|
||
<!-- END Role Input Parameters --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,78 @@ | ||
`Beta` | ||
|
||
<!-- BEGIN Title --> | ||
# sap_vm_temp_vip Ansible Role | ||
<!-- END Title --> | ||
|
||
Ansible Role for assignment of Temporary Virtual IP (VIP) to OS Network Interface prior to Linux Pacemaker ownership. | ||
|
||
This Ansible Role will (dependent on detected Infrastructure Platform) perform assignment of a Virtual IP Address to the OS Network Interface. | ||
|
||
|
||
## Functionality | ||
|
||
The hosts for SAP Software allocated for High Availability are configured with a temporary Virtual IP for the OS Network Interface; thereby allowing Linux Pacemaker to be installed once the SAP Software installation has concluded (best practice for Linux Pacemaker). When an Infrastructure Platform with specific requirements is detected (e.g. Load Balancers), then bespoke actions are performed. | ||
|
||
|
||
## Scope | ||
## Description | ||
<!-- BEGIN Description --> | ||
Ansible role `sap_vm_temp_vip` is used to enable installation of SAP Application and Database on High Availability clusters provisioned by [sap_vm_provision](https://github.com/sap-linuxlab/community.sap_infrastructure/tree/main/roles/sap_vm_provision) role. | ||
|
||
Only hosts required for High Availability (such as SAP HANA Primary node, SAP NetWeaver ASCS/ERS) should use this Ansible Role. | ||
Installation of cluster environment requires temporary assignment of Virtual IP (VIP) before executing installation roles [sap_hana_install](https://github.com/sap-linuxlab/community.sap_install/tree/main/roles/sap_hana_install) and [sap_swpm](https://github.com/sap-linuxlab/community.sap_install/tree/main/roles/sap_swpm). | ||
- This is temporary and it will be replaced by Cluster VIP resource once cluster is configured by [sap_ha_pacemaker_cluster](https://github.com/sap-linuxlab/community.sap_install/tree/main/roles/sap_ha_pacemaker_cluster) role. | ||
|
||
Assumptions are made based upon the default High Availability configuration for a given Infrastructure Platform (e.g. using Linux Pacemaker `IPAddr2` resource agent). | ||
This role does not update `/etc/hosts` or DNS, because that is completed by [sap_vm_provision](https://github.com/sap-linuxlab/community.sap_infrastructure/tree/main/roles/sap_vm_provision) role. | ||
<!-- END Description --> | ||
|
||
## Prerequisites | ||
<!-- BEGIN Prerequisites --> | ||
Environment: | ||
1. Execute role with `gather_facts: true`, as it uses `ansible_default_ipv4` facts. | ||
2. Assign hosts to correct groups, which are also used in other roles in our project | ||
- Supported cluster groups: `hana_primary, hana_secondary, anydb_primary, anydb_secondary, nwas_ascs, nwas_ers` | ||
|
||
## Requirements | ||
|
||
### Target hosts | ||
|
||
**OS Versions:** | ||
- Red Hat Enterprise Linux 8.2+ | ||
- SUSE Linux Enterprise Server 15 SP3+ | ||
|
||
### Execution/Controller host | ||
|
||
**Dependencies:** | ||
- OS Packages | ||
- Python 3.9.7+ (i.e. CPython distribution) | ||
- Python Packages | ||
- None | ||
- Ansible | ||
- Ansible Core 2.12.0+ | ||
- Ansible Collections: | ||
- None | ||
|
||
Dependant on roles: | ||
1. [sap_vm_provision](https://github.com/sap-linuxlab/community.sap_infrastructure/tree/main/roles/sap_vm_provision) to create dependant resources: DNS, Load Balancers and Health Checks. | ||
<!-- END Prerequisites --> | ||
|
||
## Execution | ||
|
||
### Sample execution | ||
|
||
For further information, see the [sample Ansible Playbooks in `/playbooks`](../playbooks/). | ||
|
||
### Suggested execution sequence | ||
|
||
It is advised this Ansible Role is used only for High Availability and executed prior to execution of: | ||
- sap_hana_install | ||
- sap_swpm | ||
|
||
Prior to execution of this Ansible Role, there are no Ansible Roles suggested to be executed first. | ||
|
||
### Summary of execution flow | ||
|
||
- Identify IPv4 Address with CIDR and Broadcast Address | ||
- If SAP AnyDB or SAP NetWeaver, assign Virtual IP to OS Network Interface. If SAP HANA, skip | ||
- Start temporary listener for SAP HANA, SAP AnyDB or SAP NetWeaver when using Load Balancers _(GCP, IBM Cloud, MS Azure)_ | ||
|
||
### Tags to control execution | ||
|
||
There are no tags used to control the execution of this Ansible Role | ||
|
||
<!-- BEGIN Execution --> | ||
Role can be execute separately or as part of [ansible.playbooks_for_sap](https://github.com/sap-linuxlab/ansible.playbooks_for_sap) playbooks. | ||
<!-- END Execution --> | ||
|
||
### Execution Flow | ||
<!-- BEGIN Execution Flow --> | ||
1. Assert that required inputs were provided. | ||
2. Collect missing inputs using provided inputs (example: Calculate prefix from netmask, if VIP prefix was not defined) | ||
3. Append VIP to network interface | ||
- SAP HANA Primary host if both groups are present: `hana_primary, hana_secondary` | ||
- SAP AnyDB Primary host if both groups are present: `anydb_primary, anydb_secondary` | ||
- SAP ASCS host if both groups are present: `nwas_ascs, nwas_ers` | ||
- SAP ERS host if both groups are present:` nwas_ascs, nwas_ers` | ||
4. Install `netcat` and start 12 hour process to ensure that Load Balancer Health Checks are working before Cluster is configured. | ||
- Limited to platforms with Network Load Balancers and `IPAddr2` resource agent: Google Cloud, MS Azure, IBM Cloud. | ||
<!-- END Execution Flow --> | ||
|
||
### Example | ||
<!-- BEGIN Execution Example --> | ||
```yaml | ||
- name: Ansible Play for Temporary VIP setup on SAP ASCS/ERS hosts | ||
hosts: nwas_ascs, nwas_ers | ||
become: true | ||
any_errors_fatal: true | ||
max_fail_percentage: 0 | ||
tasks: | ||
|
||
- name: Execute Ansible Role sap_vm_temp_vip | ||
ansible.builtin.include_role: | ||
name: community.sap_infrastructure.sap_vm_temp_vip | ||
``` | ||
<!-- END Execution Example --> | ||
<!-- BEGIN Role Tags --> | ||
<!-- END Role Tags --> | ||
<!-- BEGIN Further Information → | ||
<!-- END Further Information --> | ||
## License | ||
|
||
<!-- BEGIN License --> | ||
Apache 2.0 | ||
<!-- END License --> | ||
## Maintainers | ||
<!-- BEGIN Maintainers --> | ||
- [Sean Freeman](https://github.com/sean-freeman) | ||
- [Marcel Mamula](https://github.com/marcelmamula) | ||
<!-- END Maintainers --> | ||
## Authors | ||
|
||
Sean Freeman | ||
|
||
--- | ||
|
||
## Ansible Role Input Variables | ||
|
||
Please first check the [/defaults parameters file](./defaults/main.yml). | ||
## Role Input Parameters | ||
All input parameters used by role are described in [INPUT_PARAMETERS.md](https://github.com/sap-linuxlab/community.sap_infrastructure/blob/main/roles/sap_vm_temp_vip/INPUT_PARAMETERS.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
--- | ||
# Get details of default ip route to detect default network interface | ||
- name: Get network interface from ip route show default 0.0.0.0/0 | ||
ansible.builtin.shell: | ||
cmd: set -o pipefail && ip route show default 0.0.0.0/0 | awk '/default/ {print $5}' | ||
register: __sap_vm_temp_vip_get_route | ||
changed_when: false | ||
failed_when: false | ||
|
||
# Get content of ip address show filtered by primary IP | ||
- name: Get contents of ip address show for {{ sap_vm_temp_vip_primary_ip }} | ||
ansible.builtin.shell: | ||
cmd: set -o pipefail && ip -oneline address show {{ __sap_vm_temp_vip_get_route.stdout }} | grep {{ sap_vm_temp_vip_primary_ip }} | ||
when: | ||
- __sap_vm_temp_vip_get_route.stdout is defined and __sap_vm_temp_vip_get_route.stdout | length > 0 | ||
register: __sap_vm_temp_vip_get_ips | ||
changed_when: false | ||
failed_when: false | ||
|
||
# Extract prefix from netmask if it is available | ||
# Use localhost (execution host) Python3 instead of relying on target host | ||
- name: Calculate prefix from netmask {{ sap_vm_temp_vip_primary_netmask }} | ||
delegate_to: localhost | ||
ansible.builtin.command: | ||
cmd: > | ||
python3 -c "import ipaddress; print(ipaddress.IPv4Network('{{ sap_vm_temp_vip_primary_ip }}/{{ sap_vm_temp_vip_primary_netmask }}', strict=False).prefixlen)" | ||
when: | ||
- sap_vm_temp_vip_primary_prefix == '' | ||
- sap_vm_temp_vip_primary_netmask | length > 0 | ||
register: __sap_vm_temp_vip_get_prefix_netmask | ||
changed_when: false | ||
failed_when: false | ||
|
||
# Extract prefix from primary IP on default interface if netmask is not available | ||
# Stdout result is array instead of string. [0] is used to select only one in case of multiple results. | ||
# [0] could be replaced by join('') but it would require duplicate record validation. | ||
- name: Calculate prefix from IP {{ sap_vm_temp_vip_primary_ip }} if sap_vm_temp_vip_primary_netmask is empty | ||
ansible.builtin.set_fact: | ||
__sap_vm_temp_vip_get_prefix_ip: | ||
"{{ (__sap_vm_temp_vip_inet[0] | basename) if __sap_vm_temp_vip_inet | length > 0 else __sap_vm_temp_vip_inet }}" | ||
vars: | ||
__sap_vm_temp_vip_inet: "{{ __sap_vm_temp_vip_get_ips.stdout | regex_search('inet ([0-9.]+/[0-9]+)', '\\1') }}" | ||
when: | ||
- sap_vm_temp_vip_primary_prefix == '' | ||
- sap_vm_temp_vip_primary_netmask == '' | ||
- __sap_vm_temp_vip_get_ips is defined and __sap_vm_temp_vip_get_ips.stdout is defined and __sap_vm_temp_vip_get_ips.stdout | length > 0 | ||
changed_when: false | ||
|
||
|
||
# Combine final prefix variable based on decision below: | ||
# 1. Use /32 for AWS and GCP if sap_vm_temp_vip_primary_prefix is empty | ||
# 2. Else use prefix calculated from netmask if it is available and sap_vm_temp_vip_primary_prefix is empty | ||
# 3. Else use prefix calculated from primary IP if netmask is not available and sap_vm_temp_vip_primary_prefix is empty | ||
# 4. Else use sap_vm_temp_vip_primary_prefix (regardless of content) to be used to skip steps. | ||
- name: Update netmask prefix variable if it was calculated | ||
ansible.builtin.set_fact: | ||
__sap_vm_temp_vip_primary_prefix: >- | ||
{%- if sap_vm_temp_vip_primary_prefix | length == 0 and __sap_vm_temp_vip_force_static_32 -%} | ||
32 | ||
{%- elif sap_vm_temp_vip_primary_prefix | length == 0 | ||
and __sap_vm_temp_vip_get_prefix_netmask.stdout is defined and __sap_vm_temp_vip_get_prefix_netmask.stdout | length > 0 -%} | ||
{{ __sap_vm_temp_vip_get_prefix_netmask.stdout }} | ||
{%- elif sap_vm_temp_vip_primary_prefix | length == 0 | ||
and __sap_vm_temp_vip_get_prefix_ip is defined and __sap_vm_temp_vip_get_prefix_ip | length > 0 -%} | ||
{{ __sap_vm_temp_vip_get_prefix_ip }} | ||
{%- else -%} | ||
{{ sap_vm_temp_vip_primary_prefix }} | ||
{%- endif -%} | ||
vars: | ||
__sap_vm_temp_vip_force_static_32: | ||
"{{ true if (('amazon' in (ansible_system_vendor | lower) or 'amazon' in (ansible_product_name | lower)) | ||
or (ansible_product_name == 'Google Compute Engine')) else false }}" | ||
|
||
|
||
# Extract broadcast IP from primary IP if it is present and ansible fact ansible_default_ipv4.broadcast is empty | ||
# Stdout result is array instead of string. [0] is used to select only one in case of multiple results. | ||
# [0] could be replaced by join('') but it would require duplicate record validation. | ||
- name: Calculate broadcast IP from IP {{ sap_vm_temp_vip_primary_ip }} if sap_vm_temp_vip_primary_broadcast is empty | ||
ansible.builtin.set_fact: | ||
__sap_vm_temp_vip_get_broadcast_ip: | ||
"{{ (__sap_vm_temp_vip_brd[0] | basename) if __sap_vm_temp_vip_brd | length > 0 else __sap_vm_temp_vip_brd }}" | ||
vars: | ||
__sap_vm_temp_vip_brd: "{{ __sap_vm_temp_vip_get_ips.stdout | regex_search('brd ([0-9.]+)', '\\1') }}" | ||
when: | ||
- sap_vm_temp_vip_primary_broadcast == '' | ||
- __sap_vm_temp_vip_get_ips is defined and __sap_vm_temp_vip_get_ips.stdout is defined and __sap_vm_temp_vip_get_ips.stdout | length > 0 | ||
changed_when: false | ||
|
||
# Combine final broadcast IP based on decision below: | ||
# 1. Use calculated broadcast from primary IP if sap_vm_temp_vip_primary_broadcast is empty | ||
# 2. Else use sap_vm_temp_vip_primary_broadcast (regardless of content) to be used during VIP creation | ||
- name: Update broadcast IP variable if it was calculated | ||
ansible.builtin.set_fact: | ||
__sap_vm_temp_vip_primary_broadcast: >- | ||
{%- if sap_vm_temp_vip_primary_broadcast | length == 0 | ||
and __sap_vm_temp_vip_get_broadcast_ip is defined and __sap_vm_temp_vip_get_broadcast_ip | length > 0 -%} | ||
{{ __sap_vm_temp_vip_get_broadcast_ip }} | ||
{%- else -%} | ||
{{ sap_vm_temp_vip_primary_broadcast }} | ||
{%- endif -%} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,36 @@ | ||
--- | ||
# Ansible role to setup temporary Virtual IP (VIP) | ||
|
||
- name: Setup temporary Virtual IP (VIP) | ||
- name: Assert that sap_vm_temp_vip_primary_ip is defined | ||
ansible.builtin.assert: | ||
that: sap_vm_temp_vip_primary_ip is defined and sap_vm_temp_vip_primary_ip | length > 0 | ||
fail_msg: | ||
- "Unable to get ansible fact ansible_default_ipv4.address or variable sap_vm_temp_vip_primary_ip is empty!" | ||
- "Ensure that gather_facts:true is set and sap_vm_temp_vip_primary_ip is not empty." | ||
|
||
|
||
- name: Block to ensure that only supported groups are allowed | ||
when: group_names | intersect(['hana_primary', 'hana_secondary', 'anydb_primary', 'anydb_secondary', 'nwas_ascs', 'nwas_ers']) | ||
block: | ||
|
||
# - name: Identify OS Primary Network Interface | ||
# ansible.builtin.include_tasks: "identify_network_interface.yml" | ||
|
||
- name: Attempt to obtain missing network information | ||
ansible.builtin.include_tasks: "get_temp_vip_details.yml" | ||
when: | ||
- not ansible_chassis_asset_tag == 'ibmcloud' # Moved here instead of each task inside of "set_temp_vip.yml" | ||
|
||
|
||
- name: Execute temporary set of a Virtual IP (VIP) prior to Linux Pacemaker ownership | ||
ansible.builtin.include_tasks: "set_temp_vip.yml" | ||
when: | ||
- not ansible_chassis_asset_tag == 'ibmcloud' # Moved here instead of each task inside of "set_temp_vip.yml" | ||
|
||
|
||
# Required when using Load Balancers (i.e. Google Cloud, IBM Cloud, MS Azure) | ||
- name: Set Health Check Probe Listener for Virtual IP when Load Balancer | ||
ansible.builtin.include_tasks: "set_temp_vip_lb_listener.yml" | ||
when: (ansible_product_name == 'Google Compute Engine') or (ansible_chassis_asset_tag == 'ibmcloud') or (ansible_chassis_vendor == 'Microsoft Corporation' and ansible_product_name == 'Virtual Machine') | ||
when: | ||
- (ansible_product_name == 'Google Compute Engine') or (ansible_chassis_asset_tag == 'ibmcloud') | ||
or (ansible_chassis_vendor == 'Microsoft Corporation' and ansible_product_name == 'Virtual Machine') |
Oops, something went wrong.