From b05f02391ce0716cda11100cb6c45f8447db95ea Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Wed, 15 Mar 2017 09:44:36 +0000 Subject: [PATCH] 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. --- ansible/group_vars/controllers/ansible-host | 3 + ansible/kolla-bifrost-hostvars.yml | 46 ++++++++++++++ ansible/kolla-bifrost-provision.yml | 67 +++++++++++++++++++++ ansible/overcloud-inventory-discover.yml | 35 +++++++++++ kayobe/cli/commands.py | 33 +++++++++- setup.py | 1 + 6 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 ansible/group_vars/controllers/ansible-host create mode 100644 ansible/kolla-bifrost-hostvars.yml create mode 100644 ansible/kolla-bifrost-provision.yml create mode 100644 ansible/overcloud-inventory-discover.yml diff --git a/ansible/group_vars/controllers/ansible-host b/ansible/group_vars/controllers/ansible-host new file mode 100644 index 000000000..9bf317056 --- /dev/null +++ b/ansible/group_vars/controllers/ansible-host @@ -0,0 +1,3 @@ +--- +# Host/IP with which to access the controllers via SSH. +ansible_host: "{{ provision_oc_net_name | net_ip }}" diff --git a/ansible/kolla-bifrost-hostvars.yml b/ansible/kolla-bifrost-hostvars.yml new file mode 100644 index 000000000..1b0a44c31 --- /dev/null +++ b/ansible/kolla-bifrost-hostvars.yml @@ -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 diff --git a/ansible/kolla-bifrost-provision.yml b/ansible/kolla-bifrost-provision.yml new file mode 100644 index 000000000..27035516d --- /dev/null +++ b/ansible/kolla-bifrost-provision.yml @@ -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 }}" diff --git a/ansible/overcloud-inventory-discover.yml b/ansible/overcloud-inventory-discover.yml new file mode 100644 index 000000000..7719cdf1b --- /dev/null +++ b/ansible/overcloud-inventory-discover.yml @@ -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" diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 038fd2a65..e74328f58 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -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): diff --git a/setup.py b/setup.py index 00849af09..5dd1315d5 100644 --- a/setup.py +++ b/setup.py @@ -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',