bifrost/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml

345 lines
12 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: "Fail if authentication configuration conflicts."
fail:
msg: >
noauth_mode and enable_keystone are mutually exclusive options.
Please set one to "false".
when: >
noauth_mode | bool == true and enable_keystone is defined and
enable_keystone | bool == true
- name: "Warn if deprecated variable nginx_port is set"
debug:
msg: >
WARNING - nginx_port is a deprecated variable and support will be
removed during the Newton cycle.
when: nginx_port is defined
- name: "If VENV is set in the environment, enable installation into venv"
set_fact:
enable_venv: true
when: lookup('env', 'VENV') | length > 0
# NOTE(sean-k-mooney) only the RabbitMQ server and MySQL db are started
# during bootstrapping. all other services are started in the Start phase.
- name: "Start database service"
service: name={{ mysql_service_name }} state=started
- name: "RabbitMQ - Testing if hostname is defined in /etc/hosts"
command: grep -i "{{ ansible_hostname }}" /etc/hosts
ignore_errors: yes
register: test_grep_fix_hostname
# NOTE(sean-k-mooney) in a docker container this will fail so /etc/hosts
# should be fixed before running the bootstrap phase in a container.
- name: "RabbitMQ - Fixing /etc/hosts"
command: sed -i 's/localhost/{{ ansible_hostname }} localhost/' /etc/hosts
when: test_grep_fix_hostname.rc != 0
# NOTE(hwoarang): The erlang SUSE package forces epmd to listen on localhost
# address which breaks rabbitmq-server when listening on a different address.
# Make sure the systemd service and socket are stopped so rabbitmq-server will
# start epmd on its own (https://bugzilla.suse.com/show_bug.cgi?id=1003085)
- name: "Stop and disable the epmd service and socket on SUSE"
service: name={{ item }} state=stopped enabled=no
with_items:
- epmd.socket
- epmd
when: ansible_os_family == 'Suse'
- name: "Start rabbitmq-server"
service: name=rabbitmq-server state=started
# NOTE(cinerama): on some systems, rabbit may not be ready when we want to
# make changes to users if we don't wait first
- name: "Wait for rabbitmq"
wait_for: port=5672 delay=5
- name: "Ensure guest user is removed from rabbitmq"
rabbitmq_user:
user: "guest"
state: absent
force: yes
- name: "Create 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: "Set mysql_username if environment variable mysql_user is set"
set_fact:
mysql_username: "{{ lookup('env', 'mysql_user') }}"
when: lookup('env', 'mysql_user') | length > 0
no_log: true
- name: "Set mysql_password if environment variable mysql_pass is set"
set_fact:
mysql_password: "{{ lookup('env', 'mysql_pass') }}"
when: lookup('env', 'mysql_pass') | length > 0
no_log: true
- name: "MySQL - Creating DB"
mysql_db:
name: "ironic"
state: present
encoding: utf8
login_user: "{{ mysql_username | default(None) }}"
login_password: "{{ mysql_password | default(None) }}"
register: test_created_db
- name: "MySQL - Creating user for Ironic"
mysql_user:
name: "ironic"
password: "{{ ironic_db_password }}"
priv: "ironic.*:ALL"
state: present
login_user: "{{ mysql_username | default(None) }}"
login_password: "{{ mysql_password | default(None) }}"
- name: "Create an ironic service group"
group:
name: "ironic"
- name: "Create an ironic service user"
user:
name: "ironic"
group: "ironic"
- name: "Ensure /etc/ironic exists"
file:
name: "/etc/ironic"
state: directory
owner: "ironic"
group: "ironic"
mode: 0755
# Note(TheJulia): The rootwrap copies will need to be re-tooled
# to possibly directly retreive current files if a source install
# is not utilized.
- name: "Copy rootwrap.conf from ironic source folder"
copy:
src: "{{ ironic_git_folder }}/etc/ironic/rootwrap.conf"
dest: "/etc/ironic/rootwrap.conf"
mode: 0644
owner: root
group: root
when: skip_install is not defined and enable_pxe_drivers | bool == true
- name: "Copy rootwrap.d contents from ironic source folder"
copy:
src: "{{ ironic_git_folder }}/etc/ironic/rootwrap.d/"
dest: "/etc/ironic/rootwrap.d"
mode: 0644
owner: root
group: root
when: skip_install is not defined and enable_pxe_drivers | bool == true
- name: "Populate keystone for Bifrost"
include: keystone_setup.yml
when: enable_keystone is defined and enable_keystone | bool == true
- name: "Generate ironic Configuration"
include: ironic_config.yml
- name: "Copy policy.json to /etc/ironic"
copy:
src: "{{ ironic_git_folder }}/etc/ironic/policy.json"
dest: "/etc/ironic/"
owner: "ironic"
group: "ironic"
mode: 0644
- name: "Create ironic DB Schema"
command: ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema
environment: "{{ bifrost_venv_env if enable_venv else '{}' }}"
when: test_created_db.changed | bool == true
- name: "Upgrade ironic DB Schema"
command: ironic-dbsync --config-file /etc/ironic/ironic.conf upgrade
environment: "{{ bifrost_venv_env if enable_venv else '{}' }}"
when: test_created_db.changed | bool == false
- name: "Do RedHat-specific changes for libvirt"
include: redhat_libvirt_changes.yml
when: ansible_os_family == 'RedHat'
- name: "Add ironic user to virtualization group"
user: name=ironic group="{{ virt_group }}" append=yes
when: testing | bool == true
- name: "Create SSH directory for ironic user"
local_action: >
file
path=/home/ironic/.ssh
owner=ironic
group=ironic
mode=0700
state=directory
when: testing | bool == true
- name: "Check for ironic user SSH key"
local_action: stat path=/home/ironic/.ssh/id_rsa
register: test_ironic_pvt_key
- name: "Generate SSH key for ironic user"
local_action: command ssh-keygen -f /home/ironic/.ssh/id_rsa -N ""
when: >
testing | bool == true and
test_ironic_pvt_key.stat.exists | bool == false
- name: "Set 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 | bool == true and
test_ironic_pvt_key.stat.exists | bool == false
- name: "Set 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 | bool == true and test_ironic_pvt_key.stat.exists | bool == false
- name: "Create authorized_keys file for ironic user"
command: >
cp -p /home/ironic/.ssh/id_rsa.pub /home/ironic/.ssh/authorized_keys
when: testing | bool == true
- name: "Create service folder if systemd template is defined"
file:
path: "{{ init_dest_dir }}"
state: directory
mode: 0755
when: init_template == 'systemd_template.j2'
- name: "Install ironic-inspector to permit use of inspection interface"
include: inspector_bootstrap.yml
when: enable_inspector | bool == true
- name: "Get ironic-api & ironic-conductor install location"
shell: echo $(dirname $(which ironic-api))
register: ironic_install_prefix
environment: "{{ bifrost_venv_env if enable_venv else '{}' }}"
- name: "Set permissions for /var/lib/ironic for the ironic user"
file:
path: "{{ item }}"
state: directory
mode: 0750
owner: "ironic"
group: "ironic"
with_items:
- "/var/lib/ironic"
- "/var/lib/ironic/images"
- name: "Place ironic services"
template:
src: "{{ init_template }}"
dest: "{{ init_dest_dir }}{{ item.service_name }}{{ init_ext }}"
owner: "root"
group: "root"
with_items:
- { service_path: "{{ ironic_install_prefix.stdout }}", service_name: 'ironic-api', username: 'ironic', args: '--config-file /etc/ironic/ironic.conf'}
- { service_path: "{{ ironic_install_prefix.stdout }}", service_name: 'ironic-conductor', username: 'ironic', args: '--config-file /etc/ironic/ironic.conf'}
- name: "Create and populate /tftpboot"
include: create_tftpboot.yml
- name: "Setup Inventory Hosts Directory"
file:
path: "/etc/dnsmasq.d/bifrost.hosts.d"
state: directory
owner: "root"
group: "root"
mode: 0755
when: "{{ inventory_dhcp | bool == true }}"
- name: "Setup Inventory DHCP Hosts Directory"
file:
path: "/etc/dnsmasq.d/bifrost.dhcp-hosts.d"
state: directory
owner: "root"
group: "root"
mode: 0755
when: "{{ inventory_dhcp | bool == true }}"
- name: "Deploy dnsmasq configuration file"
template: src=dnsmasq.conf.j2 dest=/etc/dnsmasq.conf
when: "{{ include_dhcp_server | bool == true }}"
# NOTE(Shrews) When testing, we want to use our custom dnsmasq.conf file,
# not the one supplied by libvirt.
- name: "Look for libvirt dnsmasq config"
stat: path=/etc/dnsmasq.d/libvirt-bin
register: test_libvirt_dnsmasq
when: "{{ include_dhcp_server | bool == true }}"
- name: "Disable libvirt dnsmasq config"
command: mv /etc/dnsmasq.d/libvirt-bin /etc/dnsmasq.d/libvirt-bin~
when: >
include_dhcp_server | bool == true and
test_libvirt_dnsmasq.stat.exists | bool == true and
testing | bool == 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: "Enable IP forwarding in sysctl"
sysctl:
name: "net.ipv4.ip_forward"
value: 1
sysctl_set: yes
state: present
reload: yes
when: testing | bool == true
# NOTE(Shrews) Ubuntu packaging+apparmor issue prevents libvirt from loading
# the ROM from /usr/share/misc.
- name: "Look for sgabios in {{ sgabios_dir }}"
stat: path={{ sgabios_dir }}/sgabios.bin
register: test_sgabios_qemu
- name: "Look 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 | bool == true
- name: "Deploy nginx configuration file for serving HTTP requests"
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: "Download Ironic Python Agent kernel & image"
include: download_ipa_image.yml
when: create_ipa_image | bool == false and download_ipa | bool == true
- name: "Download cirros to use for deployment if requested"
get_url:
url: "{{ cirros_deploy_image_upstream_url }}"
dest: "{{ deploy_image }}"
when: "{{ use_cirros | bool == true }}"
- name: >
"Explicitly permit nginx port (TCP) for
file downloads from nodes to be provisioned"
command: >
iptables -I INPUT -p tcp --dport {{file_url_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
- block:
- name: "Explicitly allow nginx and IPA port (TCP) on selinux"
seport:
ports: "{{ file_url_port }},6385"
proto: tcp
setype: http_port_t
state: present
- name: "Add proper context on created data for http_boot"
command: semanage fcontext -a -t httpd_sys_content_t "{{ http_boot_folder }}(/.*)?"
- name: Copy ironic policy file to temporary directory
copy:
src: ironic_policy.te
dest: /tmp/ironic_policy.te
- name: Check ironic policy module
command: checkmodule -M -m -o /tmp/ironic_policy.mod /tmp/ironic_policy.te
- name: Package ironic policy module
command: semodule_package -m /tmp/ironic_policy.mod -o /tmp/ironic_policy.pp
- name: Include ironic policy module
command: semodule -i /tmp/ironic_policy.pp
- name: Enable ironic policy module
command: semodule -e ironic_policy
when: (ansible_os_family == 'RedHat' or ansible_os_family == 'Suse') and
ansible_selinux.status == 'enabled' and ansible_selinux.mode == "enforcing"