deploy/ansible/roles-sap/3.3-bom-processing/tasks/bom_processor.yaml (156 lines of code) (raw):

# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. --- # /*---------------------------------------------------------------------------8 # | | # | BOM Validation role | # | | # | Assumptions | # | target_media_location exists on disk | # | | # | Inputs: | # | target_media_location Default {{ target_media_location }}| # | download_directory | # | bom_name | # | sapbits_location_base_path | # | sapbits_bom_files | # | sapbits_sas_token | # | sapbits_access_key | # | S_user | # | S_password: | # | download_directory: Default /mnt/downloads | # | | # |Locals: | # | _bom | # | item | # | result | # | | # | BOM Fields: | # | download | # | archive | # | permissions | # | | # | | # | Steps: | # | 01) Register BOM | # | 02) Create static download directories | # | 03) Create dynamic extract directories | # | 04) Download media from bom | # | 05) Extract files - SAPCAR | # | 06) Extract files - UNRAR/UNAR | # | 07) Extract files - UNZIP | # | 08) Purge BOM file from Ansible Controller - TBD | # | # +------------------------------------4--------------------------------------*/ - name: "3.3 BoM Processing: - Register BoM" ansible.builtin.include_role: name: roles-sap/3.3.1-bom-utility tasks_from: bom-register vars: inventory_dir: "{{ download_directory }}/bom" task_prefix: "BOM Processing: " # 02) Create static download directories - name: "3.3 BoM Processing: - Create SAP download directories" ansible.builtin.file: path: "{{ item.path }}" state: directory mode: 0755 loop: - path: "{{ target_media_location }}/tmp" - path: "{{ target_media_location }}/downloads" - path: "{{ target_media_location }}/download_basket" # 03) Create dynamic extract directories - name: "3.3 BoM Processing: - Create BOM directories" ansible.builtin.file: path: "{{ target_media_location }}/{{ item.extractDir }}" state: directory mode: 0755 loop: "{{ bom.materials.media | flatten(levels=1) }}" when: not ((item.extractDir is undefined) or (item.extractDir == '')) # Download Files # ------------------<DEBUGGING>------------------- - name: "3.3 BoM Processing: - Check if dynamic BOM download was performed successfully." block: - name: "3.3 BoM Processing: - Check if the item has dynamic property" ansible.builtin.fail: msg: "INSTALL:0023:Error while downloading BOM contents. Invalid BOM structure detected." when: - item.download is undefined or item.download - item.dynamic is defined or item.archive is undefined loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - is_executed_by_acss - name: "3.3 BoM Processing: - List files" ansible.builtin.debug: msg: - "URL : {{ sapbits_location_base_path }}/{{ sapbits_bom_files }}/archives/{{ item.archive }}\ {% if sapbits_sas_token is not undefined %}?{{ sapbits_sas_token }}{% endif %}" - "DEST: {{ target_media_location }}/{% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" - "MODE: {% if item.permissions is undefined %}0644{% else %}{{ item.permissions }}{% endif %}" verbosity: 2 loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - item.download is undefined or item.download # ------------------</DEBUGGING>------------------ - name: "3.3 BoM Processing: - Set Python version {{ distribution_id }}" ansible.builtin.set_fact: python_version: 'python2' when: (ansible_distribution | lower ~ ansible_distribution_major_version) in ['sles_sap12'] # 04) Download media from bom # Loop through BOM media files and download to correct location # validate checksum while downloading the files. # For checksum validation, if we need to worry about portability, only the # sha1 algorithm is available on all platforms and python versions. # also, when we pass checksum if the file exists in destination it will be # deleted if the checksum does not match and will be downloaded from URL - name: "3.3 BoM Processing: - Creates temporary download directory" become: true ansible.builtin.file: path: "{{ tmp_directory }}/tmp" state: directory mode: 0775 - name: "3.3 BoM Processing: - Download Files on {{ distribution_id }}" ansible.builtin.get_url: url: "{{ sapbits_location_base_path }}/{{ sapbits_bom_files }}/archives/{{ item.archive | string | trim }}\ {% if sapbits_sas_token is defined %}?{{ sapbits_sas_token }}{% endif %}" dest: "{{ target_media_location }}/{% if item.path is undefined %}downloads{% else %}{{ item.path }}{% endif %}/\ {% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" mode: "{% if item.permissions is undefined %}0644{% else %}{{ item.permissions }}{% endif %}" tmp_dest: "{{ target_media_location }}/tmp" checksum: "{% if item.checksum is defined %}{% if item.checksum | trim | length > 1 %}sha256:{{ item.checksum | upper }}{% endif %}{% endif %}" validate_certs: false register: result until: result is succeeded retries: 2 loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - item.download is undefined or item.download - item.archive is defined - item.archive | trim | length > 1 - distribution_id in ['suse15', 'redhat8', 'redhat9', 'sles_sap15' ] delay: 5 vars: ansible_python_interpreter: "{{ python_version }}" - name: "3.3 BoM Processing: - Download Files on {{ distribution_id }}" ansible.builtin.get_url: url: "{{ sapbits_location_base_path }}/{{ sapbits_bom_files }}/archives/{{ item.archive | string | trim }}\ {% if sapbits_sas_token is not undefined %}?{{ sapbits_sas_token }}{% endif %}" dest: "{{ target_media_location }}/{% if item.path is undefined %}downloads{% else %}{{ item.path }}{% endif %}/\ {% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" mode: "{% if item.permissions is undefined %}0644{% else %}{{ item.permissions }}{% endif %}" checksum: "{% if item.checksum is defined %}{% if item.checksum | trim | length > 1 %}sha256:{{ item.checksum | upper }}{% endif %}{% endif %}" tmp_dest: "{{ target_media_location }}/tmp" validate_certs: false register: result until: result is succeeded retries: 2 delay: 5 loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - item.download is undefined or item.download - distribution_id != 'suse15' - distribution_id != 'sles_sap15' - distribution_id != 'redhat8' - distribution_id != 'redhat9' - name: "3.3 BoM Processing: - Download result" ansible.builtin.debug: var: result verbosity: 2 # 05) Extract files - SAPCAR - name: "3.3 BoM Processing: - Extract File, SAPCAR" ansible.builtin.command: "{{ target_media_location }}/downloads/SAPCAR -manifest SIGNATURE.SMF \ -xf {{ target_media_location }}/{% if item.path is undefined %}downloads{% else %}{{ item.path }}{% endif %}/\ {% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" args: chdir: "{{ target_media_location }}/{{ item.extractDir }}" creates: "{{ target_media_location }}/{{ item.extractDir }}/ \ {% if item.creates is defined %}{{ item.creates }}{% else %}NOT_DEFINED{% endif %}" loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - item.extract is not undefined - item.extract - ( item.filename is undefined and (item.archive | regex_search('[^.]+(?=\\.*$)') | upper=="SAR") ) or ( item.filename is defined and (item.filename | regex_search('[^.]+(?=\\.*$)') | upper=="SAR") ) # 06) Extract files - UNRAR # Note: SAP has started to distribute Schema files packed as RAR files or spanned solid archives with self extracting EXE files against Zip files as before. # This requires WinRAR or opensource RAR extractor. # RHEL does not distibuted unrar anymore https://access.redhat.com/solutions/28959 # RHEL recommends using unarchiver ( alias : unar ) in EPEL repository from Fedora as unrar from https://www.rarlab.com does not cplies with OpenSource Licenses. # This also presents another problem as the archive files will get unpacked into /usr/sap/install/CD_EXPORT/<package_ID>/<files> and will cause setup to fail. # This issue is now being handled by process_exe_archives.yaml # - name: "3.3 BoM Processing: - Extract File, UNRAR" # ansible.builtin.command: "{% if (ansible_os_family | upper) == 'REDHAT' %}unar -s -D{% else %}unrar x{% endif %} {{ target_media_location }}/{% if item.path is undefined %}downloads{% else %}{{ item.path }}{% endif %}/{% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" # args: # chdir: "{{ target_media_location }}/{{ item.extractDir }}" # creates: "{{ target_media_location }}/{{ item.extractDir }}/\ # {% if item.creates is defined %}{{ item.creates }}{% else %}NOT_DEFINED{% endif %}" # loop: "{{ bom.materials.media | flatten(levels=1) }}" # when: # - item.extract is not undefined # - item.extract # - ( item.filename is undefined and (item.archive |regex_search('[^.]+(?=\\.*$)')|upper=="RAR") ) or # ( item.filename is defined and (item.filename|regex_search('[^.]+(?=\\.*$)')|upper=="RAR") ) or # ( item.filename is undefined and (item.archive |regex_search('[^.]+(?=\\.*$)')|upper=="EXE") ) or # ( item.filename is defined and (item.filename|regex_search('[^.]+(?=\\.*$)')|upper=="EXE") ) # 07) Extract files - UNZIP - name: "3.3 BoM Processing: - Extract File, UNZIP" ansible.builtin.unarchive: src: "{{ target_media_location }}/{% if item.path is undefined %}downloads{% else %}{{ item.path }}{% endif %}/\ {% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" dest: "{{ target_media_location }}/{{ item.extractDir }}" remote_src: true creates: "{{ target_media_location }}/{{ item.extractDir }}/{% if item.creates is defined %}\ {{ item.creates }}{% else %}NOT_DEFINED{% endif %}" loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - item.extract is not undefined - item.extract - ( item.filename is undefined and (item.archive |regex_search('[^.]+(?=\\.*$)')|upper=="ZIP") ) or ( item.filename is defined and (item.filename|regex_search('[^.]+(?=\\.*$)')|upper=="ZIP") ) or ( item.filename is undefined and (item.archive |regex_search('[^.]+(?=\\.*$)')|upper=="TGZ") ) or ( item.filename is defined and (item.filename|regex_search('[^.]+(?=\\.*$)')|upper=="TGZ") ) # 07) Extract files - EXE # - name: "3.3 BoM Processing: - Extract File, UNRAR" # ansible.builtin.command: unrar x "{{ target_media_location }}/{% if item.path is undefined %}downloads{% else %}{{ item.path }}{% endif %}/\ # {% if item.filename is undefined %}{{ item.archive }}{% else %}{{ item.filename }}{% endif %}" # args: # chdir: "{{ target_media_location }}/{{ item.extractDir }}" # creates: "{{ target_media_location }}/{{ item.extractDir }}/\ # {% if item.creates is defined %}{{ item.creates }}{% else %}NOT_DEFINED{% endif %}" # loop: "{{ bom.materials.media|flatten(levels=1) }}" # when: # - item.extract is not undefined # - item.extract # - ( item.filename is undefined and (item.archive |regex_search('[^.]+(?=\\.*$)')|upper=="EXE") ) or # ( item.filename is defined and (item.filename|regex_search('[^.]+(?=\\.*$)')|upper=="EXE") ) # 08) Extract files - EXE - name: "3.3 BoM Processing: - Extract File, EXE" ansible.builtin.include_tasks: "process_exe_archives.yaml" loop: "{{ bom.materials.media | flatten(levels=1) }}" when: - item.extract is defined - item.extract - ( item.filename is undefined and (item.archive |regex_search('[^.]+(?=\\.*$)')|upper=="EXE") ) or ( item.filename is defined and (item.filename|regex_search('[^.]+(?=\\.*$)')|upper=="EXE") ) # -------------------------------------+---------------------------------------8 # # Description: Process BOM dependencies. # Call BOM processor, passing dependent BOM names. # # bom_processor.yaml # Gather Dependencies - name: "3.3 BoM Processing: - Gather all dependencies" ansible.builtin.set_fact: current_dependencies: "{{ bom.materials.dependencies | default([]) }}" # Process Dependencies - name: "3.3 BoM Processing: - Process each dependency" ansible.builtin.include_tasks: "bom_processor.yaml" vars: bom_name: "{{ current_dep.name }}" dependencies_processed: true loop: "{{ current_dependencies | flatten(levels=1) }}" loop_control: loop_var: current_dep when: - current_dependencies | length > 0 - dependencies_processed is not defined # -------------------------------------+---------------------------------------8 # # 08) Purge BOM file from Ansible Controller # - name: "Ensure {{ bom_name }} is absent" # ansible.builtin.file: # path: "{{ inventory_dir }}/{{ bom_name }}.yaml" # state: absent # delegate_to: localhost # -------------------------------------+---------------------------------------8 ...