diff --git a/.ansible-lint b/.ansible-lint
new file mode 100644
index 0000000..ff93a8f
--- /dev/null
+++ b/.ansible-lint
@@ -0,0 +1,24 @@
+---
+# Collection wide lint-file
+# DO NOT CHANGE
+exclude_paths:
+ - .ansible/
+ - .cache/
+ - .github/
+ # - docs/
+ - changelogs/
+ - playbooks/
+ - tests/
+enable_list:
+ - yaml
+skip_list:
+ # We don't want to enforce new Ansible versions for Galaxy:
+ - meta-runtime[unsupported-version]
+ # We do not want to use checks which are marked as experimental:
+ - experimental
+ # We use ignore_errors for all the assert tasks, which should be acceptable:
+ - ignore-errors
+ # We want to allow single digit version numbers in a role's meta/main.yml file:
+ - schema
+ # Allow templating inside name because it creates more detailed output:
+ - name[template]
diff --git a/.gitignore b/.gitignore
index 4938417..9ff6291 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,4 @@ __pycache__/
# VSCode
.vscode
+.ansible
diff --git a/plugins/module_utils/sap_api_common.py b/plugins/module_utils/sap_api_common.py
index 204b492..164b173 100644
--- a/plugins/module_utils/sap_api_common.py
+++ b/plugins/module_utils/sap_api_common.py
@@ -37,9 +37,23 @@ def _request(url, **kwargs):
method = 'POST' if kwargs.get('data') or kwargs.get('json') else 'GET'
res = https_session.request(method, url, **kwargs)
- if (res.status_code == 403
- and res.json()['errorMessage'].startswith('Account Temporarily Locked Out')):
- raise Exception('SAP ID Service has reported `Account Temporarily Locked Out`. Please reset password to regain access and try again.')
+ # Validating against `res.text` can cause long execution time, because fuzzy search result can contain large `res.text`.
+ # This can be prevented by validating `res.status_code` check before `res.text`.
+ # Example: 'Two-Factor Authentication' is only in `res.text`, which can lead to long execution.
+
+ if res.status_code == 403:
+ if 'You are not authorized to download this file' in res.text:
+ raise Exception(f'You are not authorized to download this file.')
+ elif 'Account Temporarily Locked Out' in res.text:
+ raise Exception(f'Account Temporarily Locked Out. Please reset password to regain access and try again.')
+ else:
+ res.raise_for_status()
+
+ if res.status_code == 404:
+ if 'The file you have requested cannot be found' in res.text:
+ raise Exception(f'The file you have requested cannot be found.')
+ else:
+ res.raise_for_status()
res.raise_for_status()
diff --git a/plugins/modules/maintenance_planner_stack_xml_download.py b/plugins/modules/maintenance_planner_stack_xml_download.py
index 3f444db..6e958eb 100644
--- a/plugins/modules/maintenance_planner_stack_xml_download.py
+++ b/plugins/modules/maintenance_planner_stack_xml_download.py
@@ -30,7 +30,7 @@
- Transaction Name or Transaction Display ID from Maintenance Planner.
required: true
type: str
- download_path:
+ dest:
description:
- Destination folder path.
required: true
@@ -46,7 +46,7 @@
suser_id: 'SXXXXXXXX'
suser_password: 'password'
transaction_name: 'MP_NEW_INST_20211015_044854'
- download_path: "/tmp/"
+ dest: "/tmp/"
register: sap_mp_register
- name: Display the list of download links and filenames
debug:
@@ -79,7 +79,7 @@ def run_module():
suser_id=dict(type='str', required=True),
suser_password=dict(type='str', required=True, no_log=True),
transaction_name=dict(type='str', required=True),
- download_path=dict(type='str', required=True)
+ dest=dict(type='str', required=True)
)
# Define result dictionary objects to be passed back to Ansible
@@ -102,7 +102,7 @@ def run_module():
username = module.params.get('suser_id')
password = module.params.get('suser_password')
transaction_name = module.params.get('transaction_name')
- download_path = module.params.get('download_path')
+ dest = module.params.get('dest')
# Main run
@@ -118,7 +118,7 @@ def run_module():
transaction_id = get_transaction_id(transaction_name)
# EXEC: Download the MP Stack XML file
- get_transaction_stack_xml(transaction_id, download_path)
+ get_transaction_stack_xml(transaction_id, dest)
# Process return dictionary for Ansible
result['changed'] = True
diff --git a/plugins/modules/software_center_download.py b/plugins/modules/software_center_download.py
index 4e1fc79..5b909e8 100644
--- a/plugins/modules/software_center_download.py
+++ b/plugins/modules/software_center_download.py
@@ -48,7 +48,7 @@
- Download filename of the SAP software.
required: false
type: str
- download_path:
+ dest:
description:
- Destination folder path.
required: true
@@ -80,14 +80,14 @@
suser_password: 'password'
search_query:
- 'SAPCAR_1324-80000936.EXE'
- download_path: "/tmp/"
+ dest: "/tmp/"
- name: Download using direct link and filename
community.sap_launchpad.software_center_download:
suser_id: 'SXXXXXXXX'
suser_password: 'password'
download_link: 'https://softwaredownloads.sap.com/file/0010000000048502015'
download_filename: 'IW_FNDGC100.SAR'
- download_path: "/tmp/"
+ dest: "/tmp/"
'''
RETURN = r'''
@@ -116,21 +116,21 @@
from ..module_utils.sap_launchpad_software_center_download_runner import *
from ..module_utils.sap_id_sso import sap_sso_login
-def _check_similar_files(download_path, filename):
+def _check_similar_files(dest, filename):
"""
Checks for similar files in the download path based on the given filename.
Args:
- download_path (str): The path where files are downloaded.
+ dest (str): The path where files are downloaded.
filename (str): The filename to check for similar files.
Returns:
bool: True if similar files exist, False otherwise.
filename_similar_names: A list of similar filenames if they exist, empty list otherwise.
"""
- # pattern = download_path + '/**/' + os.path.splitext(filename)[0]
+ # pattern = dest + '/**/' + os.path.splitext(filename)[0]
filename_base = os.path.splitext(filename)[0]
- filename_pattern = os.path.join(download_path, "**", filename_base)
+ filename_pattern = os.path.join(dest, "**", filename_base)
filename_similar = glob.glob(filename_pattern, recursive=True)
if filename_similar:
@@ -150,7 +150,7 @@ def run_module():
search_query=dict(type='str', required=False, default=''),
download_link=dict(type='str', required=False, default=''),
download_filename=dict(type='str', required=False, default=''),
- download_path=dict(type='str', required=True),
+ dest=dict(type='str', required=True),
dry_run=dict(type='bool', required=False, default=False),
deduplicate=dict(type='str', required=False, default=''),
search_alternatives=dict(type='bool', required=False, default=False)
@@ -174,7 +174,7 @@ def run_module():
else:
query = None
- download_path = module.params['download_path']
+ dest = module.params['dest']
download_link= module.params.get('download_link')
download_filename= module.params.get('download_filename')
dry_run = module.params.get('dry_run')
@@ -207,7 +207,7 @@ def run_module():
# Search for existing files using exact filename
filename = query if query else download_filename
- filename_exact = os.path.join(download_path, filename)
+ filename_exact = os.path.join(dest, filename)
result['filename'] = filename
if os.path.exists(filename_exact):
@@ -216,7 +216,7 @@ def run_module():
module.exit_json(**result)
else:
# Exact file not found, search for similar files with pattern
- filename_similar_exists, filename_similar_names = _check_similar_files(download_path, filename)
+ filename_similar_exists, filename_similar_names = _check_similar_files(dest, filename)
if filename_similar_exists and not (query and search_alternatives):
result['skipped'] = True
result['msg'] = f"Similar file(s) already exist: {', '.join(filename_similar_names)}"
@@ -235,14 +235,14 @@ def run_module():
result['filename'] = download_filename
result['alternative'] = True
- filename_alternative_exact = os.path.join(download_path, download_filename)
+ filename_alternative_exact = os.path.join(dest, download_filename)
if os.path.exists(filename_alternative_exact):
result['skipped'] = True
result['msg'] = f"Alternative file already exists: {download_filename} - original file {query} is not available to download"
module.exit_json(**result)
else:
# Exact file not found, search for similar files with pattern
- filename_similar_exists, filename_similar_names = _check_similar_files(download_path, download_filename)
+ filename_similar_exists, filename_similar_names = _check_similar_files(dest, download_filename)
if filename_similar_exists:
result['skipped'] = True
result['msg'] = f"Similar alternative file(s) already exist: {', '.join(filename_similar_names)}"
@@ -252,13 +252,13 @@ def run_module():
elif filename != download_filename and not alternative_found:
result['filename'] = download_filename
- if os.path.exists(os.path.join(download_path, download_filename)):
+ if os.path.exists(os.path.join(dest, download_filename)):
result['skipped'] = True
result['msg'] = f"File already exists with correct name: {download_filename}"
module.exit_json(**result)
else:
# Exact file not found, search for similar files with pattern
- filename_similar_exists, filename_similar_names = _check_similar_files(download_path, download_filename)
+ filename_similar_exists, filename_similar_names = _check_similar_files(dest, download_filename)
if filename_similar_exists:
result['skipped'] = True
result['msg'] = f"Similar file(s) already exist for correct name {download_filename}: {', '.join(filename_similar_names)}"
@@ -281,7 +281,7 @@ def run_module():
else:
module.fail_json(msg="Download link {} is not available".format(download_link))
- download_software(download_link, download_filename, download_path)
+ download_software(download_link, download_filename, dest)
# Update final results json
result['changed'] = True
diff --git a/roles/.gitkeep b/roles/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/roles/sap_software_download/.yamllint.yml b/roles/sap_software_download/.yamllint.yml
new file mode 100644
index 0000000..ee4457c
--- /dev/null
+++ b/roles/sap_software_download/.yamllint.yml
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+# Based on ansible-lint config
+extends: default
+
+rules:
+ braces: {max-spaces-inside: 1, level: error}
+ brackets: {max-spaces-inside: 1, level: error}
+# colons: {max-spaces-after: -1, level: error}
+# commas: {max-spaces-after: -1, level: error}
+ comments:
+ require-starting-space: false
+ min-spaces-from-content: 1
+ comments-indentation: disable
+# document-start: disable
+# empty-lines: {max: 3, level: error}
+# hyphens: {level: error}
+# indentation: disable
+# key-duplicates: enable
+ line-length: disable
+# new-line-at-end-of-file: disable
+# new-lines: {type: unix}
+# trailing-spaces: disable
+ truthy: disable
+ octal-values:
+ forbid-implicit-octal: true
+ forbid-explicit-octal: true
diff --git a/roles/sap_software_download/README.md b/roles/sap_software_download/README.md
new file mode 100644
index 0000000..93fdd7b
--- /dev/null
+++ b/roles/sap_software_download/README.md
@@ -0,0 +1,321 @@
+
+# sap_software_download Ansible Role
+
+
+## Description
+
+The Ansible Role `sap_software_download` is used to download SAP Software Media from SAP.
+
+
+
+## Dependencies
+This role requires the following Python modules to be installed on the target node (the machine where SAP software will be downloaded):
+
+- wheel
+- urllib3
+- requests
+- beautifulsoup4
+- lxml
+
+The role installs these modules if they are not already present. Installation can be done in one of the following ways:
+
+- **Virtual Environment (Default):**
+ - When `sap_software_download_use_venv` is `true` (default), a temporary virtual environment is created, and modules are installed via `pip`.
+ - The Python version is determined by `sap_software_download_python_interpreter`.
+- **System Environment:**
+ - When `sap_software_download_use_venv` is `false`, modules are installed directly into the system's Python environment using OS packages specified by `sap_software_download_python_module_packages`.
+
+
+
+## Prerequisites
+The target node must meet the following requirements:
+
+* **OS Package Repositories:** The operating system must be registered and have access to repositories to install the required Python packages.
+ * The actual package name is determined by the `sap_software_download_python_package` variable.
+ * For example, on some systems, these packages might be named `python3` and `python3-pip`.
+
+
+
+
+## Execution
+
+
+
+
+
+
+### Execution Flow
+
+1. **Input Validation:** The role first checks if all required input variables have been provided.
+2. **Python Environment Preparation:** The role prepares the Python environment:
+ * **Virtual Environment (Default):** A temporary Python virtual environment is created, and all necessary dependencies are installed within it.
+ * **System Environment:** Alternatively, if `sap_software_download_use_venv` is set to `false`, dependencies are installed directly into the system's default Python environment.
+3. **Validate provided S-User credentials** The role will search for `SAPCAR` file to validate credentials and download authorization.
+4. **Maintenance Plan File List:** If the `sap_software_download_mp_transaction` variable is provided, the role retrieves the list of files associated with the specified Maintenance Plan transaction.
+5. **File Relationship Validation:** If `sap_software_download_validate_relationships` is `true`, the role performs validation checks on the relationships between the files to be downloaded.
+ * **Alternative File Search:** If `sap_software_download_find_alternatives` is `true`, the role will search for alternative files if the requested files are not found.
+ * More information about validation logic is available at [Explanation of relationship validation logic](#explanation-of-relationship-validation-logic)
+6. **Maintenance Plan File Download:** If `sap_software_download_mp_transaction` is provided, the role downloads the files associated with the Maintenance Plan.
+7. **Direct File Download:** If `sap_software_download_files` is provided, the role downloads the specified files.
+8. **Virtual Environment Cleanup:** If a temporary Python virtual environment was used, it is removed.
+
+
+
+### Example
+
+Download of SAP Software files using input list
+```yaml
+---
+- name: Ansible Play for downloading SAP Software
+ hosts: localhost
+ become: true
+ tasks:
+ - name: Include role sap_software_download
+ ansible.builtin.include_role:
+ name: community.sap_launchpad.sap_software_download
+ vars:
+ sap_software_download_suser_id: "Enter SAP S-User ID"
+ sap_software_download_suser_password: "Enter SAP S-User Password"
+ sap_software_download_directory: "/software"
+ sap_software_download_files:
+ - 'SAPCAR_1115-70006178.EXE'
+ - 'SAPEXE_100-80005509.SAR'
+```
+
+Download of SAP Software files using Maintenance Plan
+```yaml
+---
+- name: Ansible Play for downloading SAP Software
+ hosts: localhost
+ become: true
+ tasks:
+ - name: Include role sap_software_download
+ ansible.builtin.include_role:
+ name: community.sap_launchpad.sap_software_download
+ vars:
+ sap_software_download_suser_id: "Enter SAP S-User ID"
+ sap_software_download_suser_password: "Enter SAP S-User Password"
+ sap_software_download_directory: "/software"
+ sap_software_download_mp_transaction: 'Transaction Name or Display ID from Maintenance Planner'
+```
+
+Combined download of SAP Software files and Maintenance Plan transaction together with settings:
+- Use default Python instead of Python virtual environment
+- No validation of S-User credentials
+- No validation of relationships
+- No warnings for unavailable files
+- No warnings for unavailable Maintenance Plan transaction
+```yaml
+- name: Ansible Play for downloading SAP Software
+ hosts: localhost
+ become: true
+ tasks:
+ - name: Include role sap_software_download
+ ansible.builtin.include_role:
+ name: community.sap_launchpad.sap_software_download
+ vars:
+ sap_software_download_suser_id: "Enter SAP S-User ID"
+ sap_software_download_suser_password: "Enter SAP S-User Password"
+ sap_software_download_directory: "/software"
+ sap_software_download_use_venv: false
+ sap_software_download_ignore_validate_credentials: true
+ sap_software_download_ignore_file_not_found: true
+ sap_software_download_ignore_plan_not_found: true
+ sap_software_download_validate_relationships: false
+ sap_software_download_deduplicate: first
+ sap_software_download_files:
+ - 'SAPCAR_1115-70006178.EXE'
+ - 'SAPEXE_100-80005509.SAR'
+ sap_software_download_mp_transaction: 'Transaction Name or Display ID from Maintenance Planner'
+```
+Download of SAP Software files using Python version `3.13`.
+```yaml
+---
+- name: Ansible Play for downloading SAP Software
+ hosts: localhost
+ become: true
+ tasks:
+ - name: Include role sap_software_download
+ ansible.builtin.include_role:
+ name: community.sap_launchpad.sap_software_download
+ vars:
+ sap_software_download_python_interpreter: python3.13
+ sap_software_download_python_package: python313
+ sap_software_download_python_module_packages:
+ - python313-wheel
+ - python313-urllib3
+ - python313-requests
+ - python313-beautifulsoup4
+ - python313-lxml
+ sap_software_download_suser_id: "Enter SAP S-User ID"
+ sap_software_download_suser_password: "Enter SAP S-User Password"
+ sap_software_download_directory: "/software"
+ sap_software_download_files:
+ - 'SAPCAR_1115-70006178.EXE'
+ - 'SAPEXE_100-80005509.SAR'
+```
+
+
+
+
+
+
+## Further Information
+### Explanation of relationship validation logic
+Validation is executed for known combinations of files, where we can validate their name and version.
+Example for SAP HANA Database Server 2.0 with LCAPPS and AFL.
+
+1. All files are examined, and a file starting with `IMDB_SERVER2` is found: `IMDB_SERVER20_084_0-80002031.SAR (Revision 2.00.084.0 (SPS08))`. This indicates a SAP HANA 2.0 database server file.
+2. The HANA version and revision are extracted from the file name: `HANA 2.0`, `Version 084`.
+3. Validation for HANA 1.0 is skipped because it expects files starting with `IMDB_SERVER1`. The following steps are only for `IMDB_SERVER2` (HANA 2.0).
+4. All files are examined for files starting with `IMDB_LCAPPS_2` (indicating LCAPPS for HANA 2.0). Then the list is filtered to only include files starting with `IMDB_LCAPPS_2084` (indicating LCAPPS for HANA 2.0 revision 084).
+5. Validation will have two outcomes:
+ - A file like `IMDB_LCAPPS_2084_0-20010426.SAR` is present. In this case, validation will pass because the LCAPPS version is compatible with the HANA revision.
+ - No file starting with `IMDB_LCAPPS_2084` is present, but there are files starting with `IMDB_LCAPPS_2`.
+ This indicates a mismatch because the LCAPPS version is not compatible with the specific HANA revision (084) found in step 2.
+ In this case, validation will fail. This can be ignored by setting `sap_software_download_ignore_relationship_warning` to `true`.
+6. All files are examined for files starting with `IMDB_AFL20` (indicating AFL for HANA 2.0). Then the list is filtered to only include files starting with `IMDB_AFL20_084` (indicating AFL for HANA 2.0 revision 084).
+7. Validation will have two outcomes:
+ - A file like `IMDB_AFL20_084_1-80001894.SAR` is present. In this case, validation will pass because the AFL version is compatible with the HANA revision.
+ - No file starting with `IMDB_AFL20_084` is present, but there are files starting with `IMDB_AFL20`.
+ This indicates a mismatch because the AFL version is not compatible with the specific HANA revision (084) found in step 2.
+ In this case, validation will fail. This can be ignored by setting `sap_software_download_ignore_relationship_warning` to `true`.
+
+This validation example checks major and minor release (SPS and Revision), but it does not validate patch version.
+
+
+## License
+
+Apache 2.0
+
+
+## Maintainers
+
+- [Marcel Mamula](https://github.com/marcelmamula)
+
+
+## Role Variables
+
+### sap_software_download_python_interpreter
+- _Type:_ `string`
+- _Default:_ **Determined by the operating system.**
+
+The Python interpreter executable to use when creating a Python virtual environment.
+**Mandatory** when `sap_software_download_use_venv` is `true`.
+This is the name of the Python executable (e.g., `python3.11`, `python3.9`), which may differ from the Python package name.
+The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+Examples: `python3.11` (SUSE), `python3.9` (Red Hat)
+
+### sap_software_download_python_package
+- _Type:_ `string`
+- _Default:_ **Determined by the operating system.**
+
+The name of the OS package that provides the desired Python version.
+The Python version provided by this package must match the version specified by `sap_software_download_python_interpreter`.
+The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+Examples: `python311` (SUSE), `python3.9` (Red Hat)
+
+### sap_software_download_python_module_packages
+- _Type:_ `list` with elements of type `string`
+- _Default:_ **Determined by the operating system.**
+
+The list of the OS packages that provide modules for the desired Python version.
+Required modules are wheel, urllib3, requests, beautifulsoup4, lxml
+The listed package versions must match the Python version specified by `sap_software_download_python_interpreter`.
+The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+Examples:
+- `['python311-wheel', 'python311-urllib3', 'python311-requests', 'python311-beautifulsoup4', 'python311-lxml']` (SUSE)
+- `['python3.9-wheel', 'python3.9-urllib3', 'python3.9-requests', 'python3.9-beautifulsoup4', 'python3.9-lxml']` (Red Hat)
+
+### sap_software_download_use_venv
+- _Type:_ `boolean`
+- _Default:_ `true`
+
+Determines whether to execute the role within a Python virtual environment.
+Using a virtual environment is strongly recommended to isolate dependencies.
+If set to `false`, the role will install Python dependencies directly into the system's Python environment.
+
+### sap_software_download_suser_id
+- _Type:_ `string`
+
+The SAP S-User ID with download authorization for SAP software.
+
+### sap_software_download_suser_password
+- _Type:_ `string`
+
+The password for the SAP S-User specified in `sap_software_download_suser_id`.
+
+### sap_software_download_files
+- _Type:_ `list` with elements of type `string`
+
+A list of SAP software file names to download.
+
+### sap_software_download_mp_transaction
+- _Type:_ `string`
+
+The name or display ID of a transaction from the SAP Maintenance Planner.
+If provided, the role will download all files associated with this Maintenance Plan transaction.
+
+### sap_software_download_find_alternatives
+- _Type:_ `boolean`
+- _Default:_ `true`
+
+Enables searching for alternative files if the requested file is not found.
+Only applies to files specified in `sap_software_download_files`.
+If set to `false`, the role will not search for alternatives.
+
+### sap_software_download_directory
+- _Type:_ `string`
+
+The directory where downloaded SAP software files will be stored.
+
+### sap_software_download_validate_relationships
+- _Type:_ `bool`
+- _Default:_ `true`
+
+Enables validation of relationships between SAP software files.
+Only applies to files specified in `sap_software_download_files`.
+If set to `false`, no relationship validation will be performed.
+Example: Verify version of IMDB_LCAPPS against IMDB_SERVER if IMDB_SERVER was found.
+
+### sap_software_download_ignore_file_not_found
+- _Type:_ `bool`
+- _Default:_ `false`
+
+Determines whether to ignore errors when a requested file is not found.
+If set to `true`, the role will continue execution and download other files, even if some files are not found.
+If set to `false`, the role will fail if any requested file is not found.
+
+### sap_software_download_ignore_plan_not_found
+- _Type:_ `bool`
+- _Default:_ `false`
+
+Determines whether to ignore errors when a specified Maintenance Plan transaction is not found.
+If set to `true` and a Maintenance Plan is not found, the role will continue execution, downloading any files specified in `sap_software_download_files`.
+If set to `false`, the role will fail if the specified Maintenance Plan is not found.
+
+### sap_software_download_ignore_relationship_warning
+- _Type:_ `bool`
+- _Default:_ `false`
+
+Determines whether to ignore warnings during file relationship validation.
+If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships.
+If set to `false`, the role will fail if any warnings are encountered during file relationship validation.
+
+### sap_software_download_ignore_validate_credentials
+- _Type:_ `bool`
+- _Default:_ `false`
+
+Determines whether to ignore validate credentials task.
+Disabling this check can lead to locked account, if password is incorrect.
+If set to `true`, the role will continue execution without validating S-User credentials.
+If set to `false`, the role will execute dry run to validate S-User credentials.
+
+### sap_software_download_deduplicate
+- _Type:_ `string`
+
+Specifies how to handle duplicate file results when using `sap_software_download_files`.
+If multiple files with the same name are found, this setting determines which one to download.
+- `first`: Download the first file found
+- `last`: Download the last file found.
+
diff --git a/roles/sap_software_download/defaults/main.yml b/roles/sap_software_download/defaults/main.yml
new file mode 100644
index 0000000..50ac01f
--- /dev/null
+++ b/roles/sap_software_download/defaults/main.yml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# The Python interpreter executable to use when creating a Python virtual environment.
+# Mandatory when `sap_software_download_use_venv` is `true`.
+# This is the name of the Python executable (e.g., `python3.11`, `python3.9`), which may differ from the Python package name.
+# The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+# Examples: `python3.11` (SUSE), `python3.9` (Red Hat)
+sap_software_download_python_interpreter:
+ "{{ __sap_software_download_python_interpreter }}"
+
+# The name of the OS package that provides the desired Python version.
+# The Python version provided by this package must match the version specified by `sap_software_download_python_interpreter`.
+# The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+# Examples: `python311` (SUSE), `python3.9` (Red Hat)
+sap_software_download_python_package:
+ "{{ __sap_software_download_python_package }}"
+
+# The list of the OS packages that provide modules for the desired Python version.
+# Required modules: wheel, urllib3, requests, beautifulsoup4, lxml
+# The listed package versions must match the Python version specified by `sap_software_download_python_interpreter`.
+# The default value is determined by the operating system and is set in the corresponding OS-specific variables file. Examples:
+# python311-wheel, python311-urllib3, python311-requests, python311-beautifulsoup4, python311-lxml (SUSE)
+# python3.9-wheel, python3.9-urllib3, python3.9-requests, python3.9-beautifulsoup4, python3.9-lxml (Red Hat)
+sap_software_download_python_module_packages:
+ "{{ __sap_software_download_python_module_packages }}"
+
+# Determines whether to execute the role within a Python virtual environment.
+# Using a virtual environment is strongly recommended to isolate dependencies.
+# If set to `false`, the role will install Python dependencies directly into the system's Python environment.
+sap_software_download_use_venv: true
+
+# The SAP S-User ID with download authorization for SAP software.
+sap_software_download_suser_id: ''
+
+# The password for the SAP S-User specified in `sap_software_download_suser_id`.
+sap_software_download_suser_password: ''
+
+# A list of SAP software file names to download.
+sap_software_download_files: []
+
+# The name or display ID of a transaction from the SAP Maintenance Planner.
+# If provided, the role will download all files associated with this Maintenance Plan transaction.
+sap_software_download_mp_transaction: ''
+
+# Enables searching for alternative files if the requested file is not found.
+# Only applies to files specified in `sap_software_download_files`.
+# If set to `false`, the role will not search for alternatives.
+sap_software_download_find_alternatives: true
+
+# The directory where downloaded SAP software files will be stored.
+sap_software_download_directory: '/software'
+
+# Determines whether to ignore errors when a requested file is not found.
+# If set to `true`, the role will continue execution and download other files, even if some files are not found.
+# If set to `false`, the role will fail if any requested file is not found.
+sap_software_download_ignore_file_not_found: false
+
+# Determines whether to ignore errors when a specified Maintenance Plan transaction is not found.
+# If set to `true` and a Maintenance Plan is not found, the role will continue execution,
+# downloading any files specified in `sap_software_download_files`.
+# If set to `false`, the role will fail if the specified Maintenance Plan is not found.
+sap_software_download_ignore_plan_not_found: false
+
+# Enables validation of relationships between SAP software files.
+# Only applies to files specified in `sap_software_download_files`.
+# If set to `false`, no relationship validation will be performed.
+# Example: Verify version of IMDB_LCAPPS against IMDB_SERVER if IMDB_SERVER was found.
+sap_software_download_validate_relationships: true
+
+# Determines whether to ignore warnings during file relationship validation.
+# If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships.
+# If set to `false`, the role will fail if any warnings are encountered during file relationship validation.
+sap_software_download_ignore_relationship_warning: false
+
+# Determines whether to ignore validate credentials task.
+# Disabling this check can lead to locked account, if password is incorrect.
+# If set to `true`, the role will continue execution without validating S-User credentials.
+# If set to `false`, the role will execute dry run to validate S-User credentials.
+sap_software_download_ignore_validate_credentials: false
+
+# Specifies how to handle duplicate file results when using `sap_software_download_files`.
+# If multiple files with the same name are found, this setting determines which one to download.
+# `first`: Download the first file found.
+# `last`: Download the last file found.
+# sap_software_download_deduplicate: first
diff --git a/roles/sap_software_download/meta/argument_spec.yml b/roles/sap_software_download/meta/argument_spec.yml
new file mode 100644
index 0000000..6a64e3e
--- /dev/null
+++ b/roles/sap_software_download/meta/argument_spec.yml
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+# Requires: ansible 2.16
+# Argument specifications in this separate file maintain backwards compatibility.
+argument_specs:
+
+ main:
+ short_description: Downloads SAP Software Media from SAP using an S-User ID and password.
+ description:
+ - This role downloads SAP Software Media from SAP using an S-User ID and password.
+ - It supports both direct file downloads and Maintenance Plan transactions.
+ options:
+
+ sap_software_download_python_interpreter:
+ description:
+ - If set to `false`, the role will only execute or verify the installation or configuration steps of SAP notes.
+ - Default is to perform installation and configuration steps.
+ required: false
+ type: str
+ - The Python interpreter executable to use when creating a Python virtual environment.
+ - Mandatory when `sap_software_download_use_venv` is `true`.
+ - This is the name of the Python executable (e.g., `python3.11`, `python3.9`), which may differ from the Python package name.
+ - The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+ - Examples are `python3.11` (SUSE), `python3.9` (Red Hat)
+
+ sap_software_download_python_package:
+ type: str
+ required: false
+ description:
+ - The name of the OS package that provides the desired Python version.
+ - The Python version provided by this package must match the version specified by `sap_software_download_python_interpreter`.
+ - The default value is determined by the operating system and is set in the corresponding OS-specific variables file.
+ - Examples are `python311` (SUSE), `python3.9` (Red Hat)
+
+ sap_software_download_python_module_packages:
+ type: list
+ elements: str
+ required: false
+ description:
+ - The list of the OS packages that provide modules for the desired Python version.
+ - Required modules are wheel, urllib3, requests, beautifulsoup4, lxml
+ - The listed package versions must match the Python version specified by `sap_software_download_python_interpreter`.
+ - The default value is determined by the operating system and is set in the corresponding OS-specific variables file. Examples are
+ - python311-wheel, python311-urllib3, python311-requests, python311-beautifulsoup4, python311-lxml (SUSE)
+ - python3.9-wheel, python3.9-urllib3, python3.9-requests, python3.9-beautifulsoup4, python3.9-lxml (Red Hat)
+
+ sap_software_download_use_venv:
+ type: bool
+ required: false
+ default: true
+ description:
+ - Determines whether to execute the role within a Python virtual environment.
+ - Using a virtual environment is strongly recommended to isolate dependencies.
+ - If set to `false`, the role will install Python dependencies directly into the system's Python environment.
+
+ sap_software_download_suser_id:
+ type: str
+ required: true
+ description:
+ - The SAP S-User ID with download authorization for SAP software.
+
+ sap_software_download_suser_password:
+ type: str
+ required: true
+ no_log: true
+ description:
+ - The password for the SAP S-User specified in `sap_software_download_suser_id`.
+
+ sap_software_download_files:
+ type: list
+ elements: str
+ required: false
+ default: []
+ description:
+ - A list of SAP software file names to download.
+
+ sap_software_download_mp_transaction:
+ type: str
+ required: false
+ default: ""
+ description:
+ - The name or display ID of a transaction from the SAP Maintenance Planner.
+ - If provided, the role will download all files associated with this Maintenance Plan transaction.
+
+ sap_software_download_find_alternatives:
+ type: bool
+ required: true
+ default: true
+ description:
+ - Enables searching for alternative files if the requested file is not found.
+ - Only applies to files specified in `sap_software_download_files`.
+ - If set to `false`, the role will not search for alternatives.
+
+ sap_software_download_directory:
+ type: str
+ required: true
+ default: "/software"
+ description:
+ - The directory where downloaded SAP software files will be stored.
+
+ sap_software_download_validate_relationships:
+ type: bool
+ required: false
+ default: true
+ description:
+ - Enables validation of relationships between SAP software files.
+ - Only applies to files specified in `sap_software_download_files`.
+ - If set to `false`, no relationship validation will be performed.
+ - Example Verify version of IMDB_LCAPPS against IMDB_SERVER if IMDB_SERVER was found.
+
+ sap_software_download_ignore_file_not_found:
+ type: bool
+ required: false
+ default: false
+ description:
+ - Determines whether to ignore errors when a requested file is not found.
+ - If set to `true`, the role will continue execution and download other files, even if some files are not found.
+ - If set to `false`, the role will fail if any requested file is not found.
+
+ sap_software_download_ignore_plan_not_found:
+ type: bool
+ required: false
+ default: false
+ description:
+ - Determines whether to ignore errors when a specified Maintenance Plan transaction is not found.
+ - If set to `true` and a Maintenance Plan is not found, the role will continue execution,
+ - downloading any files specified in `sap_software_download_files`.
+ - If set to `false`, the role will fail if the specified Maintenance Plan is not found.
+
+ sap_software_download_ignore_relationship_warning:
+ type: bool
+ required: false
+ default: false
+ description:
+ - Determines whether to ignore warnings during file relationship validation.
+ - If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships.
+ - If set to `false`, the role will fail if any warnings are encountered during file relationship validation.
+
+ sap_software_download_ignore_validate_credentials:
+ type: bool
+ required: false
+ default: false
+ description:
+ - Determines whether to ignore warnings during file relationship validation.
+ - Disabling this check can lead to locked account, if password is incorrect.
+ - If set to `true`, the role will continue execution even if there are warnings during the validation of file relationships.
+ - If set to `false`, the role will fail if any warnings are encountered during file relationship validation.
+
+ sap_software_download_deduplicate:
+ type: str
+ required: false
+ default: "first"
+ choices: ["first", "last"]
+ description:
+ - Specifies how to handle duplicate file results when using `sap_software_download_files`.
+ - If multiple files with the same name are found, this setting determines which one to download.
+ - Value `first` - Download the first file found.
+ - Value `last` - Download the last file found.
diff --git a/roles/sap_software_download/meta/main.yml b/roles/sap_software_download/meta/main.yml
new file mode 100644
index 0000000..cdd1066
--- /dev/null
+++ b/roles/sap_software_download/meta/main.yml
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+galaxy_info:
+ namespace: community
+ author: SUSE, Marcel Mamula
+ description: Downloads SAP Software Media from SAP using an S-User ID and password, supporting both direct file downloads and Maintenance Plan transactions.
+ company: SUSE
+ license: Apache-2.0
+ min_ansible_version: 2.16
+ platforms:
+ - name: EL
+ versions: ["7", "8", "9"]
+ - name: SLES
+ versions: ["15", "16"]
+ galaxy_tags:
+ - sap
+ - download
+ - suse
+ - redhat
+dependencies: []
diff --git a/roles/sap_software_download/tasks/download_files.yml b/roles/sap_software_download/tasks/download_files.yml
new file mode 100644
index 0000000..177e76f
--- /dev/null
+++ b/roles/sap_software_download/tasks/download_files.yml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Download - SAP Software Files - Get files with Python venv
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ search_query: "{{ item }}"
+ dest: "{{ sap_software_download_directory }}"
+ search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}"
+ deduplicate: "{{ sap_software_download_deduplicate | d('') }}"
+ # Loop condition acts as when conditional
+ loop: "{{ sap_software_download_files if sap_software_download_use_venv | d(true) else [] }}"
+ loop_control:
+ label: "{{ item }} : {{ __sap_software_download_files_results_venv.msg | d('') }}"
+ register: __sap_software_download_files_results_venv
+ retries: 1
+ until: __sap_software_download_files_results_venv is not failed
+ environment:
+ PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}"
+ PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages"
+ VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}"
+ vars:
+ ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+
+- name: Download - SAP Software Files - Get files with Python system default
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ search_query: "{{ item }}"
+ dest: "{{ sap_software_download_directory }}"
+ search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}"
+ deduplicate: "{{ sap_software_download_deduplicate | d('') }}"
+ # Loop condition acts as when conditional
+ loop: "{{ sap_software_download_files if not sap_software_download_use_venv | d(true) else [] }}"
+ loop_control:
+ label: "{{ item }} : {{ __sap_software_download_files_results_default.msg | d('') }}"
+ register: __sap_software_download_files_results_default
+ retries: 1
+ until: __sap_software_download_files_results_default is not failed
+ vars:
+ ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+
+- name: Download - SAP Software Files - Set fact with software_center_download output
+ ansible.builtin.set_fact:
+ __sap_software_download_files_results: "{{ __sap_software_download_files_results_venv
+ if sap_software_download_use_venv | d(true) else __sap_software_download_files_results_default }}"
+
+- name: Download - SAP Software Files - Show failed results
+ ansible.builtin.fail:
+ msg: |
+ Download failed for following files: {{ __failed_items | map(attribute='item') | list | join(', ') }}
+ Either set `sap_software_download_find_alternatives` to `true` to search for alternative files
+ or ignore this error with `sap_software_download_ignore_file_not_found` set to `true`.
+ vars:
+ __failed_items: "{{ __sap_software_download_files_results.results
+ | selectattr('failed', 'defined') | selectattr('failed', 'true') }}"
+ when:
+ - not sap_software_download_ignore_file_not_found | d(false)
+ - __failed_items | length > 0
diff --git a/roles/sap_software_download/tasks/download_plan.yml b/roles/sap_software_download/tasks/download_plan.yml
new file mode 100644
index 0000000..b89af1f
--- /dev/null
+++ b/roles/sap_software_download/tasks/download_plan.yml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Download - Maintenance Plan - Get files with Python venv
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ download_link: "{{ item.DirectLink }}"
+ download_filename: "{{ item.Filename }}"
+ dest: "{{ sap_software_download_directory }}"
+ # Loop condition acts as when conditional
+ loop: "{{ __sap_software_download_mp_transaction_results.download_basket if sap_software_download_use_venv | d(true) else [] }}"
+ loop_control:
+ label: "{{ item.Filename }} : {{ __sap_software_download_files_plan_results_venv.msg | d('') }}"
+ register: __sap_software_download_files_plan_results_venv
+ retries: 1
+ until: __sap_software_download_files_plan_results_venv is not failed
+ environment:
+ PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}"
+ PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages"
+ VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}"
+ vars:
+ ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+
+- name: Download - Maintenance Plan - Get files with Python system default
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ download_link: "{{ item.DirectLink }}"
+ download_filename: "{{ item.Filename }}"
+ dest: "{{ sap_software_download_directory }}"
+ # Loop condition acts as when conditional
+ loop: "{{ __sap_software_download_mp_transaction_results.download_basket if not sap_software_download_use_venv | d(true) else [] }}"
+ loop_control:
+ label: "{{ item.Filename }} : {{ __sap_software_download_files_plan_results_default.msg | d('') }}"
+ register: __sap_software_download_files_plan_results_default
+ retries: 1
+ until: __sap_software_download_files_plan_results_default is not failed
+ vars:
+ ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+
+- name: Download - Maintenance Plan - Set fact with software_center_download output
+ ansible.builtin.set_fact:
+ __sap_software_download_files_plan_results: "{{ __sap_software_download_files_plan_results_venv
+ if sap_software_download_use_venv | d(true) else __sap_software_download_files_plan_results_default }}"
+
+- name: Download - Maintenance Plan - Show failed results
+ ansible.builtin.fail:
+ msg: |
+ Maintenance Plan file(s) not found: {{ __failed_items | map(attribute='item.Filename') | list | join(', ') }}
+ Verify your Maintenance Plan on SAP Launchpad before retrying.
+ vars:
+ __failed_items: "{{ __sap_software_download_files_plan_results.results
+ | selectattr('failed', 'defined') | selectattr('failed', 'true') }}"
+ when:
+ - not sap_software_download_ignore_file_not_found | d(false)
+ - __failed_items | length > 0
diff --git a/roles/sap_software_download/tasks/main.yml b/roles/sap_software_download/tasks/main.yml
new file mode 100644
index 0000000..299dcf5
--- /dev/null
+++ b/roles/sap_software_download/tasks/main.yml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: SAP Software Download - Pre-Steps - Include role variables
+ ansible.builtin.include_tasks:
+ file: pre_steps/01_include_variables.yml
+
+- name: SAP Software Download - Pre-Steps - Prepare Python environment
+ ansible.builtin.include_tasks:
+ file: pre_steps/02_prepare_python_environment.yml
+
+- name: SAP Software Download - Pre-Steps - Validate user credentials
+ ansible.builtin.include_tasks:
+ file: pre_steps/03_validate_credentials.yml
+ when: not sap_software_download_ignore_validate_credentials | d(false)
+
+- name: SAP Software Download - Pre-Steps - Find files for Maintenance Plan
+ ansible.builtin.include_tasks:
+ file: pre_steps/04_get_plan_files.yml
+ when:
+ - sap_software_download_mp_transaction | length > 0
+
+# NOTE: We do not validate files generated by Maintenance Plan.
+- name: SAP Software Download - Pre-Steps - Check related SAP Software combinations
+ ansible.builtin.include_tasks:
+ file: pre_steps/05_validate_relations.yml
+ when:
+ - sap_software_download_files | length > 0
+ - sap_software_download_validate_relationships
+
+
+- name: SAP Software Download - Download - Maintenance Plan {{ sap_software_download_mp_transaction | d('') }}
+ ansible.builtin.include_tasks:
+ file: download_plan.yml
+ when:
+ - sap_software_download_mp_transaction | length > 0
+ - __sap_software_download_mp_transaction_results.download_basket is defined
+ and __sap_software_download_mp_transaction_results.download_basket | length > 0
+
+- name: SAP Software Download - Download - Files in sap_software_download_files
+ ansible.builtin.include_tasks:
+ file: download_files.yml
+
+
+- name: SAP Software Download - Post-Steps - Cleanup Python environment
+ ansible.builtin.include_tasks:
+ file: post_steps/01_cleanup_python_environment.yml
diff --git a/roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml b/roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml
new file mode 100644
index 0000000..e3d303b
--- /dev/null
+++ b/roles/sap_software_download/tasks/post_steps/01_cleanup_python_environment.yml
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Post-Steps - Remove temporary Python Virtual Environment
+ ansible.builtin.file:
+ path: "{{ __sap_software_download_venv.path }}"
+ state: absent
+ when: sap_software_download_use_venv | d(true)
diff --git a/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml
new file mode 100644
index 0000000..edfec13
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/01_include_variables.yml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# Example of files loading order:
+# 1. Suse.yml / RedHat.yml - Specific to OS family.
+# 2. SLES_15.yml / RedHat_9.yml - Specific to distribution (SLES, SLES_SAP or RedHat) and major release.
+# 3. SLES_15.6.yml / RedHat_9.2 - Specific to distribution (SLES, SLES_SAP or RedHat) and minor release.
+# 4. SLES_SAP_15.yml - Specific to distribution SLES_SAP and major release.
+# 5. SLES_SAP_15.6.yml - Specific to distribution SLES_SAP and minor release.
+- name: Pre-Steps - Include OS specific variables
+ ansible.builtin.include_vars: "{{ __vars_file }}"
+ loop: "{{ __var_files }}"
+ vars:
+ __vars_file: "{{ role_path }}/vars/{{ item }}"
+ __distribution_major: "{{ ansible_distribution ~ '_' ~ ansible_distribution_major_version }}"
+ __distribution_minor: "{{ ansible_distribution ~ '_' ~ ansible_distribution_version }}"
+ # Enables loading of shared vars between SLES and SLES_SAP
+ __distribution_major_split: "{{ ansible_distribution.split('_')[0] ~ '_' ~ ansible_distribution_major_version }}"
+ __distribution_minor_split: "{{ ansible_distribution.split('_')[0] ~ '_' ~ ansible_distribution_version }}"
+ __var_files: >-
+ {{
+ [
+ ansible_os_family ~ '.yml',
+ (ansible_distribution ~ '.yml') if ansible_distribution != ansible_os_family else None,
+ (__distribution_major_split ~ '.yml') if __distribution_major_split != __distribution_major else None,
+ (__distribution_minor_split ~ '.yml') if __distribution_minor_split != __distribution_minor else None,
+ __distribution_major ~ '.yml',
+ __distribution_minor ~ '.yml'
+ ] | select('defined') | select('string') | list
+ }}
+ when: __vars_file is file
+
+
+- name: Pre-Steps - Assert that SAP Software files were specified
+ ansible.builtin.assert:
+ that:
+ - (sap_software_download_files is defined and sap_software_download_files | type_debug == 'list' and sap_software_download_files | length > 0)
+ or (sap_software_download_mp_transaction is defined and sap_software_download_mp_transaction | length > 0)
+ fail_msg: |
+ Neither `sap_software_download_files` or `sap_software_download_mp_transaction` are valid.
+ Ensure that it at least one of them is valid.
+
+- name: "Pre-Steps - Assert that download directory was provided"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_directory is defined
+ - sap_software_download_directory | length > 0
+ fail_msg: |
+ Empty variable `sap_software_download_directory`.
+
+
+- name: "Pre-Steps - Verify variable: sap_software_download_use_venv"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_use_venv is boolean
+ fail_msg: |
+ Variable `sap_software_download_use_venv` is not boolean.
+ when: sap_software_download_use_venv is defined
+
+- name: "Pre-Steps - Verify variable: sap_software_download_python_interpreter"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_python_interpreter is defined
+ - sap_software_download_python_interpreter | length > 0
+ fail_msg: |
+ Empty variable `sap_software_download_python_interpreter`.
+ Ensure that it contains correct Python interpreter or revert back to defaults.
+ when: sap_software_download_use_venv
+
+- name: "Pre-Steps - Verify variable: sap_software_download_python_package"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_python_package is defined
+ - sap_software_download_python_package | length > 0
+ fail_msg: |
+ Empty variable `sap_software_download_python_package`.
+ Ensure that it contains correct Python package name or revert back to defaults.
+
+- name: "Pre-Steps - Verify variable: sap_software_download_python_module_packages"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_python_module_packages is defined
+ - sap_software_download_python_module_packages | type_debug == 'list'
+ - sap_software_download_python_module_packages | length > 0
+ fail_msg: |
+ Empty variable `sap_software_download_python_module_packages`.
+ Ensure that it contains correct list of Python module package names or revert back to defaults.
+
+- name: "Pre-Steps - Verify variable: sap_software_download_suser_id"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_suser_id is defined
+ - sap_software_download_suser_id | length > 0
+ fail_msg: |
+ Empty variable `sap_software_download_suser_id`.
+ Enter valid S-User ID with download authorizations.
+
+- name: "Pre-Steps - Verify variable: sap_software_download_suser_password"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_suser_password is defined
+ - sap_software_download_suser_password | length > 0
+ fail_msg: |
+ Empty variable `sap_software_download_suser_password`.
+ Enter valid S-User password.
+ no_log: true
+
+- name: "Pre-Steps - Verify variable: sap_software_download_find_alternatives"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_find_alternatives is boolean
+ fail_msg: |
+ Variable `sap_software_download_find_alternatives` is not boolean.
+ when: sap_software_download_find_alternatives is defined
+
+- name: "Pre-Steps - Verify variable: sap_software_download_deduplicate"
+ ansible.builtin.assert:
+ that:
+ - sap_software_download_deduplicate in ['first', 'last']
+ fail_msg: |
+ Enter valid option for `sap_software_download_deduplicate` variable.
+ Options: first, last
+ when: sap_software_download_deduplicate is defined
diff --git a/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml b/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml
new file mode 100644
index 0000000..2be5480
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/02_prepare_python_environment.yml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Pre-Steps - Install Python and Python package manager pip
+ ansible.builtin.package:
+ name:
+ - "{{ sap_software_download_python_package }}"
+ - "{{ sap_software_download_python_package }}-pip"
+ state: present
+
+
+- name: Pre-Steps - Create download directory {{ sap_software_download_directory }}
+ ansible.builtin.file:
+ path: "{{ sap_software_download_directory }}"
+ state: directory
+ mode: '0755'
+
+
+- name: Pre-Steps - Block for Python venv preparation
+ when: sap_software_download_use_venv | d(true)
+ block:
+ - name: Pre-Steps - Create temporary directory for venv
+ ansible.builtin.tempfile:
+ state: directory
+ suffix: __sap_software_download_venv
+ register: __sap_software_download_venv
+
+ - name: Pre-Steps - Install Python modules to Python venv
+ ansible.builtin.pip:
+ name: "{{ __sap_software_download_python_modules }}"
+ virtualenv: "{{ __sap_software_download_venv.path }}"
+ virtualenv_command: "{{ sap_software_download_python_interpreter }} -m venv"
+
+
+- name: Pre-Steps - Block for default Python preparation
+ when: not sap_software_download_use_venv | d(true)
+ block:
+ # Packages with python modules are installed instead of modules to avoid error:
+ # `externally-managed-environment` which requires `--break-system-packages`
+ - name: Pre-Steps - Install Python module packages
+ ansible.builtin.package:
+ name: "{{ __sap_software_download_python_module_packages }}"
+ state: present
diff --git a/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml
new file mode 100644
index 0000000..8154b72
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/03_validate_credentials.yml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+# This task attempts dry run to check SAPCAR file in order to validate provided credentials.
+
+- name: Validate Credentials - Dry run check user credentials and download privilege with Python venv
+ when: sap_software_download_use_venv | d(true)
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ search_query: "SAPCAR"
+ dest: "{{ sap_software_download_directory }}"
+ search_alternatives: true
+ deduplicate: "last"
+ dry_run: true
+ register: __sap_software_download_validate_credentials_venv
+ retries: 1
+ delay: 5
+ environment:
+ PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}"
+ PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages"
+ VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}"
+ vars:
+ ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+- name: Validate Credentials - Dry run check user credentials and download privilege with Python system default
+ when: not sap_software_download_use_venv | d(true)
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ search_query: "SAPCAR"
+ dest: "{{ sap_software_download_directory }}"
+ search_alternatives: true
+ deduplicate: "last"
+ dry_run: true
+ register: __sap_software_download_validate_credentials_default
+ retries: 1
+ delay: 5
+ vars:
+ ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+- name: Validate Credentials - Show failed results
+ ansible.builtin.fail:
+ msg: |
+ Validation of provided S-User credentials failed.
+ Ensure correct S-User credentials are provided in:
+ `sap_software_download_suser_id` and `sap_software_download_suser_password`
+ when:
+ - (sap_software_download_use_venv | d(true)
+ and __sap_software_download_validate_credentials_venv.failed is defined and __sap_software_download_validate_credentials_venv.failed)
+ or (not sap_software_download_use_venv | d(true)
+ and __sap_software_download_validate_credentials_default is defined and __sap_software_download_validate_credentials_default.failed)
diff --git a/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml b/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml
new file mode 100644
index 0000000..a4baef1
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/04_get_plan_files.yml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Maintenance Plan - Get list of files with Python venv
+ when: sap_software_download_use_venv | d(true)
+ community.sap_launchpad.maintenance_planner_files:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ transaction_name: "{{ sap_software_download_mp_transaction }}"
+ register: __sap_software_download_mp_transaction_results_venv
+ retries: 1
+ environment:
+ PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}"
+ PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages"
+ VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}"
+ vars:
+ ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}"
+ changed_when: false # Getting list of files does not change anything
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+- name: Maintenance Plan - Get list of files with default Python
+ when: not sap_software_download_use_venv | d(true)
+ community.sap_launchpad.maintenance_planner_files:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ transaction_name: "{{ sap_software_download_mp_transaction }}"
+ register: __sap_software_download_mp_transaction_results_default
+ retries: 1
+ vars:
+ ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}"
+ changed_when: false # Getting list of files does not change anything
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+- name: Maintenance Plan - Set fact with maintenance_planner_files output
+ ansible.builtin.set_fact:
+ __sap_software_download_mp_transaction_results: "{{ __sap_software_download_mp_transaction_results_venv
+ if sap_software_download_use_venv | d(true) else __sap_software_download_mp_transaction_results_default }}"
+
+
+- name: Maintenance Plan - Show failed results
+ ansible.builtin.fail:
+ msg: |
+ Maintenance Plan was not found.
+ Either ensure correct value in `sap_software_download_mp_transaction`
+ or ignore this error with `sap_software_download_ignore_plan_not_found` set to `true`.
+ when:
+ - not sap_software_download_ignore_plan_not_found | d(false)
+ - __sap_software_download_mp_transaction_results.failed
+
+- name: Maintenance Plan - Show ignored failed results
+ ansible.builtin.debug:
+ msg: |
+ Maintenance Plan was not found.
+ Error was ignored with `sap_software_download_ignore_plan_not_found` set to `true`.
+ when:
+ - sap_software_download_ignore_plan_not_found | d(false)
+ - __sap_software_download_mp_transaction_results.failed
diff --git a/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml
new file mode 100644
index 0000000..39c9687
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/05_validate_relations.yml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Block - Relationship Validation - Check availability of files (with alternatives)
+ when: sap_software_download_find_alternatives
+ block:
+
+ - name: Relationship Validation - Dry run to check availability of files with Python venv
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ search_query: "{{ item }}"
+ dest: "{{ sap_software_download_directory }}"
+ search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}"
+ deduplicate: "{{ sap_software_download_deduplicate | d('') }}"
+ dry_run: true
+ # Loop condition acts as when conditional
+ loop: "{{ sap_software_download_files if sap_software_download_use_venv | d(true) else [] }}"
+ loop_control:
+ label: "{{ item }} : {{ __sap_software_download_files_results_dryrun_venv.msg | d('') }}"
+ register: __sap_software_download_files_results_dryrun_venv
+ retries: 1
+ until: __sap_software_download_files_results_dryrun_venv is not failed
+ environment:
+ PATH: "{{ __sap_software_download_venv.path }}/bin:{{ ansible_env.PATH }}"
+ PYTHONPATH: "{{ __sap_software_download_venv.path }}/lib/{{ sap_software_download_python_interpreter }}/site-packages"
+ VIRTUAL_ENV: "{{ __sap_software_download_venv.path }}"
+ vars:
+ ansible_python_interpreter: "{{ __sap_software_download_venv.path ~ '/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+
+ - name: Relationship Validation - Dry run to check availability of files with Python system default
+ community.sap_launchpad.software_center_download:
+ suser_id: "{{ sap_software_download_suser_id }}"
+ suser_password: "{{ sap_software_download_suser_password }}"
+ search_query: "{{ item }}"
+ dest: "{{ sap_software_download_directory }}"
+ search_alternatives: "{{ sap_software_download_find_alternatives | d(true) }}"
+ deduplicate: "{{ sap_software_download_deduplicate | d('') }}"
+ dry_run: true
+ # Loop condition acts as when conditional
+ loop: "{{ sap_software_download_files if not sap_software_download_use_venv | d(true) else [] }}"
+ loop_control:
+ label: "{{ item }} : {{ __sap_software_download_files_results_dryrun_default.msg | d('') }}"
+ register: __sap_software_download_files_results_dryrun_default
+ retries: 1
+ until: __sap_software_download_files_results_dryrun_default is not failed
+ vars:
+ ansible_python_interpreter: "{{ '/usr/bin/' ~ sap_software_download_python_interpreter }}"
+ ignore_errors: true # Errors are ignored and validated afterwards
+
+
+ - name: Relationship Validation - Set fact with software_center_download output
+ ansible.builtin.set_fact:
+ __sap_software_download_files_results_dryrun: "{{ __sap_software_download_files_results_dryrun_venv
+ if sap_software_download_use_venv | d(true) else __sap_software_download_files_results_dryrun_default }}"
+
+ - name: Relationship Validation - Show failed results
+ ansible.builtin.fail:
+ msg: |
+ Relationship validation failed because following files were not found: {{ __failed_items | map(attribute='item') | list | join(', ') }}
+ Either ensure correct list of files in `sap_software_download_files`
+ or ignore this error with `sap_software_download_ignore_file_not_found` set to `true`.
+ vars:
+ __failed_items: "{{ __sap_software_download_files_results_dryrun.results | selectattr('failed', 'defined') | selectattr('failed', 'true') }}"
+ when:
+ - not sap_software_download_ignore_file_not_found | d(false)
+ - __failed_items | length > 0
+
+
+- name: Relationship Validation - Define list of files
+ ansible.builtin.set_fact:
+ __sap_software_download_files: "{{ sap_software_download_files if not sap_software_download_find_alternatives
+ else __sap_software_download_files_results_dryrun.results | selectattr('failed', 'false')| map(attribute='filename') | list | unique | d([])}}"
+
+
+- name: Relationship Validation - SAP HANA - Multiple IMDB_SERVER files found
+ ansible.builtin.debug:
+ msg: Warning - Multiple SAP HANA Database (IMDB_SERVER) found, which can result in inaccurate relationship validation!
+ when: __sap_software_download_files | select('match', '^IMDB_SERVER.*') | list | length > 1
+
+
+- name: Relationship Validation - Include tasks for SAP HANA 1.0 relationship validation
+ when: __sap_software_download_files | select('match', '^IMDB_SERVER1.*') | list | length > 0
+ ansible.builtin.include_tasks:
+ file: pre_steps/06_validate_sap_hana_1.yml
+ loop: "{{ __sap_software_download_files | select('match', '^IMDB_SERVER1.*') | list }}"
+ loop_control:
+ loop_var: __sap_software_download_sap_hana
+
+- name: Relationship Validation - Include tasks for SAP HANA 2.0 relationship validation
+ when: __sap_software_download_files | select('match', '^IMDB_SERVER2.*') | list | length > 0
+ ansible.builtin.include_tasks:
+ file: pre_steps/07_validate_sap_hana_2.yml
+ loop: "{{ __sap_software_download_files | select('match', '^IMDB_SERVER2.*') | list }}"
+ loop_control:
+ loop_var: __sap_software_download_sap_hana
diff --git a/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml b/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml
new file mode 100644
index 0000000..93ac892
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/06_validate_sap_hana_1.yml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Relationship Validation - SAP HANA 1.00 - Set HANA variables
+ ansible.builtin.set_fact:
+ # 122 for IMDB_SERVER100_122_35-10009569.SAR
+ __sap_software_download_sap_hana_1_version:
+ "{{ __sap_software_download_sap_hana.split('_')[2] | regex_replace('[^0-9]', '') }}"
+
+ # 35 for IMDB_SERVER100_122_35-10009569.SAR
+ __sap_software_download_sap_hana_1_revision:
+ "{{ __sap_software_download_sap_hana.split('_')[3].split('-')[0] | regex_replace('[^0-9]', '') }}"
+
+
+# Warning conditions:
+# - At least one IMDB_LCAPPS_1 was found
+# - No IMDB_LCAPPS__ was found
+# Examples:
+# - IMDB_SERVER100_122_35-10009569.SAR - Maintenance Revision 122.35 (SPS12) for HANA DB 1.00
+# - IMDB_LCAPPS_122P_3500-20010426.SAR - LCAPPS for HANA 1.00.122.35 Build 100.47 PL 017
+- name: Relationship Validation - SAP HANA 1.00 - IMDB_SERVER and IMDB_LCAPPS
+ ansible.builtin.fail:
+ msg: |
+ Warning: Incompatible SAP HANA component LCAPPS files were found for detected SAP HANA DATABASE 1.0 SPS {{
+ __sap_software_download_sap_hana_1_version[:2] }} Revision {{ __sap_software_download_sap_hana_1_version
+ }}.{{ __sap_software_download_sap_hana_1_revision }}.
+
+ Expected file pattern: IMDB_LCAPPS_{{
+ __sap_software_download_sap_hana_1_version }}*_{{__sap_software_download_sap_hana_1_revision }}*
+ Actual files detected: {{ __sap_software_download_sap_hana_1_lcapps_list | unique | join(', ') }}
+ vars:
+ __sap_software_download_sap_hana_1_lcapps_list:
+ "{{ __sap_software_download_files | select('match', '^IMDB_LCAPPS_1.*') | list }}"
+ __sap_software_download_sap_hana_1_lcapps_list_filtered:
+ "{{ sap_software_download_files | select('match', '^IMDB_LCAPPS_.*'
+ ~ __sap_software_download_sap_hana_1_version ~ '.*_' ~ __sap_software_download_sap_hana_1_revision) | list }}"
+ ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}"
+ when:
+ - __sap_software_download_sap_hana_1_lcapps_list | length > 0
+ - __sap_software_download_sap_hana_1_lcapps_list_filtered | length == 0
+
+
+# Warning conditions:
+# - At least one IMDB_AFL100 was found
+# - No IMDB_AFL100__ was found
+# Examples:
+# - IMDB_SERVER100_122_35-10009569.SAR - Maintenance Revision 122.35 (SPS12) for HANA DB 1.00
+# - IMDB_AFL100_122P_3500-10012328.SAR - SAP HANA AFL 1.0 Revision 122.3500 only for HANA DB 122.35
+- name: Relationship Validation - SAP HANA 1.00 - IMDB_SERVER and IMDB_AFL
+ ansible.builtin.fail:
+ msg: |
+ Warning: Incompatible SAP HANA component AFL files were found for detected SAP HANA DATABASE 1.0 SPS {{
+ __sap_software_download_sap_hana_1_version[:2] }} Revision {{ __sap_software_download_sap_hana_1_version
+ }}.{{ __sap_software_download_sap_hana_1_revision }}.
+
+ Expected file pattern: IMDB_AFL100_{{ __sap_software_download_sap_hana_1_version }}*_{{ __sap_software_download_sap_hana_1_revision }}*
+ Actual files detected: {{ __sap_software_download_sap_hana_1_afl_list | unique | join(', ') }}
+ vars:
+ __sap_software_download_sap_hana_1_afl_list:
+ "{{ __sap_software_download_files | select('match', '^IMDB_AFL100.*') | list }}"
+ __sap_software_download_sap_hana_1_afl_list_filtered:
+ "{{ sap_software_download_files | select('match', '^IMDB_AFL100_.*'
+ ~ __sap_software_download_sap_hana_1_version ~ '.*_' ~ __sap_software_download_sap_hana_1_revision) | list }}"
+ ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}"
+ when:
+ - __sap_software_download_sap_hana_1_afl_list | length > 0
+ - __sap_software_download_sap_hana_1_afl_list_filtered | length == 0
+
+
+# Warning conditions:
+# - At least one IMDB_CLIENT was found
+# - No IMDB_CLIENT1* was found
+# Examples:
+ # - IMDB_SERVER100_122_35-10009569.SAR - Maintenance Revision 122.35 (SPS12) for HANA DB 1.00
+ # - IMDB_CLIENT100_120_140-10009663.SAR - Revision 120 for SAP HANA CLIENT 1.00
+- name: Relationship Validation - SAP HANA 1.00 - IMDB_SERVER and IMDB_CLIENT
+ ansible.builtin.fail:
+ msg: |
+ Warning: Incompatible SAP HANA client files were found for detected SAP HANA DATABASE 1.0.
+
+ Expected file pattern: IMDB_CLIENT100_*
+ Actual files detected: {{ __sap_software_download_sap_hana_client_list | unique | join(', ') }}
+ vars:
+ __sap_software_download_sap_hana_client_list:
+ "{{ __sap_software_download_files | select('match', '^IMDB_CLIENT.*') | list }}"
+ ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}"
+ when:
+ - __sap_software_download_sap_hana_client_list | length > 0
+ - __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT1.*') | length == 0
diff --git a/roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml b/roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml
new file mode 100644
index 0000000..094fca7
--- /dev/null
+++ b/roles/sap_software_download/tasks/pre_steps/07_validate_sap_hana_2.yml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+- name: Relationship Validation - SAP HANA 2.00 - Set HANA variables
+ ansible.builtin.set_fact:
+ # 084 for IMDB_SERVER20_084_0-80002031.SAR
+ __sap_software_download_sap_hana_2_version:
+ "{{ __sap_software_download_sap_hana.split('_')[2] }}"
+
+
+# Warning conditions:
+# - At least one IMDB_LCAPPS_2 was found
+# - No IMDB_LCAPPS_2 was found
+# Examples:
+ # - IMDB_SERVER20_084_0-80002031.SAR - Revision 2.00.084.0 (SPS08) for HANA DB 2.0
+ # - IMDB_LCAPPS_2084_0-20010426.SAR - LCAPPS for HANA 2.0 Rev 84 Build 101.19 PL 007
+- name: Relationship Validation - SAP HANA 2.00 - IMDB_SERVER and IMDB_LCAPPS
+ ansible.builtin.fail:
+ msg: |
+ Warning: Incompatible SAP HANA component LCAPPS files were found for detected SAP HANA DATABASE 2.0 SPS {{
+ __sap_software_download_sap_hana_2_version[:2] }} Revision {{ __sap_software_download_sap_hana_2_version }}.
+
+ Expected file pattern: IMDB_LCAPPS_2{{ __sap_software_download_sap_hana_2_version }}*
+ Actual files detected: {{ __sap_software_download_sap_hana_2_lcapps_list | unique | join(', ') }}
+ vars:
+ __sap_software_download_sap_hana_2_lcapps_list:
+ "{{ __sap_software_download_files | select('match', '^IMDB_LCAPPS_2.*') | list }}"
+ __sap_software_download_sap_hana_2_lcapps_list_filtered:
+ "{{ sap_software_download_files | select('match', '^IMDB_LCAPPS_2' ~ __sap_software_download_sap_hana_2_version) | list }}"
+ ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}"
+ when:
+ - __sap_software_download_sap_hana_2_lcapps_list | length > 0
+ - __sap_software_download_sap_hana_2_lcapps_list_filtered | length == 0
+
+
+# Warning conditions:
+# - At least one IMDB_AFL20 was found
+# - No IMDB_AFL20_ was found
+# Examples:
+ # - IMDB_SERVER20_084_0-80002031.SAR - Revision 2.00.084.0 (SPS08) for HANA DB 2.0
+ # - IMDB_AFL20_084_1-80001894.SAR - SAP HANA AFL Rev 84.1 only for HANA 2.0 Rev 84
+- name: Relationship Validation - SAP HANA 2.00 - IMDB_SERVER and IMDB_AFL
+ ansible.builtin.fail:
+ msg: |
+ Warning: Incompatible SAP HANA component AFL files were found for detected SAP HANA DATABASE 2.0 SPS {{
+ __sap_software_download_sap_hana_2_version[:2] }} Revision {{ __sap_software_download_sap_hana_2_version }}.
+
+ Expected file pattern: IMDB_AFL20_{{ __sap_software_download_sap_hana_2_version }}*
+ Actual files detected: {{ __sap_software_download_sap_hana_2_afl_list | unique | join(', ') }}
+ vars:
+ __sap_software_download_sap_hana_2_afl_list:
+ "{{ __sap_software_download_files | select('match', '^IMDB_AFL20.*') | list }}"
+ __sap_software_download_sap_hana_2_afl_list_filtered:
+ "{{ sap_software_download_files | select('match', '^IMDB_AFL20_.*' ~ __sap_software_download_sap_hana_2_version) | list }}"
+ ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}"
+ when:
+ - __sap_software_download_sap_hana_2_afl_list | length > 0
+ - __sap_software_download_sap_hana_2_afl_list_filtered | length == 0
+
+
+# Warning conditions:
+# - At least one IMDB_CLIENT was found
+# - No IMDB_CLIENT2* was found
+# Examples:
+ # - IMDB_SERVER20_084_0-80002031.SAR - Revision 2.00.084.0 (SPS08) for HANA DB 2.0
+ # - IMDB_CLIENT20_024_21-80002082.SAR - SAP HANA CLIENT Version 2.24
+- name: Relationship Validation - SAP HANA 2.00 - IMDB_SERVER and IMDB_CLIENT
+ ansible.builtin.fail:
+ msg: |
+ Warning: Incompatible SAP HANA client files were found for detected SAP HANA DATABASE 2.0.
+
+ Expected file pattern: IMDB_CLIENT20_*
+ Actual files detected: {{ __sap_software_download_sap_hana_client_list | unique | join(', ') }}
+ vars:
+ __sap_software_download_sap_hana_client_list:
+ "{{ __sap_software_download_files | select('match', '^IMDB_CLIENT.*') | list }}"
+ ignore_errors: "{{ sap_software_download_ignore_relationship_warning | d(false) }}"
+ when:
+ - __sap_software_download_sap_hana_client_list | length > 0
+ - __sap_software_download_sap_hana_client_list | select('match', '^IMDB_CLIENT2.*') | length == 0
diff --git a/roles/sap_software_download/vars/RedHat_10.yml b/roles/sap_software_download/vars/RedHat_10.yml
new file mode 100644
index 0000000..13cb27b
--- /dev/null
+++ b/roles/sap_software_download/vars/RedHat_10.yml
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# Variables specific to following versions:
+# - Red Hat Linux Enterprise Server 10
+
+# Set which Python version will be used on destination node.
+# This is python executable name, which can differ from python package name.
+__sap_software_download_python_interpreter: 'python3.12'
+
+# Set which Python package will be installed on destination node.
+__sap_software_download_python_package: 'python3.12'
+
+# The list of required Python Modules in packages
+# This is required in order to avoid externally-managed-environment error.
+__sap_software_download_python_module_packages:
+ - python3.12-wheel
+ - python3.12-urllib3
+ - python3.12-requests
+ - python3.12-beautifulsoup4
+ - python3.12-lxml
diff --git a/roles/sap_software_download/vars/RedHat_8.yml b/roles/sap_software_download/vars/RedHat_8.yml
new file mode 100644
index 0000000..453b5ce
--- /dev/null
+++ b/roles/sap_software_download/vars/RedHat_8.yml
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# Variables specific to following versions:
+# - Red Hat Linux Enterprise Server 8
+
+# Set which Python version will be used on destination node.
+# This is python executable name, which can differ from python package name.
+__sap_software_download_python_interpreter: 'python3.9'
+
+# Set which Python package will be installed on destination node.
+__sap_software_download_python_package: 'python39'
+
+# The list of required Python Modules in packages
+# This is required in order to avoid externally-managed-environment error.
+__sap_software_download_python_module_packages:
+ - python39-wheel
+ - python39-urllib3
+ - python39-requests
+ - python39-beautifulsoup4
+ - python39-lxml
diff --git a/roles/sap_software_download/vars/RedHat_9.yml b/roles/sap_software_download/vars/RedHat_9.yml
new file mode 100644
index 0000000..f472adf
--- /dev/null
+++ b/roles/sap_software_download/vars/RedHat_9.yml
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# Variables specific to following versions:
+# - Red Hat Linux Enterprise Server 9
+
+# Set which Python version will be used on destination node.
+# This is python executable name, which can differ from python package name.
+__sap_software_download_python_interpreter: 'python3.9'
+
+# Set which Python package will be installed on destination node.
+__sap_software_download_python_package: 'python3.9'
+
+# The list of required Python Modules in packages
+# This is required in order to avoid externally-managed-environment error.
+__sap_software_download_python_module_packages:
+ - python3.9-wheel
+ - python3.9-urllib3
+ - python3.9-requests
+ - python3.9-beautifulsoup4
+ - python3.9-lxml
diff --git a/roles/sap_software_download/vars/Suse.yml b/roles/sap_software_download/vars/Suse.yml
new file mode 100644
index 0000000..f540820
--- /dev/null
+++ b/roles/sap_software_download/vars/Suse.yml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# Variables specific to following versions:
+# - SUSE Linux Enterprise Server 15
+# - SUSE Linux Enterprise Server 16
+
+# NOTE: SLES 15 SP5 introduced Python 3.11.
+
+# Set which Python version will be used on destination node.
+# This is python executable name, which can differ from python package name.
+__sap_software_download_python_interpreter: >-
+ {%- if ansible_distribution_major_version == '15' and ansible_distribution_version.split('.')[1] | int < 5 -%}
+ python3
+ {%- else -%}
+ python3.11
+ {%- endif -%}
+
+# Set which Python package will be installed on destination node.
+__sap_software_download_python_package: >-
+ {%- if ansible_distribution_major_version == '15' and ansible_distribution_version.split('.')[1] | int < 5 -%}
+ python3
+ {%- else -%}
+ python311
+ {%- endif -%}
+
+# The list of required Python Modules in packages
+# This is required in order to avoid externally-managed-environment error.
+__sap_software_download_python_module_packages: >-
+ {%- if ansible_distribution_major_version == '15' and ansible_distribution_version.split('.')[1] | int < 5 -%}
+ [
+ "python3-wheel",
+ "python3-urllib3",
+ "python3-requests",
+ "python3-beautifulsoup4",
+ "python3-lxml"
+ ]
+ {%- else -%}
+ [
+ "python311-wheel",
+ "python311-urllib3",
+ "python311-requests",
+ "python311-beautifulsoup4",
+ "python311-lxml"
+ ]
+ {%- endif -%}
diff --git a/roles/sap_software_download/vars/main.yml b/roles/sap_software_download/vars/main.yml
new file mode 100644
index 0000000..e40f28e
--- /dev/null
+++ b/roles/sap_software_download/vars/main.yml
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: Apache-2.0
+---
+
+# The list of required Python Modules for download module
+__sap_software_download_python_modules:
+ - wheel
+ - urllib3
+ - requests
+ - beautifulsoup4
+ - lxml
+
+# The list of required Python Modules in packages
+# This is required in order to avoid externally-managed-environment error.
+# Specific packages are available in OS specific var files
+__sap_software_download_python_module_packages:
+ - python3-wheel
+ - python3-urllib3
+ - python3-requests
+ - python3-beautifulsoup4
+ - python3-lxml