tenks/ansible/roles/ironic-enrolment/tasks/node.yml

129 lines
5.0 KiB
YAML

---
- name: Check node has a resource class
fail:
msg: >
The `ironic_config` of node '{{ node }}' does not contain a
`resource_class`.
when: "'resource_class' not in node.ironic_config"
- name: Collect domain NIC MAC addresses
block:
- name: Get vNIC MAC addresses
# The output format of this command gives two lines of header, followed by
# (for each vNIC):
# <name> <type> <source interface> <model> <MAC>
command: >-
/usr/bin/virsh
{% if uri %}-c {{ uri }}{% endif %}
domiflist '{{ node.name }}'
vars:
uri: "{{ hostvars[ironic_hypervisor].libvirt_local_uri }}"
register: iflist_res
changed_when: false
become: true
delegate_to: "{{ ironic_hypervisor }}"
run_once: true
# We need to do this for each run to ensure other nodes' NICs don't carry over
# to this run.
- name: Reset list of NICs
set_fact:
nics: []
- name: Collect MAC addresses into NIC list
set_fact:
nics: "{{ nics | union([{'mac': item.split()[4]}]) }}"
loop: "{{ iflist_res.stdout_lines[2:] }}"
when: (node.state | default('present')) == 'present'
# If the node's state is 'absent', the domain will already have been
# destroyed.
when: (node.state | default('present')) == 'present'
- name: Configure node in Ironic
os_ironic:
auth_type: "{{ 'password' if lookup('env', 'OS_USERNAME') else omit }}"
cloud: "{{ lookup('env', 'OS_CLOUD') | default(omit, true) }}"
ironic_url: "{{ ironic_url | default(omit) }}"
driver: "{{ node.ironic_driver }}"
driver_info:
power:
ipmi_address: "{{ hostvars[ironic_hypervisor].ipmi_address }}"
# This is passed in from main.yml.
ipmi_port: "{{ ipmi_port }}"
ipmi_username: "{{ hostvars[ironic_hypervisor].ipmi_username }}"
ipmi_password: "{{ hostvars[ironic_hypervisor].ipmi_password }}"
deploy:
deploy_kernel: "{{ ironic_deploy_kernel_uuid | default(omit, true) }}"
deploy_ramdisk: "{{ ironic_deploy_ramdisk_uuid | default(omit, true) }}"
name: "{{ node.name }}"
# The 'nics' list can be empty without a problem if state is 'absent'.
nics: "{{ nics | default([]) }}"
state: "{{ node.state | default('present') }}"
vars:
# This module requires the openstacksdk package, which is installed within
# our virtualenv.
ansible_python_interpreter: >-
{{ '/'.join([ironic_virtualenv_path, 'bin', 'python']) }}
register: node_res
- name: Perform node and port attribute manipulation
block:
# The os_ironic module automatically brings the node from 'enrol' to
# 'available' state, but we still need to set more port and node attributes.
# Use maintenance mode to do this.
- name: Put Ironic node into maintenance mode
command: >-
'{{ ironic_virtualenv_path }}/bin/openstack' baremetal node maintenance set
'{{ node_res.uuid }}'
- name: Set additional Ironic node attributes
command: >-
'{{ ironic_virtualenv_path }}/bin/openstack' baremetal node set
'{{ node_res.uuid }}'
--resource-class {{ node.ironic_config.resource_class }}
{% for iface in ironic_interfaces %}
{% if (iface + '_interface') in node.ironic_config %}
--{{ iface }}-interface {{ node.ironic_config[iface + '_interface'] }}
{% endif %}
{% endfor %}
{% for key, val in properties.iteritems() %}
--property '{{ key }}={{ val }}'
{% endfor %}
vars:
properties: "{{ default_properties | combine(custom_properties) }}"
custom_properties: "{{ node.ironic_config.get('properties', {}) }}"
# Although properties are not required for scheduling, the os_ironic module
# adds silly defaults that cause the validation API call to fail,
# preventing deployment. We add them here because the os_ironic module
# uses unusual names (cpus, ram, disk_size) for scheduling properties,
# and doesn't support setting other properties.
default_properties:
cpus: "{{ node.vcpus }}"
memory_mb: "{{ node.memory_mb }}"
local_gb: "{{ node.volumes[0].capacity | size_string_to_gb if node.volumes | length > 0 else 0 }}"
- name: Add Ironic node traits
command: >-
'{{ ironic_virtualenv_path }}/bin/openstack' baremetal node add trait
'{{ node_res.uuid }}'
{{ " ".join(node.ironic_config.traits) }}
when: node.ironic_config.traits | default([])
- name: Set additional Ironic port attributes
include_tasks: port.yml
vars:
source_interface: "{{ vnic.split()[2] }}"
mac: "{{ vnic.split()[4] }}"
# Loop over each NIC.
loop: "{{ iflist_res.stdout_lines[2:] }}"
loop_control:
loop_var: vnic
- name: Bring Ironic node out of maintenance mode
command: >-
'{{ ironic_virtualenv_path }}/bin/openstack' baremetal node maintenance
unset '{{ node_res.uuid }}'
when: (node.state | default('present')) == 'present'