5a180949a2
Refactor the ironic-install role so that it can be used on Centos and RHEL. Also add a new template for systemd configuration so we can install and run the ironic services. Document the additional steps that RHEL and CentOS users will need to take to get bifrost up and running. Install gcc in env-setup.sh as it is needed to install pip and we can't take it for granted. Temporarily remove amttool from RedHat family dependencies since it's not currently packaged for RHEL or CentOS 7. We'll handle this in a separate patch. Change libxslt-dev to libxslt1-dev as it is the correct name for the package. Closes-Bug: 1460930 Closes-Bug: 1456896 Partial-Bug: 1463871 Change-Id: I72a5b329d3c55350644a777b5a77d61947c921bc
279 lines
14 KiB
YAML
279 lines
14 KiB
YAML
# 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: Include OS-specific packages variables.
|
|
include_vars: "{{ item }}"
|
|
with_first_found:
|
|
- "../defaults/required_defaults_{{ ansible_distribution }}.yml"
|
|
- "../defaults/required_defaults_{{ ansible_os_family }}.yml"
|
|
- name: "Update Package Cache"
|
|
apt: update_cache=yes
|
|
when: ansible_os_family == 'Debian'
|
|
- name: "Install packages"
|
|
action: "{{ ansible_pkg_mgr }} name={{ item }}"
|
|
with_items: required_packages
|
|
# Step required for Ubuntu 14.10
|
|
- name: "Install 14.10 packages"
|
|
action: "{{ ansible_pkg_mgr }} name={{ item }}"
|
|
with_items:
|
|
- pxelinux
|
|
when: ansible_distribution_version|version_compare('14.10', '>=') and ansible_distribution == 'Ubuntu'
|
|
- name: "Ensuring /opt/stack is present"
|
|
file: name=/opt/stack state=directory owner=root group=root
|
|
- name: "Downloading Ironic"
|
|
command: git clone {{ ironic_git_url }} 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/
|
|
- name: "Ironic - Apply CI changes if necessary"
|
|
script: parse_zuul_changes.py /opt/stack/ironic https://review.openstack.org openstack/ironic "{{ lookup('env', 'ZUUL_CHANGES') }}"
|
|
when: ci_testing == true
|
|
- name: "Ironic Client - Install from source if configured to do so."
|
|
include: ironicclient_source_install.yml
|
|
when: skip_install is not defined and ((ironicclient_source_install is defined and ironicclient_source_install == true) or ci_testing == true)
|
|
- name: "Ironic Client - Install from pip"
|
|
pip: name=python-ironicclient state=present
|
|
when: skip_install is not defined and (ironicclient_source_install is not defined or ironicclient_source_install == false) and (ci_testing == false)
|
|
- name: "proliantutils - Install from pip"
|
|
pip: name=proliantutils state=present
|
|
when: skip_install is not defined
|
|
- name: "Shade - Install from source if configured to do so"
|
|
include: shade_source_install.yml
|
|
when: skip_install is not defined and ((shade_source_install is defined and shade_source_install == true) or ci_testing == true)
|
|
- name: "Shade - Installing patched shade library."
|
|
pip: name=shade state=latest
|
|
when: skip_install is not defined and (shade_source_install is not defined or shade_source_install == false) and (ci_testing == false)
|
|
- name: "dib-utils - install from pip"
|
|
pip: name=dib-utils state=present
|
|
when: skip_install is not defined and create_image_via_dib == true
|
|
- name: "Include diskimage-builder installation"
|
|
include: dib_install.yml
|
|
when: create_image_via_dib == true
|
|
- name: "Starting database service"
|
|
service: name={{ mysql_service_name }} 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
|
|
when: ci_testing_zuul is not defined
|
|
- 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
|
|
when: ci_testing_zuul is not defined
|
|
- name: "MySQL - Creating DB - OpenStack CI"
|
|
mysql_db: login_user=openstack_citest login_password=openstack_citest name=ironic state=present encoding=utf8
|
|
register: test_created_db
|
|
when: ci_testing_zuul is defined
|
|
- name: "MySQL - Creating user for Ironic - OpenStack CI"
|
|
mysql_user: login_user=openstack_citest login_password=openstack_citest name=ironic password={{ ironic_db_password }} priv=ironic.*:ALL state=present
|
|
when: ci_testing_zuul is defined
|
|
- 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"
|
|
command: cp -p /home/ironic/.ssh/id_rsa.pub /home/ironic/.ssh/authorized_keys
|
|
when: testing == true
|
|
- name: "Placing services"
|
|
template: src={{ init_template }} dest={{ init_dest_dir }}{{item.service_name}}{{ init_ext }} 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: "Reload systemd configuration"
|
|
command: systemctl daemon-reload
|
|
when: ansible_os_family == 'RedHat'
|
|
- 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=restarted
|
|
- 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={{ syslinux_tftp_dir }}/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={{ ipxe_dir }}/undionly.kpxe dest=/tftpboot/
|
|
- name: "Deploy dnsmasq configuration file"
|
|
template: src=dnsmasq.conf.j2 dest=/etc/dnsmasq.conf
|
|
when: "{{include_dhcp_server|bool}}"
|
|
# 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
|
|
when: "{{include_dhcp_server|bool}}"
|
|
- name: "Disabling libvirt dnsmasq config"
|
|
command: mv /etc/dnsmasq.d/libvirt-bin /etc/dnsmasq.d/libvirt-bin~
|
|
when: "{{include_dhcp_server|bool and test_libvirt_dnsmasq.stat.exists|bool and testing|bool}}"
|
|
- name: "Stopping existing libvirt dnsmasq processes"
|
|
command: killall -w dnsmasq
|
|
when: "{{testing|bool and include_dhcp_server|bool}}"
|
|
# 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 {{ sgabios_dir }}"
|
|
stat: path={{ sgabios_dir }}/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 services are running with current config"
|
|
service: name={{ item }} state=restarted
|
|
with_items:
|
|
- xinetd
|
|
- nginx
|
|
- name: "Ensuring dnsmasq is running with current config"
|
|
service: name={{ item }} state=restarted
|
|
with_items:
|
|
- dnsmasq
|
|
when: "{{include_dhcp_server|bool}}"
|
|
- name: "Sending services a reload signal"
|
|
service: name={{ item }} state=reloaded
|
|
with_items:
|
|
- xinetd
|
|
- nginx
|
|
- name: "Sending services a force-reload signal"
|
|
service: name=dnsmasq state=restarted
|
|
when: "{{include_dhcp_server|bool}}"
|
|
# 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={{ deploy_kernel_upstream_url }} 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={{ deploy_ramdisk_upstream_url }} dest={{ http_boot_folder }}/coreos_production_pxe_image-oem.cpio.gz
|
|
when: test_core_os_image_present.stat.exists == false
|
|
- name: "Download cirros to use for deployment if requested"
|
|
get_url: url={{ cirros_deploy_image_upstream_url }} dest="{{ deploy_image }}"
|
|
when: "{{use_cirros|bool}}"
|
|
- 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={{ deploy_image_upstream_url }} 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"
|
|
unarchive: src=/httpboot/ubuntu-14.04-server-cloudimg-amd64.tar.gz dest=/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 image 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
|
|
- name: "Explicitly permit nginx port (TCP) for file downloads from nodes to be provisioned"
|
|
command: iptables -I INPUT -p tcp --dport {{nginx_port}} -i {{network_interface}} -j ACCEPT
|
|
- name: "Explicitly permit TCP/6385 for IPA callback"
|
|
command: iptables -I INPUT -p tcp --dport 6385 -i {{network_interface}} -j ACCEPT
|