# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# /*---------------------------------------------------------------------------8
# |                                                                            |
# |                SAP: Register BOM                                           |
# |         SAP DBLOAD: deploy DBLOAD Parameter file install template          |
# |         SAP DBLOAD: Install                                                |
# |                                                                            |
# +------------------------------------4--------------------------------------*/

---

- name:                                "DBLoad: - Set dbload facts"
  ansible.builtin.set_fact:
    sap_inifile:                       "{{ bom_base_name }}-dbload-{{ sid_to_be_deployed.sid | lower }}-{{ ansible_hostname }}.params"
    sap_inifile_template:              "dbload-inifile-param.j2"
    dir_params:                        "{{ tmp_directory }}/.params"
    pas_virtual_hostname:              "{{ custom_pas_virtual_hostname | default(virtual_host, true) }}"
- name:                                "DBLoad: -  Create directories"
  ansible.builtin.file:
    path:                              "{{ item.path }}"
    state:                             directory
    mode:                              '{{ item.mode }}'
  loop:
    - { mode: '0755', path: '{{ dir_params }}' }
    - { mode: '0755', path: '{{ tmp_directory }}/{{ sid_to_be_deployed.sid | upper }}' }
    - { mode: '0755', path: '/etc/sap_deployment_automation/{{ sap_sid | upper }}' }

- name:                                "DBLoad: - reset"
  ansible.builtin.file:
    path:                              "/etc/sap_deployment_automation/{{ sid_to_be_deployed.sid | upper }}/sap_deployment_dbload.txt"
    state:                             absent
  when:                                reinstall

# Returns bom object
- name:                                "DBLoad: - Register BoM"
  ansible.builtin.include_role:
    name:                              roles-sap/3.3.1-bom-utility
    tasks_from:                        bom-register
  vars:
    bom_name:                          "{{ bom_base_name }}"
    task_prefix:                       "DBLoad: "
    sa_enabled:                        true

- name:                                "DBLoad: Default instance type"
  ansible.builtin.set_fact:
    instance_type:                     "ASCS"
  when:                                bom.InstanceType is not defined

- name:                                "DBLoad: register instance type"
  ansible.builtin.set_fact:
    instance_type:  >-
                                       {%- set _instance_type = 'ASCS' -%}
                                       {%- if bom.InstanceType == 'JAVA' -%}
                                       {%- set _instance_type = 'SCS' -%}
                                       {%- elif bom.InstanceType == 'ABAP' -%}
                                       {%- set _instance_type = 'ASCS' -%}
                                       {%- else -%}
                                       {%- set _instance_type = 'ASCS' -%}
                                       {%- endif -%}
                                       {{- _instance_type -}}
    public:                            true
  when:                                bom.InstanceType is defined

- name:                                "DBLoad: register application type"
  ansible.builtin.set_fact:
    application_type:                  "{% if instance_type == 'SCS' %}JAVA{% else %}ABAP{% endif %}"

- name:                                "DBLoad: -  Set the product ID"
  ansible.builtin.set_fact:
    product_id:                        "{{ bom.product_ids.dbl }}"

- name:                                "DBLoad: - Set dbload path"
  ansible.builtin.set_fact:
    db_load_path:                      "{{ tmp_directory }}/{{ sid_to_be_deployed.sid | upper }}/sapinst_instdir/{{ product_id.replace('.', '/').replace('/' + application_type, '').split(':')[1] }}/INSTALL/DISTRIBUTED/{{ application_type }}/DB"

- name:                                "DBLoad: Check if DBLoad has been tried on this server"
  ansible.builtin.stat:
    path:                              "{{ db_load_path }}"
  register:                            dbload_performed

- name:                                "DBLoad Install: Set Schema Name"
  when:
    - platform == "HANA"
  ansible.builtin.include_role:
    name:                              "roles-db/4.0.4-hdb-schema"
    public:                            true

- name:                                "DBLoad: Check if install is performed"
  block:
    - name:                            "DBLoad: Find the installationSuccesfullyFinished.dat (SAPINST)"
      ansible.builtin.find:
        paths:                         "{{ db_load_path }}"
        file_type:                     file
        patterns:                      'installationSuccesfullyFinished.dat'
        recurse:                       false
      register:                        dbload_performed_according_to_sapinst

    - name:                            "DBLoad: show"
      ansible.builtin.debug:
        var:                           dbload_performed_according_to_sapinst
        verbosity:                     2
      when:                            dbload_performed.stat.exists

    - name:                            "DBLoad: flag"
      ansible.builtin.file:
        path:                          "/etc/sap_deployment_automation/{{ sid_to_be_deployed.sid | upper }}/sap_deployment_dbload.txt"
        state:                          touch
        mode:                          0755
      when:
        - dbload_performed_according_to_sapinst is defined
        - dbload_performed_according_to_sapinst.matched == 1
  when:
    - dbload_performed.stat.exists

- name:                                "DBLoad: - check if DBLoad is performed for {{ sid_to_be_deployed.sid | upper }}"
  ansible.builtin.stat:
    path:                              "/etc/sap_deployment_automation/{{ sid_to_be_deployed.sid | upper }}/sap_deployment_dbload.txt"
  register:                            dbload_installed

- name:                                "DBLoad: register variables"
  ansible.builtin.set_fact:
    dbl_bom_instance_type:             "{% if bom.InstanceType is defined %}{{ bom.InstanceType }}{% else %}ABAP{% endif %}"
    public:                            true

# *====================================4=======================================8
#   SAP DBLOAD: Install
# 2230669 - System Provisioning Using a Parameter Input File
#
# *====================================4=======================================8

- name:                                "DBLoad: - Run"
  block:

    - name:                            "DBLoad: -  Set the SCS Server name list"
      ansible.builtin.set_fact:
        scs_server_temp:               "{{ scs_server_temp | default([]) + [item] }}"
      with_items:
        - "{{ query('inventory_hostnames', '{{ sap_sid | upper }}_SCS') }}"
        - "{{ query('inventory_hostnames', '{{ sap_sid | upper }}_DB') }}"

    - name:                            "DBLoad: -  Set the DB Server name list"
      ansible.builtin.set_fact:
        db_server_temp:                "{{ db_server_temp | default([]) + [item] }}"
      with_items:
        - "{{ query('inventory_hostnames', '{{ sid_to_be_deployed.sid | upper }}_DB') }}"

    - name:                            "Backward Compatibility - Check required Database HA variables"
      ansible.builtin.set_fact:
        database_high_availability:    "{{ db_high_availability | default(false) }}"
      when:
        - db_high_availability is defined
        - database_high_availability is not defined

    - name:                            "DBLoad: Calculate virtual host name when running scale out"
      ansible.builtin.set_fact:
        db_virtualhost_temp:  >-
                                       {%- set _host_name = hostvars[db_server_temp | first]['virtual_host'] -%}
                                       {%- if database_scale_out and not database_high_availability -%}
                                       {%-  set _host_name = sap_sid | lower ~ db_sid | lower ~ 'db' ~ db_instance_number ~ 'so' -%}
                                       {%- endif -%}
                                       {{- _host_name -}}

    - name:                            "DBLoad: Display temporary database virtual host name"
      ansible.builtin.debug:
        msg:                           "DB Virtual Host: {{ db_virtualhost_temp }}"

    - name:                            "DBLoad: -  Set the server facts"
      ansible.builtin.set_fact:
        scs_server:                    "{% if scs_high_availability %}{{ sid_to_be_deployed.sid | lower }}scs{{ scs_instance_number }}cl1{% else %}{{ hostvars[scs_server_temp | first]['virtual_host'] }}{% endif %}"
        db_virtual_hostname:           "{{ db_virtualhost_temp | default(hostvars[db_server_temp | first]['virtual_host'], true) }}"

    - name:                            "DBLoad: Display database virtual host name"
      ansible.builtin.debug:
        msg:                           "DB Virtual Host: {{ db_virtual_hostname }}"

    - name:                            "DBLoad: check media exists"
      ansible.builtin.stat:
        path:                          "{{ target_media_location }}/SWPM/sapinst"
      register:                        sapinst_found

    - name:                            "ErrorHandling"
      ansible.builtin.fail:
        msg:                           "INSTALL:0005:Unable to find sapinst, please check that the installation media is mounted"
      when: not sapinst_found.stat.exists

    - name:                            "DBLoad: - DB Server name list"
      ansible.builtin.set_fact:
        db_server:                     "{{ db_server | default([]) + [item] }}"
      with_items:
        - "{{ query('inventory_hostnames', '{{ sap_sid | upper }}_DB') }}"

    - name:                            "DBLoad: - Check if the backup disk exists on DB Server"
      ansible.builtin.set_fact:
        backupdisks_count: >-
                                       {{ disks | selectattr('host', 'defined') |
                                           selectattr('host', 'equalto', db_server[0]) |
                                           selectattr('type', 'equalto', 'backup') |
                                           map(attribute='type') | sort | unique |
                                           list | length | int }}

    - name:                            "DBLoad: -  Set the hana backup facts"
      ansible.builtin.set_fact:
        backup_path:                   "{% if (backupdisks_count | int) == 0 %}/hana/data/backup{% else %}{{ hana_backup_path }}{% endif %}"

    - name:                            "Hana backup directory"
      ansible.builtin.debug:
        msg:
          - "DB Server:                {{ db_server[0] }}"
          - "Backup disk count:        {{ backupdisks_count | int }}"
          - "HANA Backup path:         {{ hana_backup_path }}"
          - "Backup path:              {{ backup_path }}"


    - name:                            "DBLoad: - Template processing - Create ini file {{ sap_inifile }} from {{ sap_inifile_template }}"
      ansible.builtin.template:
        src:                           "{{ sap_inifile_template }}"
        dest:                          "{{ dir_params }}/{{ sap_inifile }}"
        mode:                          0644
        force:                         true
      vars:
        hana_backup_path:              "{{ backup_path }}"
        hana_schema:                   "{% if schema_name is defined %}{{ schema_name }}{% else %}omit{% endif %}"
        param_directory:               "{{ dir_params }}"
        sap_db_hostname:               "{{ custom_db_virtual_hostname | default(db_virtual_hostname, true) }}"
        sap_profile_dir:               "/sapmnt/{{ sid_to_be_deployed.sid | upper }}/profile"
        sap_scs_hostname:              "{{ custom_scs_virtual_hostname | default(scs_server, true) }}"
        sap_sid:                       "{{ sid_to_be_deployed.sid }}"
        sidadm_uid:                    "{{ sid_to_be_deployed.sidadm_uid }}"

    - name:                            "DBLoad: Get ini file"
      ansible.builtin.slurp:
        src:                           "{{ dir_params }}/{{ sap_inifile }}"
      register:                        profilefile

    - name:                            "DBLoad: Inifile"
      ansible.builtin.debug:
        msg:                           "{{ profilefile['content'] | b64decode }}"
        verbosity:                     4


    - name:                            "DBLoad: install variables"
      ansible.builtin.debug:
        msg:
          - "INSTALLED:  {{ dbload_installed.stat.exists }}"
          - "INIFILE:    {{ sap_inifile }}"
          - "PRODUCT ID: {{ product_id }}"
          - "INSTANCE:   {{ db_instance_number }}"
          - "SCSHOST:    {{ custom_scs_virtual_hostname | default(scs_server, true) }}"
          - "DBHOST:     {{ custom_db_virtual_hostname | default(db_virtual_hostname, true) }}"
          - "SID:        {{ sid_to_be_deployed.sid | upper }}"

        # Import this task only if the tier is ora.
    - name:                            "DBLoad: import oracle tasks"
      ansible.builtin.import_tasks:    oracle.yaml
      when:
        - node_tier == "oracle-multi-sid"

    - name:                            "Create temp directory for sid"
      ansible.builtin.file:
        path:                          "{{ tmp_directory }}/{{ sid_to_be_deployed.sid | upper }}"
        state:                         directory
        mode:                          0755

    - name:                            "DBLoad: progress"
      ansible.builtin.debug:
        msg:                           "Starting DBLoad for {{ sid_to_be_deployed.sid | upper }}. Please wait"

    - name:                            "DBLoad: - run SAPInst"
      ansible.builtin.shell: |
                                       umask {{ custom_umask | default('022') }} ;
                                       ./sapinst SAPINST_INPUT_PARAMETERS_URL={{ dir_params }}/{{ sap_inifile }} \
                                                 SAPINST_EXECUTE_PRODUCT_ID={{ product_id }}                     \
                                                 SAPINST_SKIP_DIALOGS=true                                       \
                                                 SAPINST_START_GUISERVER=false
      args:
        chdir:                         "{{ target_media_location }}/SWPM"
        creates:                       "/etc/sap_deployment_automation/{{ sid_to_be_deployed.sid | upper }}/sap_deployment_dbload.txt"
      environment:
        TMPDIR:                        "{{ tmp_directory }}/{{ sid_to_be_deployed.sid | upper }}"
        SAPSYSTEMNAME:                 "{{ sid_to_be_deployed.sid | upper }}"
      register:                        dbload_results
      async:                           7200
      poll:                            0

    - name:                            "DBLoad Install -Wait for asynchronous job to end and rescue"
      block:
        - name:                        "DBLoad Install -Wait for asynchronous job to end"
          ansible.builtin.async_status:
            jid:                       "{{ dbload_results.ansible_job_id }}"
          register:                    job_result
          until:                       job_result.finished
          retries:                     "{% if dbload_retry_count is defined %}{{ dbload_retry_count }}{% else %}120{% endif %}"
          delay:                       60
          when:                        dbload_results.ansible_job_id is defined

      rescue:
        - name:                        "Capturing the modified message for message server being offline"
          ansible.builtin.set_fact:
            modified_error_message:    "{{ job_result.stdout | try_get_error_code(task_tag='dbload', failure='messageserver_offline') }}"

        - name:                        "Capturing the modified message for database being offline"
          ansible.builtin.set_fact:
            modified_error_message:    "{{ modified_error_message | try_get_error_code(task_tag='dbload', failure='db_offline') }}"

        - name:                        "Debug: Modified error message"
          ansible.builtin.debug:
            msg:                       "Modified error message: {{ modified_error_message }}"
          when:                         modified_error_message != job_result.stdout

        - name:                        "Error Handling: Fail with the modified error message "
          ansible.builtin.fail:
            msg:                       "{{ modified_error_message }}"

    - name:                            "DBLoad: Results"
      ansible.builtin.debug:
        msg:
          - "DBLoad : {{ dbload_results }}"
          - "Job result: {{ job_result }}"

    - name:                            "DBLoad: Results"
      ansible.builtin.debug:
        var:                           dbload_results
      when:
        - job_result is defined
        - job_result.rc > 0

    - name:                            "DBLoad: Cleanup ini file {{ ansible_hostname }}"
      ansible.builtin.file:
        path:                          "{{ dir_params }}/{{ sap_inifile }}"
        state:                         absent

    - name:                            "DBLoad: - set completion flag"
      ansible.builtin.file:
        path:                          "/etc/sap_deployment_automation/{{ sid_to_be_deployed.sid | upper }}/sap_deployment_dbload.txt"
        state:                         touch
        mode:                          0755
      when:
        - job_result.rc is defined
        - job_result.rc == 0

    - name:                            "DBLoad: results"
      ansible.builtin.debug:
        msg:                           "DBLoad succeeded"
      when:
        - job_result.rc is defined
        - job_result.rc == 0

    # # Import this task only if the tier is ora.
    # - import_tasks:                    "oracle-postprocessing.yaml"
    #   when:
    #     - node_tier in ["oracle","oracle-asm"]

    - name:                            "DBLoad Install: Set Schema Name"
      when:
        - platform == "HANA"
      ansible.builtin.include_role:
        name:                          "roles-db/4.0.4-hdb-schema"
        public:                        true

    - name:                            "Backward Compatibility - Check required Database HA variables"
      ansible.builtin.set_fact:
        database_high_availability:    "{{ db_high_availability | default(false) }}"
      when:
        - db_high_availability is defined
        - database_high_availability is not defined

    - name:                            "DBLoad: Get hdbuserstore path"
      become:                          true
      become_user:                     "root"
      when:
        - database_high_availability
        - platform == 'HANA'
      ansible.builtin.find:
        paths:                         "/usr/sap/{{ sid_to_be_deployed.sid | upper }}/SYS/exe/uc/linuxx86_64/hdbclient/,/usr/sap/{{ sid_to_be_deployed.sid }}/hdbclient"
        file_type:                     file
        patterns:                      'hdbuserstore'
        recurse:                       true
      register:                        hdbuserstore_file
      environment:
        SAPSYSTEMNAME:                 "{{ sid_to_be_deployed.sid | upper }}"
      vars:
        allow_world_readable_tmpfiles:     true

    - name:                            "DBLoad: Set hdbuserstore path"
      when:
        - database_high_availability
        - platform == 'HANA'
        - hdbuserstore_file is defined
        - hdbuserstore_file | length > 0
      ansible.builtin.set_fact:
        hdbuserstore_path:             "{{ hdbuserstore_file.files[0].path }}"
        db_lb_virtual_host:            "{{ sid_to_be_deployed.sid | lower }}{{ db_sid | lower }}db{{ db_instance_number }}cl.{{ sap_fqdn }}"

    - name:                            "DBLoad: show hdbuserstore path"
      when:
        - database_high_availability
        - platform == 'HANA'
      ansible.builtin.debug:
        var:                           hdbuserstore_path
        verbosity:                     2

    - name:                            "DBLoad: Set DB Virtual Host name ({{ custom_db_virtual_hostname | default(db_lb_virtual_host, true) }})"
      become:                          true
      become_user:                     "{{ sid_to_be_deployed.sid | lower }}adm"
      when:
        - database_high_availability
        - platform == 'HANA'
        - hdbuserstore_path is defined
      ansible.builtin.shell: |
                                       {{ hdbuserstore_path }} -H {{ pas_virtual_hostname }} SET DEFAULT {{ custom_db_virtual_hostname | default(db_lb_virtual_host, true) }}:3{{ db_instance_number }}13@{{ db_sid | upper }} {{ schema_name }} {{ main_password }}
      environment:
        SAPSYSTEMNAME:                 "{{ sid_to_be_deployed.sid | upper }}"
        TMPDIR:                        "{{ hdbuserstore_path }}"
        ssfs_connect:                  "1"
      register:                        hdbuserstore
      vars:
        allow_world_readable_tmpfiles: true

    - name:                            "DBLoad: Set DB Virtual Host name ({{ custom_db_virtual_hostname | default(db_lb_virtual_host, true) }})"
      become:                          true
      become_user:                     "root"
      when:
        - database_high_availability
        - platform == 'HANA'
        - hdbuserstore_path is defined
      ansible.builtin.shell: |
                                       {{ hdbuserstore_path }} SET DEFAULT {{ custom_db_virtual_hostname | default(db_lb_virtual_host, true) }}:3{{ db_instance_number }}13@{{ db_sid | upper }} {{ schema_name }} {{ main_password }}
      environment:
        SAPSYSTEMNAME:                 "{{ sid_to_be_deployed.sid | upper }}"
        TMPDIR:                        "{{ hdbuserstore_path }}"
        ssfs_connect:                  "1"
      register:                        hdbuserstore
      vars:
        allow_world_readable_tmpfiles: true

  when:
    - not dbload_installed.stat.exists

# Import this task only if the tier is ora.
- name:                                "Oracle post processing"
  ansible.builtin.import_tasks:        "oracle-postprocessing.yaml"
  when:
    - node_tier in ["oracle","oracle-asm"]

- name:                                "DBLoad: - status"
  when: dbload_installed.stat.exists
  block:
    - name:                            "DBLoad: - status"
      ansible.builtin.debug:
        msg:                           "DBLoad is already performed ({{ sid_to_be_deployed.sid | upper }})"

    - name:                            "DBLoad: - return value"
      ansible.builtin.set_fact:
        dbload_already_performed:      true

    - name:                            "Backward Compatibility - Check required Database HA variables"
      ansible.builtin.set_fact:
        database_high_availability:    "{{ db_high_availability | default(false) }}"
      when:
        - db_high_availability is defined
        - database_high_availability is not defined

    - name:                            "DBLoad: Get hdbuserstore path"
      become:                          true
      become_user:                     "root"
      when:
        - database_high_availability
        - platform == 'HANA'
      ansible.builtin.find:
        paths:                         "/usr/sap/{{ sid_to_be_deployed.sid | upper }}/SYS/exe/uc/linuxx86_64/hdbclient/,/usr/sap/{{ sid_to_be_deployed.sid }}/hdbclient"
        file_type:                     file
        patterns:                      'hdbuserstore'
        recurse:                       true
      register:                        hdbuserstore_file
      environment:
        SAPSYSTEMNAME:                 "{{ sid_to_be_deployed.sid | upper }}"

    - name:                            "DBLoad: Set hdbuserstore path"
      when:
        - database_high_availability
        - platform == 'HANA'
        - hdbuserstore_file is defined
        - hdbuserstore_file | length > 0
      ansible.builtin.set_fact:
        hdbuserstore_path:             "{{ hdbuserstore_file.files[0].path }}"
        db_lb_virtual_host:            "{{ sid_to_be_deployed.sid | lower }}{{ db_sid | lower }}db{{ db_instance_number }}cl.{{ sap_fqdn }}"

    - name:                            "DBLoad: show hdbuserstore path"
      when:
        - database_high_availability
        - platform == 'HANA'
      ansible.builtin.debug:
        var:                           hdbuserstore_path
        verbosity:                     2

    - name:                            "DBLoad: Set DB Virtual Host name ({{ custom_db_virtual_hostname | default(db_lb_virtual_host, true) }})"
      become:                          true
      become_user:                     "root"
      when:
        - database_high_availability
        - platform == 'HANA'
        - hdbuserstore_path is defined
      ansible.builtin.shell: |
                                       {{ hdbuserstore_path }} -H {{ pas_virtual_hostname }} SET DEFAULT {{ custom_db_virtual_hostname | default(db_lb_virtual_host, true) }}:3{{ db_instance_number }}13@{{ db_sid | upper }} {{ hana_schema }} {{ main_password }}
      environment:
        SAPSYSTEMNAME:                 "{{ sid_to_be_deployed.sid | upper }}"
        TMPDIR:                        "{{ hdbuserstore_path }}"
        ssfs_connect:                  "1"
      register:                        hdbuserstore
      vars:
        allow_world_readable_tmpfiles: true

...
# /*---------------------------------------------------------------------------8
# |                                   END                                      |
# +------------------------------------4--------------------------------------*/
