---
# NOTE(yoctozepto): this handler dance is to ensure we delay restarting master
# keepalived and haproxy which control VIP address until we have working backups.
# This could be improved by checking if backup keepalived do not report FAULT state.
# Master node is handled specially to let it close down connections and only then
# drop the VIP address by stopping keepalived service.

# NOTE(yoctozepto): we need fresh VIP address placement info (facts may be old)
- name: Check IP addresses on the API interface
  vars:
    version: "{{ '6' if api_address_family == 'ipv6' else '4' }}"
  become: true
  command: ip -{{ version }} -o addr show dev {{ api_interface }}
  register: ip_addr_output
  changed_when: false
  when:
    - kolla_action != "config"
  listen:
    - Restart haproxy container
    - Restart proxysql container
    - Restart keepalived container

- name: Group HA nodes by status
  vars:
    re_safe_address: "{{ kolla_internal_vip_address | regex_escape }}"
  group_by:
    key: kolla_ha_is_master_{{ ip_addr_output.stdout is regex('\b' + re_safe_address + '\b') }}
  changed_when: false
  when:
    - kolla_action != "config"
  listen:
    - Restart haproxy container
    - Restart proxysql container
    - Restart keepalived container

- name: Stop backup keepalived container
  become: true
  kolla_container:
    action: "stop_container"
    # NOTE(yoctozepto): backup node might not have keepalived yet - ignore
    ignore_missing: true
    common_options: "{{ docker_common_options }}"
    name: "keepalived"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_False is defined
    - inventory_hostname in groups.kolla_ha_is_master_False
  listen:
    - Restart keepalived container

# NOTE(yoctozepto): We need the following to be stop-start as haproxy and
# proxysql need to be reconfigured simultaneously when switching between them.

- name: Stop backup haproxy container
  become: true
  kolla_container:
    action: "stop_container"
    # NOTE(kevko): backup node might not have haproxy yet - ignore
    ignore_missing: true
    common_options: "{{ docker_common_options }}"
    name: "haproxy"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_False is defined
    - inventory_hostname in groups.kolla_ha_is_master_False
  listen:
    - Restart haproxy container
    - Restart keepalived container

- name: Stop backup proxysql container
  become: true
  kolla_container:
    action: "stop_container"
    # NOTE(kevko): backup node might not have proxysql yet - ignore
    ignore_missing: true
    common_options: "{{ docker_common_options }}"
    name: "proxysql"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_False is defined
    - inventory_hostname in groups.kolla_ha_is_master_False
  listen:
    # NOTE(kevko): We need the following "Restart haproxy container" as
    # there is nothing to trigger "Restart proxysql container" when
    # proxysql is deconfigured.
    - Restart haproxy container
    - Restart proxysql container
    - Restart keepalived container

- name: Start backup haproxy container
  vars:
    service_name: "haproxy"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    privileged: "{{ service.privileged | default(False) }}"
    volumes: "{{ service.volumes }}"
    dimensions: "{{ service.dimensions }}"
    healthcheck: "{{ service.healthcheck | default(omit) }}"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_False is defined
    - inventory_hostname in groups.kolla_ha_is_master_False
    - service.enabled | bool
  listen:
    - Restart haproxy container
    - Restart keepalived container
  notify:
    - Wait for backup haproxy to start

- name: Wait for backup haproxy to start
  wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ haproxy_monitor_port }}"
  any_errors_fatal: true

- name: Start backup proxysql container
  vars:
    service_name: "proxysql"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    privileged: "{{ service.privileged | default(False) }}"
    volumes: "{{ service.volumes }}"
    dimensions: "{{ service.dimensions }}"
    healthcheck: "{{ service.healthcheck | default(omit) }}"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_False is defined
    - inventory_hostname in groups.kolla_ha_is_master_False
    - service.enabled | bool
  listen:
    # NOTE(kevko): We need the following "Restart haproxy container" as
    # there is nothing to trigger "Restart proxysql container" when
    # proxysql is configured.
    - Restart haproxy container
    - Restart proxysql container
    - Restart keepalived container
  notify:
    - Wait for backup proxysql to start

- name: Wait for backup proxysql to start
  wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ proxysql_admin_port }}"
  any_errors_fatal: true

- name: Start backup keepalived container
  vars:
    service_name: "keepalived"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    privileged: "{{ service.privileged | default(False) }}"
    volumes: "{{ service.volumes }}"
    dimensions: "{{ service.dimensions }}"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_False is defined
    - inventory_hostname in groups.kolla_ha_is_master_False
    - service.enabled | bool
  listen:
    - Restart keepalived container
  notify:
    - Wait for virtual IP to appear

# NOTE(yoctozepto): This is to ensure haproxy, proxysql can close any open connections
# to the VIP address.
- name: Stop master haproxy container
  become: true
  kolla_container:
    action: "stop_container"
    # NOTE(yoctozepto): master node might not have haproxy yet - ignore
    ignore_missing: true
    common_options: "{{ docker_common_options }}"
    name: "haproxy"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_True is defined
    - inventory_hostname in groups.kolla_ha_is_master_True
  listen:
    - Restart haproxy container
    - Restart keepalived container

- name: Stop master proxysql container
  become: true
  kolla_container:
    action: "stop_container"
    common_options: "{{ docker_common_options }}"
    name: "proxysql"
    ignore_missing: true
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_True is defined
    - inventory_hostname in groups.kolla_ha_is_master_True
  listen:
    - Restart proxysql container
    - Restart keepalived container

- name: Stop master keepalived container
  become: true
  kolla_container:
    action: "stop_container"
    common_options: "{{ docker_common_options }}"
    name: "keepalived"
    ignore_missing: true
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_True is defined
    - inventory_hostname in groups.kolla_ha_is_master_True
  listen:
    - Restart keepalived container

- name: Start master haproxy container
  vars:
    service_name: "haproxy"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    privileged: "{{ service.privileged | default(False) }}"
    volumes: "{{ service.volumes }}"
    dimensions: "{{ service.dimensions }}"
    healthcheck: "{{ service.healthcheck | default(omit) }}"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_True is defined
    - inventory_hostname in groups.kolla_ha_is_master_True
    - service.enabled | bool
  listen:
    - Restart haproxy container
    - Restart keepalived container
  notify:
    - Wait for master haproxy to start

- name: Wait for master haproxy to start
  wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ haproxy_monitor_port }}"

- name: Start master proxysql container
  vars:
    service_name: "proxysql"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    privileged: "{{ service.privileged | default(False) }}"
    volumes: "{{ service.volumes }}"
    dimensions: "{{ service.dimensions }}"
    healthcheck: "{{ service.healthcheck | default(omit) }}"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_True is defined
    - inventory_hostname in groups.kolla_ha_is_master_True
    - service.enabled | bool
  listen:
    - Restart proxysql container
    - Restart keepalived container
  notify:
    - Wait for master proxysql to start

- name: Wait for master proxysql to start
  wait_for:
    host: "{{ api_interface_address }}"
    port: "{{ proxysql_admin_port }}"

- name: Start master keepalived container
  vars:
    service_name: "keepalived"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    privileged: "{{ service.privileged | default(False) }}"
    volumes: "{{ service.volumes }}"
    dimensions: "{{ service.dimensions }}"
  when:
    - kolla_action != "config"
    - groups.kolla_ha_is_master_True is defined
    - inventory_hostname in groups.kolla_ha_is_master_True
    - service.enabled | bool
  listen:
    - Restart keepalived container
  notify:
    - Wait for virtual IP to appear

- name: Wait for haproxy to listen on VIP
  vars:
    service_name: "haproxy"
    service: "{{ loadbalancer_services[service_name] }}"
  wait_for:
    host: "{{ kolla_internal_vip_address }}"
    port: "{{ haproxy_monitor_port }}"
  when:
    - service.enabled | bool
  listen:
    - Wait for virtual IP to appear

- name: Wait for proxysql to listen on VIP
  vars:
    service_name: "proxysql"
    service: "{{ loadbalancer_services[service_name] }}"
  wait_for:
    host: "{{ kolla_internal_vip_address }}"
    port: "{{ proxysql_admin_port }}"
  when:
    - service.enabled | bool
  listen:
    - Wait for virtual IP to appear

- name: Restart haproxy-ssh container
  vars:
    service_name: "haproxy-ssh"
    service: "{{ loadbalancer_services[service_name] }}"
  become: true
  kolla_container:
    action: "recreate_or_restart_container"
    common_options: "{{ docker_common_options }}"
    name: "{{ service.container_name }}"
    image: "{{ service.image }}"
    volumes: "{{ service.volumes | reject('equalto', '') | list }}"
    dimensions: "{{ service.dimensions }}"
    healthcheck: "{{ service.healthcheck | default(omit) }}"
  when:
    - kolla_action != "config"
