---
- name: Check whether Ironic is enabled
  hosts: controllers
  gather_facts: False
  tags:
    - config
    - config-validation
    - kolla-ansible
    - kolla-openstack
  tasks:
    - name: Create controllers group with ironic enabled
      group_by:
        key: "controllers_with_ironic_enabled_{{ kolla_enable_ironic | bool }}"
      changed_when: false

- name: Ensure locally built Ironic Python Agent images are copied
  hosts: controllers_with_ironic_enabled_True[0]
  gather_facts: False
  tags:
    - kolla-ansible
    - kolla-openstack
  vars:
    # These are the filenames generated by overcloud-ipa-build.yml.
    ipa_image_name: "ipa"
    ipa_images:
      - "{{ ipa_image_name }}.kernel"
      - "{{ ipa_image_name }}.initramfs"
  tasks:
    - block:
        - block:
            - name: Check for the presence of locally built Ironic Python Agent (IPA) images
              stat:
                path: "{{ image_cache_path }}/{{ ipa_image_name }}/{{ item }}"
                get_md5: False
                get_checksum: False
                mime: False
              with_items: "{{ ipa_images }}"
              register: ipa_image_stat

            - name: Validate the presence of locally built Ironic Python Agent (IPA) images
              fail:
                msg: >
                  Expected locally built Ironic Python Agent (IPA) image
                  {{ item.item }} was not present in
                  {{ image_cache_path }}/{{ ipa_image_name }}.
              with_items: "{{ ipa_image_stat.results }}"
              when: not item.stat.exists
          tags:
            - config-validation

        - name: Check whether the image cache directory exists
          local_action:
            module: stat
            path: "{{ hostvars.localhost.image_cache_path }}"
            get_md5: False
            get_checksum: False
            mime: False
          register: image_cache_stat

        - name: Ensure the image cache directory exists
          local_action:
            module: file
            path: "{{ hostvars.localhost.image_cache_path }}"
            state: directory
            owner: "{{ lookup('env', 'USER') }}"
            group: "{{ lookup('env', 'USER') }}"
          become: True
          when: >-
            not image_cache_stat.stat.exists or
            not image_cache_stat.stat.writeable

        - name: Ensure Ironic Python Agent images are copied onto the local machine
          fetch:
            src: "{{ image_cache_path }}/{{ ipa_image_name }}/{{ item.src }}"
            dest: "{{ hostvars.localhost.image_cache_path }}/{{ ipa_image_name }}/{{ item.dest }}"
            flat: True
          with_items:
            - src: "{{ ipa_images[0] }}"
              dest: "{{ ipa_images_kernel_name }}"
            - src: "{{ ipa_images[1] }}"
              dest: "{{ ipa_images_ramdisk_name }}"
      when:
        - kolla_enable_ironic | bool
        - ipa_build_images | bool
      tags:
        - config

- name: Ensure Kolla OpenStack components are configured
  hosts: localhost
  tags:
    - kolla-ansible
    - kolla-openstack
  vars:
    switch_type_to_device_type:
      arista: netmiko_arista_eos
      dellos9: netmiko_dell_force10
      dell-powerconnect: netmiko_dell_powerconnect
      junos: netmiko_juniper
      openvswitch: netmiko_ovs_linux
    ipa_image_name: "ipa"
  pre_tasks:
    - block:
        - name: Check whether Kolla extra configuration files exist
          stat:
            path: "{{ kayobe_env_config_path }}/kolla/config/{{ item.file }}"
            get_checksum: False
            get_md5: False
            mime: False
          register: stat_result
          with_items:
            - { name: aodh, file: aodh.conf }
            - { name: barbican, file: barbican.conf }
            - { name: blazar, file: blazar.conf }
            - { name: ceilometer, file: ceilometer.conf }
            - { name: cinder, file: cinder.conf }
            - { name: cloudkitty, file: cloudkitty.conf }
            - { name: designate, file: designate.conf }
            - { name: glance, file: glance.conf }
            - { name: global, file: global.conf }
            - { name: gnocchi, file: gnocchi.conf }
            - { name: grafana, file: grafana.ini }
            - { name: heat, file: heat.conf }
            - { name: inspector, file: ironic-inspector.conf }
            - { name: ironic, file: ironic.conf }
            - { name: kafka, file: kafka.server.properties }
            - { name: keystone, file: keystone.conf }
            - { name: magnum, file: magnum.conf }
            - { name: manila, file: manila.conf }
            - { name: mariabackup, file: backup.my.cnf }
            - { name: mariadb, file: galera.cnf }
            - { name: masakari, file: masakari.conf }
            - { name: multipathd, file: multipath.conf }
            - { name: murano, file: murano.conf }
            - { name: neutron, file: neutron.conf }
            - { name: neutron_ml2, file: neutron/ml2_conf.ini }
            - { name: nova, file: nova.conf }
            - { name: octavia, file: octavia.conf }
            - { name: placement, file: placement.conf }
            - { name: sahara, file: sahara.conf }
            - { name: zookeeper, file: zookeeper.cfg }

        - name: Initialise a fact containing extra configuration
          set_fact:
            kolla_extra_config: {}

        - name: Update a fact containing extra configuration
          set_fact:
            kolla_extra_config: "{{ kolla_extra_config | combine({item.item.name: lookup('template', '{{ item.stat.path }}')}) }}"
          with_items: "{{ stat_result.results }}"
          when: item.stat.exists

        - name: Validate switch configuration for Neutron ML2 genericswitch driver
          fail:
            msg: >
              Switch configuration for {{ item }} is invalid. The following
              variables must be set for the host: switch_type, ansible_host,
              ansible_user, ansible_ssh_pass. Further, switch_type must be one of
              {{ switch_type_to_device_type.keys() | join(', ') }}.
          with_items: "{{ kolla_neutron_ml2_generic_switch_hosts }}"
          when: >
            item not in hostvars or
            'switch_type' not in hostvars[item] or
            hostvars[item].switch_type not in switch_type_to_device_type or
            'ansible_host' not in hostvars[item] or
            'ansible_user' not in hostvars[item] or
            'ansible_ssh_pass' not in hostvars[item]
          tags:
            - config-validation

        - name: Update a fact containing switches for use by Neutron ML2 genericswitch driver
          set_fact:
            kolla_neutron_ml2_generic_switches: >
              {{
                  kolla_neutron_ml2_generic_switches +
                  [{
                    'name': item,
                    'device_type': switch_type_to_device_type[hostvars[item].switch_type],
                    'ip': hostvars[item].ansible_host,
                    'username': hostvars[item].ansible_user,
                    'password': hostvars[item].ansible_ssh_pass,
                    'ngs_trunk_ports': (
                         hostvars[item].switch_interface_config |
                         switch_interface_config_select_description(kolla_neutron_ml2_generic_switch_trunk_port_hosts) |
                         switch_interface_config_select_trunk()).keys() | join(',')
                  } | combine(hostvars[item].kolla_neutron_ml2_generic_switch_extra) ]
              }}
          with_items: "{{ kolla_neutron_ml2_generic_switch_hosts }}"

        - block:
            - name: Set facts containing IPA kernel and ramdisk URLs
              set_fact:
                kolla_inspector_ipa_kernel_upstream_url: "{{ inspector_ipa_kernel_upstream_url }}"
                kolla_inspector_ipa_kernel_checksum_url: "{{ inspector_ipa_kernel_checksum_url }}"
                kolla_inspector_ipa_kernel_checksum_algorithm: "{{ inspector_ipa_kernel_checksum_algorithm }}"
                kolla_inspector_ipa_ramdisk_upstream_url: "{{ inspector_ipa_ramdisk_upstream_url }}"
                kolla_inspector_ipa_ramdisk_checksum_url: "{{ inspector_ipa_ramdisk_checksum_url }}"
                kolla_inspector_ipa_ramdisk_checksum_algorithm: "{{ inspector_ipa_ramdisk_checksum_algorithm }}"
              when: not ipa_build_images | bool

            - name: Set facts containing IPA kernel and ramdisk paths
              set_fact:
                kolla_inspector_ipa_kernel_path: "{{ image_cache_path }}/{{ ipa_image_name }}/{{ ipa_images_kernel_name }}"
                kolla_inspector_ipa_ramdisk_path: "{{ image_cache_path }}/{{ ipa_image_name }}/{{ ipa_images_ramdisk_name }}"
              when: ipa_build_images | bool
          when: kolla_enable_ironic | bool
      tags:
        - config
  roles:
    - role: kolla-openstack
      # Ironic inspector configuration.
      kolla_inspector_processing_hooks: "{{ inspector_processing_hooks }}"
      kolla_inspector_add_ports: "{{ inspector_add_ports }}"
      kolla_inspector_keep_ports: "{{ inspector_keep_ports }}"
      kolla_inspector_enable_discovery: "{{ inspector_enable_discovery }}"
      kolla_inspector_discovery_enroll_node_driver: "{{ inspector_discovery_enroll_node_driver }}"
      # Ironic inspector swift store configuration. Currently only supports the
      # 'fake' inspection store.
      kolla_inspector_enable_swift: "{{ inspector_store_enabled }}"
      kolla_inspector_swift_auth:
        auth_type: none
        endpoint_override: "http://{% raw %}{{ api_interface_address }}{% endraw %}:{{ inspector_store_port }}"
      # Extra free-form user-provided configuration.
      kolla_extra_aodh: "{{ kolla_extra_config.aodh | default }}"
      kolla_extra_barbican: "{{ kolla_extra_config.barbican | default }}"
      kolla_extra_blazar: "{{ kolla_extra_config.blazar | default }}"
      kolla_extra_ceilometer: "{{ kolla_extra_config.ceilometer | default }}"
      kolla_extra_cinder: "{{ kolla_extra_config.cinder | default }}"
      kolla_extra_cloudkitty: "{{ kolla_extra_config.cloudkitty | default }}"
      kolla_extra_designate: "{{ kolla_extra_config.designate | default }}"
      kolla_extra_glance: "{{ kolla_extra_config.glance | default }}"
      kolla_extra_global: "{{ kolla_extra_config.global | default }}"
      kolla_extra_gnocchi: "{{ kolla_extra_config.gnocchi | default }}"
      kolla_extra_grafana: "{{ kolla_extra_config.grafana | default }}"
      kolla_extra_heat: "{{ kolla_extra_config.heat | default }}"
      kolla_extra_inspector: "{{ kolla_extra_config.inspector | default }}"
      kolla_extra_ironic: "{{ kolla_extra_config.ironic | default }}"
      kolla_extra_kafka: "{{ kolla_extra_config.kafka | default }}"
      kolla_extra_keystone: "{{ kolla_extra_config.keystone | default }}"
      kolla_extra_magnum: "{{ kolla_extra_config.magnum | default }}"
      kolla_extra_manila: "{{ kolla_extra_config.manila | default }}"
      kolla_extra_mariabackup: "{{ kolla_extra_config.mariabackup | default }}"
      kolla_extra_mariadb: "{{ kolla_extra_config.mariadb | default }}"
      kolla_extra_masakari: "{{ kolla_extra_config.masakari | default }}"
      kolla_extra_multipathd: "{{ kolla_extra_config.multipathd | default }}"
      kolla_extra_murano: "{{ kolla_extra_config.murano | default }}"
      kolla_extra_neutron: "{{ kolla_extra_config.neutron | default }}"
      kolla_extra_neutron_ml2: "{{ kolla_extra_config.neutron_ml2 | default }}"
      kolla_extra_nova: "{{ kolla_extra_config.nova | default }}"
      kolla_extra_octavia: "{{ kolla_extra_config.octavia | default }}"
      kolla_extra_placement: "{{ kolla_extra_config.placement | default }}"
      kolla_extra_sahara: "{{ kolla_extra_config.sahara | default }}"
      kolla_extra_zookeeper: "{{ kolla_extra_config.zookeeper | default }}"
      kolla_extra_config_path: "{{ kayobe_env_config_path }}/kolla/config"
