Discovery of overcloud hosts from Bifrost's Ironic inventory

This change enables 'zero touch' provisioning of the overcloud hosts. Following
power on of the nodes, they are discovered by Ironic inspector running on the
seed node and registered with the seed node's instance of Ironic. Once discovered
and inspected, Kayobe uses the seed's Ironic inventory to populate its own Ansible
inventory. From here, we can fill out host variables for Bifrost to use when
provisioning the nodes. Finally, we configure Kolla Ansible's inventory.
This commit is contained in:
Mark Goddard 2017-03-15 09:44:36 +00:00
parent c97a73e990
commit b05f02391c
6 changed files with 183 additions and 2 deletions

View File

@ -0,0 +1,3 @@
---
# Host/IP with which to access the controllers via SSH.
ansible_host: "{{ provision_oc_net_name | net_ip }}"

View File

@ -0,0 +1,46 @@
---
# Update the Bifrost inventory with the IP allocation and other variables.
- name: Ensure the Bifrost controller inventory is initialised
hosts: seed
gather_facts: no
tasks:
- name: Ensure the Bifrost host variables directory exists
file:
path: "/etc/kolla/bifrost/inventory/host_vars"
state: directory
become: True
- name: Ensure the Bifrost inventory exists
file:
path: "/etc/kolla/bifrost/inventory/bifrost_inventory.py"
src: "/bifrost/playbooks/inventory/bifrost_inventory.py"
state: link
# This file should only exist within the bifrost_deploy container.
force: True
become: True
- name: Ensure the Bifrost controller inventory is populated
hosts: controllers
gather_facts: no
vars:
seed_host: "{{ groups['seed'][0] }}"
bifrost_hostvars:
# Also supports vlan_id and network_mtu.
addressing_mode: static
ipv4_interface_mac: "{% raw %}{{ extra.pxe_interface_mac | default }}{% endraw %}"
ipv4_address: "{{ provision_oc_net_name | net_ip }}"
ipv4_subnet_mask: "{{ provision_oc_net_name | net_cidr | ipaddr('netmask') }}"
ipv4_gateway: "{{ provision_oc_net_name | net_gateway }}"
ipv4_nameserver: "{{ resolv_nameservers[0] }}"
tasks:
- name: Ensure the Bifrost host variable files exist
copy:
content: |
---
# This file is managed via Ansible. Do not edit.
# Bifrost host variables for {{ inventory_hostname }}
{{ bifrost_hostvars | to_nice_yaml }}
dest: "/etc/kolla/bifrost/inventory/host_vars/{{ inventory_hostname }}"
delegate_to: "{{ seed_host }}"
become: True

View File

@ -0,0 +1,67 @@
---
# Use bifrost to provision the overcloud nodes with a base OS.
- name: Ensure the Bifrost controller inventory is provisioned
hosts: seed
vars:
# Allow the set of hosts to be limited.
bifrost_limit:
gather_facts: no
tasks:
- name: Ensure the Bifrost controller inventory is managed
command: >
docker exec bifrost_deploy
bash -c '. env-vars &&
export BIFROST_INVENTORY_SOURCE=ironic &&
ansible baremetal -vvvv
--connection local
--inventory /etc/bifrost/inventory/
-e @/etc/bifrost/bifrost.yml
-e @/etc/bifrost/dib.yml
{% if bifrost_limit %}--limit {{ bifrost_limit }}{% endif %}
-m command
-a "ironic node-set-provision-state {% raw %}{{ inventory_hostname }}{% endraw %} manage"'
- name: Ensure the Bifrost controller inventory is provided
command: >
docker exec bifrost_deploy
bash -c '. env-vars &&
export BIFROST_INVENTORY_SOURCE=ironic &&
ansible baremetal -vvvv
--connection local
--inventory /etc/bifrost/inventory/
-e @/etc/bifrost/bifrost.yml
-e @/etc/bifrost/dib.yml
{% if bifrost_limit %}--limit {{ bifrost_limit }}{% endif %}
-m command
-a "ironic node-set-provision-state {% raw %}{{ inventory_hostname }}{% endraw %} provide"'
- name: Ensure the Bifrost controller inventory is provisioned
command: >
docker exec bifrost_deploy
bash -c '. env-vars &&
export BIFROST_INVENTORY_SOURCE=ironic &&
ansible-playbook -vvvv
/bifrost/playbooks/deploy-dynamic.yaml
--inventory /etc/bifrost/inventory/
-e @/etc/bifrost/bifrost.yml
-e @/etc/bifrost/dib.yml
{% if bifrost_limit %}--limit {{ bifrost_limit }}{% endif %}'
- name: Wait for the controller hosts to be available
hosts: controllers
gather_facts: no
vars:
# Set to False to avoid waiting for the controllers to be accessible via
# SSH.
wait: True
wait_timeout: 600
tasks:
- name: Wait for SSH access to the controllers
local_action:
module: wait_for
host: "{{ ansible_host }}"
port: 22
state: started
timeout: "{{ wait_timeout }}"
when: "{{ wait | bool }}"

View File

@ -0,0 +1,35 @@
---
# Gather an inventory of nodes from the seed's Ironic service. Use this to
# generate an Ansible inventory for Kayobe.
- name: Ensure the controller Ansible inventory is populated
hosts: seed
tasks:
- name: Gather the Ironic node inventory using Bifrost
command: >
docker exec bifrost_deploy
bash -c 'source /bifrost/env-vars &&
export BIFROST_INVENTORY_SOURCE=ironic &&
/bifrost/playbooks/inventory/bifrost_inventory.py'
register: inventory_result
changed_when: False
- name: Set a fact containing the Ironic node inventory
set_fact:
ironic_inventory: "{{ inventory_result.stdout | from_json }}"
- name: Ensure Kayobe controller inventory exists
local_action:
module: copy
content: |
# Managed by Ansible - do not edit.
# This is the Kayobe controller inventory, autogenerated from the seed
# node's Ironic inventory.
[controllers]
{% for host in ironic_inventory.baremetal.hosts %}
{% set hostvars=ironic_inventory._meta.hostvars[host] %}
{% set ipmi_address=hostvars.driver_info.ipmi_address | default %}
{{ host }} ipmi_address={{ ipmi_address }}
{% endfor %}
dest: "{{ kayobe_config_path }}/inventory/controllers"

View File

@ -166,9 +166,33 @@ class SeedServiceDeploy(KollaAnsibleMixin, KayobeAnsibleMixin, Command):
ansible.run_playbook(parsed_args, "ansible/seed-introspection-rules.yml")
class OvercloudProvision(KollaAnsibleMixin, KayobeAnsibleMixin, Command):
class OvercloudInventoryDiscover(KayobeAnsibleMixin, Command):
"""Discover the overcloud inventory from the seed's Ironic service."""
def take_action(self, parsed_args):
self.app.LOG.debug("Discovering overcloud inventory")
# Run the inventory discovery playbook separately, else the discovered
# hosts will not be present in the following playbooks in which they
# are used to populate other inventories.
ansible.run_playbook(parsed_args,
"ansible/overcloud-inventory-discover.yml")
# Now populate the Kolla Ansible and Bifrost inventories.
ansible.run_playbook(parsed_args, "ansible/kolla-bifrost-hostvars.yml")
ansible.run_playbook(parsed_args, "ansible/kolla-ansible.yml",
tags="config")
class OvercloudProvision(KayobeAnsibleMixin, Command):
"""Provision the overcloud."""
def get_parser(self, prog_name):
parser = super(OvercloudProvision, self).get_parser(prog_name)
group = parser.add_argument_group("Bifrost")
group.add_argument("-bl", "--bifrost-limit", metavar="SUBSET",
help="further limit selected hosts to an "
"additional pattern")
return parser
def take_action(self, parsed_args):
self.app.LOG.debug("Provisioning overcloud")
self._configure_network(parsed_args)
@ -183,7 +207,12 @@ class OvercloudProvision(KollaAnsibleMixin, KayobeAnsibleMixin, Command):
def _deploy_servers(self, parsed_args):
self.app.LOG.debug("Deploying overcloud servers via Bifrost")
kolla_ansible.run_seed(parsed_args, "deploy-servers")
extra_vars = {}
if parsed_args.bifrost_limit:
extra_vars["bifrost_limit"] = parsed_args.bifrost_limit
ansible.run_playbook(parsed_args,
"ansible/kolla-bifrost-provision.yml",
extra_vars=extra_vars)
class OvercloudHostConfigure(KollaAnsibleMixin, KayobeAnsibleMixin, Command):

View File

@ -40,6 +40,7 @@ setup(
'configuration_dump = kayobe.cli.commands:ConfigurationDump',
'kolla_ansible_run = kayobe.cli.commands:KollaAnsibleRun',
'overcloud_host_configure = kayobe.cli.commands:OvercloudHostConfigure',
'overcloud_inventory_discover = kayobe.cli.commands:OvercloudInventoryDiscover',
'overcloud_service_deploy = kayobe.cli.commands:OvercloudServiceDeploy',
'overcloud_provision = kayobe.cli.commands:OvercloudProvision',
'playbook_run = kayobe.cli.commands:PlaybookRun',