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',