---
# Perform configuration of the overcloud nodes' BIOS and RAID. Nodes should be
# registered with the seed's ironic service but not active. The BIOS and RAID
# is configured out of band using the ansible stackhpc.drac role. As such, only
# Dell servers with iDRACs are currently supported. During configuration, we
# set the ironic nodes' to maintenance mode to prevent ironic from managing
# their power states.

- name: Group overcloud nodes by their BMC type
  hosts: overcloud
  gather_facts: no
  tags:
    - bios
    - raid
  vars:
    # List of BMC types supporting BIOS and RAID configuration.
    supported_bmc_types:
      - idrac
  tasks:
    - name: Fail if node has BIOS and/or RAID configuration and BMC type is not supported
      fail:
        msg: >
          Node has BIOS and/or RAID configuration but BMC type
          {% if bmc_type is undefined %}is not defined{% else %}{{ bmc_type }}
          is not supported{% endif %}.
      when:
        - bios_config or raid_config
        - bmc_type is undefined or bmc_type not in supported_bmc_types

    - name: Group overcloud hosts by their BMC type
      group_by:
        key: "overcloud_with_bmcs_of_type_{{ bmc_type | default('unknown') }}"

- name: Check whether any changes to nodes' BIOS and RAID configuration are required
  hosts: overcloud_with_bmcs_of_type_idrac
  gather_facts: no
  tags:
    - bios
    - raid
  vars:
    # Set this to False to avoid rebooting the nodes after configuration.
    drac_reboot: True
  roles:
    - role: stackhpc.drac
      drac_address: "{{ ipmi_address }}"
      drac_username: "{{ ipmi_username }}"
      drac_password: "{{ ipmi_password }}"
      drac_bios_config: "{{ bios_config }}"
      drac_raid_config: "{{ raid_config }}"
      drac_check_mode: True
  tasks:
    - name: Set a fact about whether the configuration changed
      set_fact:
        bios_or_raid_change: "{{ drac_result | changed }}"

- name: Ensure that overcloud BIOS and RAID volumes are configured
  hosts: overcloud_with_bmcs_of_type_idrac
  gather_facts: no
  tags:
    - bios
    - raid
  vars:
    # Set this to False to avoid rebooting the nodes after configuration.
    drac_reboot: True
    seed_host: "{{ groups['seed'][0] }}"
  pre_tasks:
    - name: Set the overcloud nodes' maintenance mode
      command: >
        docker exec bifrost_deploy
        bash -c '. env-vars &&
        export OS_URL=$IRONIC_URL &&
        export OS_TOKEN=$OS_AUTH_TOKEN &&
        export BIFROST_INVENTORY_SOURCE=ironic &&
        ansible baremetal
        --connection local
        --inventory /etc/bifrost/inventory/
        -e @/etc/bifrost/bifrost.yml
        -e @/etc/bifrost/dib.yml
        --limit {{ inventory_hostname }}
        -m command
        -a "openstack baremetal node maintenance set {% raw %}{{ inventory_hostname }}{% endraw %} --reason BIOS-RAID"'
      delegate_to: "{{ seed_host }}"
      vars:
        # NOTE: Without this, the seed's ansible_host variable will not be
        # respected when using delegate_to.
        ansible_host: "{{ hostvars[seed_host].ansible_host | default(seed_host) }}"
      when: bios_or_raid_change | bool

  roles:
    - role: stackhpc.drac
      drac_address: "{{ ipmi_address }}"
      drac_username: "{{ ipmi_username }}"
      drac_password: "{{ ipmi_password }}"
      drac_bios_config: "{{ bios_config }}"
      drac_raid_config: "{{ raid_config }}"
      when: bios_or_raid_change | bool

  tasks:
    - name: Unset the overcloud nodes' maintenance mode
      command: >
        docker exec bifrost_deploy
        bash -c '. env-vars &&
        export OS_URL=$IRONIC_URL &&
        export OS_TOKEN=$OS_AUTH_TOKEN &&
        export BIFROST_INVENTORY_SOURCE=ironic &&
        ansible baremetal
        --connection local
        --inventory /etc/bifrost/inventory/
        -e @/etc/bifrost/bifrost.yml
        -e @/etc/bifrost/dib.yml
        --limit {{ inventory_hostname }}
        -m command
        -a "openstack baremetal node maintenance unset {% raw %}{{ inventory_hostname }}{% endraw %}"'
      delegate_to: "{{ seed_host }}"
      vars:
        # NOTE: Without this, the seed's ansible_host variable will not be
        # respected when using delegate_to.
        ansible_host: "{{ hostvars[seed_host].ansible_host | default(seed_host) }}"
      when: bios_or_raid_change | bool