# Copyright (c) 2015 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. --- - name: "Update Package Cache" apt: update_cache=yes - name: "Install packages" apt: name={{ item }} with_items: required_packages_ubuntu # Step required for Ubuntu 14.10 - name: "Install 14.10 packages" apt: name={{ item }} with_items: - pxelinux when: ansible_distribution_version|version_compare('14.10', '>=') - name: "Install testing packages" apt: name={{ item }} when: testing is defined and testing == true with_items: - libvirt-bin - qemu-utils - qemu-kvm - sgabios - name: "Ensuring /opt/stack is present" file: name=/opt/stack state=directory owner=root group=root - name: "Retrieving latest known os_ironic.py file" get_url: url={{ latest_os_ironic_url }} dest=/opt/stack/ansible/lib/ansible/modules/extras/cloud/os_ironic.py - name: "Retrieving latest known os_ironic_node.py file" get_url: url={{ latest_os_ironic_node_url }} dest=/opt/stack/ansible/lib/ansible/modules/extras/cloud/os_ironic_node.py - name: "Downloading Ironic" command: git clone https://git.openstack.org/openstack/ironic chdir=/opt/stack creates=/opt/stack/ironic - name: "Ironic - checking out master branch" command: git checkout -f master chdir=/opt/stack/ironic - name: "Ironic - resetting master branch" command: git reset --hard master chdir=/opt/stack/ironic - name: "Ironic - resyncing to current master branch" command: git pull --ff-only chdir=/opt/stack/ironic/ # TODO: Remove this once it has landed. - name: "Ironic - Temporary - Retrieve 166903" shell: git fetch https://jkreger@review.openstack.org/openstack/ironic refs/changes/03/166903/4 && git checkout FETCH_HEAD chdir=/opt/stack/ironic # TODO: The pip installation of python-ironicclient is disabled in order to # support rev 158520. #- name: "Install ironic client" # pip name=python-ironicclient state=present - name: "python-ironicclient - Retrieving library from git.openstack.org" command: git clone https://review.openstack.org/openstack/python-ironicclient chdir=/opt/stack creates=/opt/stack/python-ironicclient - name: "python-ironicclient - Checking out master branch" command: git checkout -f master chdir=/opt/stack/python-ironicclient - name: "python-ironicclient - Resetting local repository" command: git reset --hard master chdir=/opt/stack/python-ironicclient - name: "python-ironicclient - Resyncing local repository" command: git pull --ff-only chdir=/opt/stack/python-ironicclient # This patch is https://review.openstack.org/#/c/158520/ which adds support # for use of node names instead of UUIDs. We don't presently utilize this # but it can be supported at some point. - name: "python-ironicclient - Downloading patch for logical names in Ironic" command: git fetch https://review.openstack.org/openstack/python-ironicclient refs/changes/20/158520/1 chdir=/opt/stack/python-ironicclient - name: "python-ironicclient - Checking out patch." command: git checkout FETCH_HEAD chdir=/opt/stack/python-ironicclient - name: "python-ironicclient - Installing patched python-ironicclient library." command: pip install -I --force-reinstall /opt/stack/python-ironicclient when: skip_install is not defined - name: "proliantutils - Install from pip" pip: name=proliantutils state=present when: skip_install is not defined # TODO: The next package is installed via git and then manyally installed # as the os_ironic and os_ironic_node are under active development and # may require features that have not yet been released in shade. # TODO: If the portion below remains for any period of time, it should # be converted to an include... or consider converting to the integrated # git module. - name: "Shade - Retrieving library from git.openstack.org" command: git clone https://review.openstack.org/openstack-infra/shade chdir=/opt/stack creates=/opt/stack/shade - name: "Shade - Checking out master branch" command: git checkout -f master chdir=/opt/stack/shade - name: "Shade - Resetting local repository" command: git reset --hard master chdir=/opt/stack/shade - name: "Shade - Resyncing local repository" command: git pull --ff-only chdir=/opt/stack/shade - name: "Shade - Installing patched shade library." command: pip install -I --force-reinstall /opt/stack/shade when: skip_install is not defined - name: "Include diskimage-builder installation" include: dib_install.yml when: create_image_via_dib == true - name: "Starting MySQL" service: name=mysql state=started - name: "Starting rabbitmq-server" service: name=rabbitmq-server state=started - name: "RabbitMQ - Testing if hostname is defined firsts in /etc/hosts" command: grep -i "127.0.0.1*.{{ ansible_hostname }}\ localhost" /etc/hosts ignore_errors: yes register: test_grep_fix_hostname - name: "RabbitMQ - Fixing /etc/hosts" command: sed -i 's/localhost/{{ ansible_hostname }} localhost/' /etc/hosts when: test_grep_fix_hostname.rc != 0 - name: "Ensuring guest user is removed from rabbitmq" rabbitmq_user: user=guest state=absent force=yes - name: "Creating Ironic user in RabbitMQ" rabbitmq_user: user=ironic password={{ ironic_db_password }} force=yes state=present configure_priv=.* write_priv=.* read_priv=.* no_log: true - name: "MySQL - Creating DB" mysql_db: login_user=root login_password={{ mysql_password }} name=ironic state=present encoding=utf8 register: test_created_db no_log: True - name: "MySQL - Creating user for Ironic" mysql_user: login_user=root login_password={{ mysql_password }} name=ironic password={{ ironic_db_password }} priv=ironic.*:ALL state=present no_log: True - name: "Install Ironic using pip" pip: name=/opt/stack/ironic state=latest when: skip_install is not defined - name: "Ensure /etc/ironic exists" file: name=/etc/ironic state=directory - name: "Place Ironic Config file" template: src=ironic.conf.j2 dest=/etc/ironic/ironic.conf - name: "Place Ironic IPA Agent PXE configuration file" template: src=agent_config.template.j2 dest=/etc/ironic/agent_config.template - name: "Copy policy.json to /etc/ironic" copy: src=/opt/stack/ironic/etc/ironic/policy.json dest=/etc/ironic/ - name: "Creating Ironic DB Schema" command: ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema when: test_created_db.changed == true - name: "Upgrading Ironic DB Schema" command: ironic-dbsync --config-file /etc/ironic/ironic.conf upgrade when: test_created_db.changed == false - name: "Creating an ironic service group" group: name=ironic - name: "Creating an ironic service user" user: name=ironic group=ironic - name: "Adding ironic user to libvirtd group" user: name=ironic group=libvirtd append=yes when: testing == true - name: "Creating SSH directory for ironic user" local_action: file path=/home/ironic/.ssh owner=ironic group=ironic mode=0700 state=directory when: testing == true - name: "Checking for ironic user SSH key" local_action: stat path=/home/ironic/.ssh/id_rsa register: test_ironic_pvt_key - name: "Generating SSH key for ironic user" local_action: command ssh-keygen -f /home/ironic/.ssh/id_rsa -N "" when: testing == true and test_ironic_pvt_key.stat.exists == false - name: "Setting ownership on ironic SSH private key" local_action: file name=/home/ironic/.ssh/id_rsa owner=ironic group=ironic mode=0600 state=file when: testing == true and test_ironic_pvt_key.stat.exists == false - name: "Setting ownership on ironic SSH public key" local_action: file name=/home/ironic/.ssh/id_rsa.pub owner=ironic group=ironic mode=0644 state=file when: testing == true and test_ironic_pvt_key.stat.exists == false - name: "Creating authorized_keys file for ironic user" local_action: command cp -p /home/ironic/.ssh/id_rsa.pub /home/ironic/.ssh/authorized_keys when: testing == true - name: "Placing services" template: src=init_template.j2 dest=/etc/init/{{item.service_name}}.conf owner=root group=root with_items: - { service_name: 'ironic-api', username: 'ironic', args: '--config-file /etc/ironic/ironic.conf'} - { service_name: 'ironic-conductor', username: 'ironic', args: '--config-file /etc/ironic/ironic.conf'} - name: "Start ironic-conductor" service: name=ironic-conductor state=started - name: "Start ironic-api" service: name=ironic-api state=started - name: "Start ironic-conductor" service: name=ironic-conductor state=restarted - name: "Start ironic-api" service: name=ironic-api state=reloaded - name: "Setting up PXE and iPXE folders" file: name={{item}} owner=ironic group=ironic state=directory with_items: - /tftpboot - /tftpboot/pxelinux.cfg - "{{ http_boot_folder }}" - name: "Placing tftpd map-file" copy: src=tftpboot-map-file dest=/tftpboot/map-file owner=ironic group=ironic - name: "Disable service tftpd-hpa" service: name=tftpd-hpa state=stopped enabled=no - name: "Placing pxelinux.0 (pre-14.10)" copy: src=/usr/lib/syslinux/pxelinux.0 dest=/tftpboot when: ansible_distribution_version|version_compare('14.10', '<') - name: "Placing pxelinux.0 (>=14.10)" copy: src=/usr/lib/PXELINUX/pxelinux.0 dest=/tftpboot when: ansible_distribution_version|version_compare('14.10', '>=') - name: "Place boot.ipxe helper script to HTTP root" copy: src=boot.ipxe dest=/httpboot/boot.ipxe - name: "Place tftp config file" copy: src=xinetd.tftp dest=/etc/xinetd.d/tftp - name: "Copy iPXE image into place" copy: src=/usr/lib/ipxe/undionly.kpxe dest=/tftpboot/ - name: "Deploy dnsmasq configuration file" template: src=dnsmasq.conf.j2 dest=/etc/dnsmasq.conf # NOTE(Shrews) When testing, we want to use our custom dnsmasq.conf file, # not the one supplied by libvirt. And the libvirt started dnsmasq processes # are not controlled by upstart, so we need to manually kill those. - name: "Looking for libvirt dnsmasq config" stat: path=/etc/dnsmasq.d/libvirt-bin register: test_libvirt_dnsmasq - name: "Disabling libvirt dnsmasq config" command: mv /etc/dnsmasq.d/libvirt-bin /etc/dnsmasq.d/libvirt-bin~ when: test_libvirt_dnsmasq.stat.exists == true and testing == true - name: "Stopping existing libvirt dnsmasq processes" command: killall -w dnsmasq when: testing == true # NOTE(Shrews) We need to enable ip forwarding for the libvirt bridge to # operate properly with dnsmasq. This should be done before starting dnsmasq. - name: "Enabling IP forwarding in sysctl" sysctl: name="net.ipv4.ip_forward" value=1 sysctl_set=yes state=present reload=yes when: testing == true # NOTE(Shrews) Ubuntu packaging+apparmor issue prevents libvirt from loading # the ROM from /usr/share/misc. - name: "Looking for sgabios in /usr/share/qemu" stat: path=/usr/share/qemu/sgabios.bin register: test_sgabios_qemu - name: "Looking for sgabios in /usr/share/misc" stat: path=/usr/share/misc/sgabios.bin register: test_sgabios_misc - name: "Place sgabios.bin" command: cp /usr/share/misc/sgabios.bin /usr/share/qemu/sgabios.bin when: test_sgabios_qemu == false and test_sgabios_misc == true and testing == true - name: "Deploying nginx configuration file for serving HTTP requests" template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf - name: "Ensuring dnsmasq is running" service: name={{ item }} state=started with_items: - xinetd - dnsmasq - nginx - name: "Sending services a reload signal" service: name={{ item }} state=reloaded with_items: - xinetd - nginx - name: "Sending services a force-reload signal" command: /etc/init.d/dnsmasq force-reload # Similar logic to below can be utilized to retrieve files - name: "Determine if folder exists, else create and populate folder." stat: path=/tftpboot/master_images register: test_master_images - name: "Create master_images folder" file: name=/tftpboot/master_images state=directory owner=ironic group=ironic when: test_master_images.stat.exists == false # This is overly complex, however get_url will always re-retrieve the file # if it already exists, and this is to prevent that behavior. - name: "Test if CoreOS kernel is present" stat: path={{ http_boot_folder }}/coreos_production_pxe.vmlinuz register: test_core_os_kernel_present - name: "Download CoreOS kernel" get_url: url=http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe.vmlinuz dest={{ http_boot_folder }}/coreos_production_pxe.vmlinuz when: test_core_os_kernel_present.stat.exists == false - name: "Test if CoreOS image is present" stat: path={{ http_boot_folder }}/coreos_production_pxe_image-oem.cpio.gz register: test_core_os_image_present - name: "Download CoreOS image" get_url: url=http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe_image-oem.cpio.gz dest={{ http_boot_folder }}/coreos_production_pxe_image-oem.cpio.gz when: test_core_os_image_present.stat.exists == false - name: "Test if Ubuntu 14.04 server cloud amd64 is present" stat: path={{ deploy_image }} register: test_os_image_present - name: "Download Ubuntu image" get_url: url=http://cloud-images.ubuntu.com/releases/trusty/release/ubuntu-14.04-server-cloudimg-amd64.tar.gz dest=/httpboot/ubuntu-14.04-server-cloudimg-amd64.tar.gz when: test_os_image_present.stat.exists == false and create_image_via_dib == false - name: "Extract Ubuntu image" command: tar -xvzf ubuntu-14.04-server-cloudimg-amd64.tar.gz chdir=/httpboot creates=/httpboot/trusty-server-cloudimg-amd64.img when: test_os_image_present.stat.exists == false and create_image_via_dib == false # Create bootable image takes a partition image, prepends space for a # bootloader, partition table, and then installs the bootloader. # # If attempting to utilize a base Ubuntu image, diskimage-builder # is the recommended, and default path. - name: "Creating bootable image" include: create_bootable_image.yml when: test_os_image_present.stat.exists == false and transform_boot_image == true and create_image_via_dib == false # DIB is presently the default path. - name: "Creating image via disk imae builder" include: create_dib_image.yml when: test_os_image_present.stat.exists == false and transform_boot_image == false and create_image_via_dib == true