
Previously, the user prompt ran on one host, but the assertion ran on all hosts. This meant the check could only pass on one host, all others would fail every time. This change ensures the check and assertion always run once on localhost. Closes-Bug: #2115037 Change-Id: If2a26b42e6fe0152922e10df924c0797259e2e53
213 lines
8.1 KiB
YAML
213 lines
8.1 KiB
YAML
---
|
|
# Use bifrost to deprovision the overcloud nodes.
|
|
|
|
- name: Ensure the overcloud nodes are deprovisioned
|
|
hosts: overcloud
|
|
max_fail_percentage: >-
|
|
{{ overcloud_deprovision_max_fail_percentage |
|
|
default(kayobe_max_fail_percentage) |
|
|
default(100) }}
|
|
tags:
|
|
- deprovision
|
|
vars:
|
|
# Set to False to avoid waiting for the nodes to become active.
|
|
wait_available: True
|
|
wait_available_timeout: 600
|
|
wait_available_interval: 10
|
|
# List of states from which we can get to available.
|
|
deprovisionable_states:
|
|
- available
|
|
- active
|
|
- error
|
|
- wait call-back
|
|
- deploying
|
|
- deploy failed
|
|
# List of valid states while a node is being deprovisioned.
|
|
deleting_states:
|
|
# The API is asynchronous, so allow the initial state.
|
|
- active
|
|
- deleting
|
|
- cleaning
|
|
- clean wait
|
|
# Retries to use when using Ironic API and hitting node locked errors.
|
|
ironic_retries: 6
|
|
ironic_retry_interval: 5
|
|
seed_host: "{{ groups['seed'][0] }}"
|
|
confirm_deprovision: False
|
|
gather_facts: no
|
|
tasks:
|
|
- name: Prompt to confirm deprovision
|
|
ansible.builtin.pause:
|
|
prompt: >
|
|
The following hosts will be deprovisioned:
|
|
{{ play_hosts | join(', ') }}
|
|
If you want to proceed type: yes
|
|
register: pause_prompt
|
|
delegate_to: localhost
|
|
run_once: true
|
|
when: not confirm_deprovision
|
|
|
|
- name: Fail if deprovision is not confirmed
|
|
assert:
|
|
that: confirm_deprovision | bool or pause_prompt.user_input == 'yes'
|
|
msg: >
|
|
Deprovision has not been confirmed. You must either type 'yes' when
|
|
prompted, or set ``confirm_deprovision=yes``.
|
|
delegate_to: localhost
|
|
run_once: true
|
|
|
|
- name: Get PXE MAC address
|
|
command: >
|
|
{{ container_engine }} exec bifrost_deploy
|
|
bash -c '
|
|
export OS_CLOUD=bifrost &&
|
|
export OS_BAREMETAL_API_VERSION=1.34 &&
|
|
export BIFROST_INVENTORY_SOURCE=ironic &&
|
|
export BIFROST_NODE_NAMES="{{ inventory_hostname }}" &&
|
|
baremetal port list --node {{ inventory_hostname }} --fields address -f value'
|
|
register: pxe_result
|
|
delegate_to: "{{ seed_host }}"
|
|
become: "{{ container_engine == 'podman' }}"
|
|
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) }}"
|
|
|
|
- name: Check the ironic node's initial provision state
|
|
command: >
|
|
{{ container_engine }} exec bifrost_deploy
|
|
bash -c '
|
|
export OS_CLOUD=bifrost &&
|
|
export OS_BAREMETAL_API_VERSION=1.34 &&
|
|
export BIFROST_INVENTORY_SOURCE=ironic &&
|
|
export BIFROST_NODE_NAMES="{{ inventory_hostname }}" &&
|
|
ansible baremetal
|
|
--connection local
|
|
--inventory /etc/bifrost/inventory/
|
|
-e @/etc/bifrost/bifrost.yml
|
|
-e @/etc/bifrost/dib.yml
|
|
--limit {{ inventory_hostname }}
|
|
-m command
|
|
-a "baremetal node show {% raw %}{{ inventory_hostname }}{% endraw %} -f value -c provision_state"'
|
|
register: show_result
|
|
changed_when: False
|
|
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) }}"
|
|
become: "{{ container_engine == 'podman' }}"
|
|
|
|
- name: Set a fact containing the ironic node's initial provision state
|
|
set_fact:
|
|
initial_provision_state: "{{ show_result.stdout_lines[1] }}"
|
|
|
|
- name: Fail if the ironic node is in an unexpected provision state
|
|
fail:
|
|
msg: >
|
|
Ironic node for {{ inventory_hostname }} is in an unexpected
|
|
initial provision state: {{ initial_provision_state }}. Expected
|
|
states are: {{ deprovisionable_states | join(',') }}.
|
|
when: initial_provision_state not in deprovisionable_states
|
|
|
|
- name: Ensure the ironic node is deprovisioned
|
|
command: >
|
|
{{ container_engine }} exec bifrost_deploy
|
|
bash -c '
|
|
export OS_CLOUD=bifrost &&
|
|
export BIFROST_INVENTORY_SOURCE=ironic &&
|
|
export BIFROST_NODE_NAMES="{{ inventory_hostname }}" &&
|
|
ansible baremetal -vvvv
|
|
--connection local
|
|
--inventory /etc/bifrost/inventory/
|
|
-e @/etc/bifrost/bifrost.yml
|
|
-e @/etc/bifrost/dib.yml
|
|
--limit {{ inventory_hostname }}
|
|
-m command
|
|
-a "baremetal node undeploy {% raw %}{{ inventory_hostname }}{% endraw %}"'
|
|
register: delete_result
|
|
until: delete_result is successful or 'is locked by host' in delete_result.stdout
|
|
retries: "{{ ironic_retries }}"
|
|
delay: "{{ ironic_retry_interval }}"
|
|
when: initial_provision_state != 'available'
|
|
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) }}"
|
|
become: "{{ container_engine == 'podman' }}"
|
|
|
|
- name: Wait for the ironic node to become available
|
|
command: >
|
|
{{ container_engine }} exec bifrost_deploy
|
|
bash -c '
|
|
export OS_CLOUD=bifrost &&
|
|
export OS_BAREMETAL_API_VERSION=1.34 &&
|
|
export BIFROST_INVENTORY_SOURCE=ironic &&
|
|
export BIFROST_NODE_NAMES="{{ inventory_hostname }}" &&
|
|
ansible baremetal
|
|
--connection local
|
|
--inventory /etc/bifrost/inventory/
|
|
-e @/etc/bifrost/bifrost.yml
|
|
-e @/etc/bifrost/dib.yml
|
|
--limit {{ inventory_hostname }}
|
|
-m command
|
|
-a "baremetal node show {% raw %}{{ inventory_hostname }}{% endraw %} -f value -c provision_state"'
|
|
register: show_result
|
|
# Wait until the node is no longer in one of the deleting states.
|
|
until: not show_result.stdout_lines[1:] | intersect(deleting_states)
|
|
retries: "{{ wait_available_timeout // wait_available_interval }}"
|
|
delay: "{{ wait_available_interval }}"
|
|
when:
|
|
- wait_available | bool
|
|
- initial_provision_state != 'available'
|
|
changed_when: False
|
|
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) }}"
|
|
become: "{{ container_engine == 'podman' }}"
|
|
|
|
- name: Set a fact containing the ironic node's final provision state
|
|
set_fact:
|
|
final_provision_state: "{{ show_result.stdout_lines[1] }}"
|
|
when:
|
|
- wait_available | bool
|
|
- initial_provision_state != 'available'
|
|
|
|
- name: Fail if the ironic node is not available
|
|
fail:
|
|
msg: >
|
|
Ironic node for {{ inventory_hostname }} is in an unexpected
|
|
provision state after deprovisioning. Ironic provision state:
|
|
{{ final_provision_state }}. Expected: available.
|
|
when:
|
|
- wait_available | bool
|
|
- initial_provision_state != 'available'
|
|
- final_provision_state != 'available'
|
|
|
|
- name: Delete host_vars file
|
|
become: yes
|
|
ansible.builtin.file:
|
|
path: /etc/kolla/bifrost/inventory/host_vars/{{ inventory_hostname }}
|
|
state: absent
|
|
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) }}"
|
|
|
|
- name: Delete ironic-mac-addr.conf
|
|
command: >
|
|
{{ container_engine }} exec bifrost_deploy
|
|
bash -c '
|
|
rm -f /etc/dnsmasq.d/bifrost.dhcp-hosts.d/ironic-{{ item }}.conf'
|
|
loop: "{{ pxe_result.stdout_lines }}"
|
|
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) }}"
|
|
become: "{{ container_engine == 'podman' }}"
|