/home/zuul/src/opendev.org/openstack/openstack-ansible-os_tempest/tasks/tempest_resources.yml
---
# Copyright 2014, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# We set the python interpreter to the ansible runtime venv if
# the delegation is to localhost so that we get access to the
# appropriate python libraries in that venv. If the delegation
# is to another host, we assume that it is accessible by the
# system python instead.
- name: Setup the tempest resources
  delegate_to: "{{ tempest_service_setup_host }}"
  vars:
    ansible_python_interpreter: "{{ tempest_service_setup_host_python_interpreter }}"
  block:
    - name: Ensures you have at least one image to upload
      assert:
        that:
          - "tempest_images | length > 0"
      when:
        - tempest_service_available_glance | bool

    - name: Create deployment-host tempest_image_dir
      file:
        path: "{{ tempest_image_dir }}"
        state: directory
      when:
        - tempest_service_available_glance | bool

    - name: Image(s) download
      get_url:
        url: "{{ item.url }}"
        dest: "{{ tempest_image_dir }}/{{ item.url | basename }}"
        checksum: "{{ item.checksum | default(omit) }}"
        url_username: "{{ item.username | default(omit) }}"
        url_password: "{{ item.password | default(omit) }}"
      with_items: "{{ tempest_images }}"
      when:
        - tempest_service_available_glance | bool
      register: fetch_url
      until: fetch_url is success
      retries: 6
      delay: 5

    - name: Upload tempest images to glance
      os_image:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ not (tempest_keystone_interface_insecure | bool) }}"
        name: "{{ item.name | default(item.url | basename) }}"
        filename: "{{ tempest_image_dir }}/{{ item.url | basename }}"
        container_format: bare
        disk_format: "{{ item.format }}"
        is_public: True
        properties: "{{ item.properties | default(omit) }}"
      with_items: "{{ tempest_images }}"
      register: tempest_image_create
      until: tempest_image_create is success
      retries: 5
      delay: 15
      when:
        - tempest_service_available_glance | bool

    # These facts are used in tempest.conf.j2; we set an empty string if it is not
    # set above to ensure the template will parse correctly.
    - name: Store first tempest image id
      set_fact:
        tempest_glance_image_id_1: "{{ tempest_service_available_glance | ternary(tempest_image_create['results'][0]['id'], '') }}"
        tempest_glance_image_id_2: "{{ tempest_service_available_glance | ternary(tempest_image_create['results'][-1]['id'], '') }}"

    - name: Add tempest projects
      os_project:
        cloud: "{{ tempest_cloud_name }}"
        state: present
        name: "{{ item }}"
        description: "{{ item }} project"
        domain: "{{ tempest_domain_name }}"
        interface: "{{ tempest_interface_name }}"
        verify: "{{ not (tempest_keystone_interface_insecure | bool) }}"
      register: add_project
      until: add_project is success
      retries: 5
      delay: 10
      with_items: "{{ tempest_projects }}"

    - name: Add tempest users
      os_user:
        cloud: "{{ tempest_cloud_name }}"
        state: present
        name: "{{ item.name }}"
        password: "{{ item.password | default(item.name) }}"
        domain: "{{ tempest_domain_name }}"
        default_project: "{{ item.project | default(item.name) }}"
        interface: "{{ tempest_interface_name }}"
        verify: "{{ not (tempest_keystone_interface_insecure | bool) }}"
      register: add_user
      until: add_user is success
      retries: 5
      delay: 10
      with_items: "{{ tempest_users }}"
      no_log: True

    - name: Add tempest roles
      os_keystone_role:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ not (tempest_keystone_interface_insecure | bool) }}"
        name: "{{ item }}"
      register: add_role
      until: add_role is success
      retries: 5
      delay: 10
      with_items: "{{ tempest_roles }}"

    - name: Add tempest users to heat_stack_owner role
      os_user_role:
        cloud: "{{ tempest_cloud_name }}"
        state: present
        user: "{{ item.name }}"
        role: "heat_stack_owner"
        project: "{{ item.project | default(item.name) }}"
        interface: "{{ tempest_interface_name }}"
        verify: "{{ not (tempest_keystone_interface_insecure | bool) }}"
      register: add_user_role
      until: add_user_role is success
      retries: 5
      delay: 10
      with_items: "{{ tempest_users }}"
      when:
        - tempest_service_available_heat | bool

    - name: Store demo tenant id
      set_fact:
        keystone_demo_tenant_id: "{{ (add_project.results | json_query('[*].project.id'))[0] }}"

    - name: Ensure private network exists
      os_network:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ tempest_keystone_interface_insecure | ternary(false, true) }}"
        name: "{{ tempest_private_net_name }}"
        provider_network_type: "{{ tempest_private_net_provider_type }}"
        provider_physical_network: "{{ tempest_private_net_physical_name | default(omit) }}"
        provider_segmentation_id: "{{ tempest_private_net_seg_id | default(omit, true) }}"
        project: "{{ keystone_demo_tenant_id }}"
      register: tempest_private_network
      until: tempest_private_network is success
      retries: 5
      delay: 10
      when:
        - tempest_service_available_neutron | bool

    - name: Store neutron private network id
      set_fact:
        tempest_neutron_private_network_id: "{{ tempest_private_network.id }}"
      when:
        - tempest_service_available_neutron | bool

    - name: Ensure public network exists
      os_network:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ tempest_keystone_interface_insecure | ternary(false, true) }}"
        name: "{{ tempest_public_net_name }}"
        provider_network_type: "{{ tempest_public_net_provider_type }}"
        provider_physical_network: "{{ tempest_public_net_physical_name | default(omit) }}"
        provider_segmentation_id: "{{ tempest_public_net_seg_id | default(omit, true) }}"
        external: "{{ tempest_public_router_external }}"
        project: "{{ keystone_demo_tenant_id }}"
      register: tempest_public_network
      until: tempest_public_network is success
      retries: 5
      delay: 10
      when:
        - tempest_service_available_neutron | bool

    - name: Store neutron public network id
      set_fact:
        tempest_neutron_public_network_id: "{{ tempest_service_available_neutron | ternary(tempest_public_network.id, '') }}"

    - name: Ensure private subnet exists
      os_subnet:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ tempest_keystone_interface_insecure | ternary(false, true) }}"
        network_name: "{{ tempest_private_net_name }}"
        name: "{{ tempest_private_subnet_name }}"
        cidr: "{{ tempest_private_subnet_cidr }}"
        project: "{{ keystone_demo_tenant_id }}"
        enable_dhcp: false
      register: _add_private_subnet
      until: _add_private_subnet is success
      retries: 5
      delay: 10
      when:
        - tempest_service_available_neutron | bool

    - name: Ensure public subnet exists
      os_subnet:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ tempest_keystone_interface_insecure | ternary(false, true) }}"
        network_name: "{{ tempest_public_net_name }}"
        name: "{{ tempest_public_subnet_name }}"
        cidr: "{{ tempest_public_subnet_cidr }}"
        allocation_pool_start: "{{ tempest_public_subnet_allocation_pools.split('-')[0] | default(omit) }}"
        allocation_pool_end: "{{ tempest_public_subnet_allocation_pools.split('-')[1] | default(omit) }}"
        gateway_ip: "{{ tempest_public_subnet_gateway_ip | default(omit) }}"
      register: _add_public_subnet
      until: _add_public_subnet is success
      retries: 5
      delay: 10
      when:
        - tempest_service_available_neutron | bool

    - name: Create router
      os_router:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ tempest_keystone_interface_insecure | ternary(false, true) }}"
        name: router
        network: "{{ tempest_public_net_name }}"
        interfaces:
          - "{{ tempest_private_subnet_name }}"
        project: "{{ keystone_demo_tenant_id }}"
      register: _add_router
      until: _add_router is success
      retries: 5
      delay: 10
      when:
        - tempest_service_available_neutron | bool

    - name: Get router admin state and ip address
      set_fact:
        router_admin_state: "{{ _add_router['router']['admin_state_up'] }}"
        router_ip: "{{ _add_router['router']['external_gateway_info']['external_fixed_ips'][0]['ip_address'] }}"
      when:
        - tempest_service_available_neutron | bool

    - name: Create tempest flavors
      os_nova_flavor:
        cloud: "{{ tempest_cloud_name }}"
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ tempest_keystone_interface_insecure | ternary(false, true) }}"
        name: "{{ item.name }}"
        flavorid: "{{ item.id }}"
        ram: "{{ item.ram }}"
        disk: "{{ item.disk }}"
        vcpus: "{{ item.vcpus }}"
      with_items: "{{ tempest_flavors }}"
      register: _add_flavors
      until: _add_flavors is success
      retries: 5
      delay: 10
      when:
        - tempest_service_available_nova | bool

    - name: Get the admin user project id
      os_project_facts:
        cloud: "{{ tempest_cloud_name }}"
        name: admin
        interface: "{{ tempest_interface_name }}"
        validate_certs: "{{ not (tempest_keystone_interface_insecure | bool) }}"
      register: _get_admin_project
      until: _get_admin_project is success
      retries: 5
      delay: 15

    - name: Store admin project id
      set_fact:
        tempest_admin_tenant_id: "{{ ansible_facts.openstack_projects[0].id }}"

- name: Ping router ip address
  shell: |
    set -e
    ping -c2 "{{ router_ip }}"
  register: _ping_router
  until: _ping_router is success
  retries: 5
  delay: 10
  when:
    - tempest_service_available_neutron | bool
    - router_admin_state | bool
    - tempest_network_ping_gateway | bool
    - tempest_public_net_provider_type not in ['local']