From 022d05e53e9024e00eb1b476b88f6f795bea25d7 Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Fri, 10 Jun 2016 14:33:32 +0100 Subject: [PATCH] split ironic install role into install,bootstrap,start phases - This change decomposes the install ironic role into 3 phases. - The install phase will install all packages. - The bootstrap phase generates all config files and configures the db. - The start phase starts all biforst/ironic services. - This change adds 3 new variable (skip_package_install, skip_bootstrap, skip_start) to optionally skip the install, bootstrap and start phases - This change splits the inspector_install.yml to reflect the 3 phases. Change-Id: Ifdfc935f594e29eb361ac31e8ae328744848258b --- .../bifrost-ironic-install/defaults/main.yml | 7 + .../tasks/bootstrap.yml | 286 +++++++++++++ .../tasks/inspector_bootstrap.yml | 73 ++++ .../tasks/inspector_install.yml | 62 --- .../tasks/inspector_start.yml | 19 + .../bifrost-ironic-install/tasks/install.yml | 97 +++++ .../bifrost-ironic-install/tasks/main.yml | 384 +----------------- .../bifrost-ironic-install/tasks/start.yml | 57 +++ ...-ironic-install-role-75b9a431bba88bad.yaml | 9 + 9 files changed, 557 insertions(+), 437 deletions(-) create mode 100644 playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml create mode 100644 playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml create mode 100644 playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml create mode 100644 playbooks/roles/bifrost-ironic-install/tasks/install.yml create mode 100644 playbooks/roles/bifrost-ironic-install/tasks/start.yml create mode 100644 releasenotes/notes/decompose-ironic-install-role-75b9a431bba88bad.yaml diff --git a/playbooks/roles/bifrost-ironic-install/defaults/main.yml b/playbooks/roles/bifrost-ironic-install/defaults/main.yml index 199be8d0f..2f8b06ebc 100644 --- a/playbooks/roles/bifrost-ironic-install/defaults/main.yml +++ b/playbooks/roles/bifrost-ironic-install/defaults/main.yml @@ -19,6 +19,13 @@ transform_boot_image: false testing: false ci_testing: false +# set to true to skip installing ironic dependencies +skip_package_install: False +# set to true to skip generation of configs, ironic db and rabbitmq configuration +skip_bootstrap: False +# set to true to skip starting ironic services and dependencies +skip_start: False + # Default network interface that bifrost will be attached to. # This is used in ipa_* so it must be before network_interface: "virbr0" diff --git a/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml b/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml new file mode 100644 index 000000000..1e2846c59 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml @@ -0,0 +1,286 @@ +# 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: "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: "Start rabbitmq-server" + service: name=rabbitmq-server state=started +- name: "RabbitMQ - Testing if hostname is defined in /etc/hosts" + command: grep -i "127.0.0.1.*{{ ansible_hostname }}\ localhost" /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 +- 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: "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 diff --git a/playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml b/playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml new file mode 100644 index 000000000..9a5ca3021 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml @@ -0,0 +1,73 @@ +# 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: "MySQL - Create database" + mysql_db: + login_user={{ mysql_username }} + login_password={{ mysql_password }} + name=inspector + state=present + encoding=utf8 + register: test_created_inspector_db +- name: "MySQL - Create user for inspector" + mysql_user: + login_user={{ mysql_username }} + login_password={{ mysql_password }} + name=inspector + password={{ ironic_db_password }} + priv=inspector.*:ALL + state=present +- name: "Inspector - Ensure /etc/ironic-inspector/ exists" + file: + dest=/etc/ironic-inspector + owner=ironic + group=ironic + mode=0755 + state=directory +- name: "Inspector - Place Configuration" + template: + src=ironic-inspector.conf.j2 + dest=/etc/ironic-inspector/inspector.conf + owner=ironic + group=ironic + mode=0740 +- name: "Inspector - create data folder" + file: + name="{{ inspector_data_dir }}" + state=directory + owner=ironic + group=ironic + mode=0755 +- name: "Inspector - create log folder" + file: + name="{{ inspector_data_dir }}/log" + state=directory + owner=ironic + group=ironic + mode=0755 +- name: "Upgrade inspector DB Schema" + shell: ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade + become: true + environment: "{{ bifrost_venv_env if enable_venv else '{}' }}" +- name: "Inspector - Get ironic-inspector install location" + shell: echo $(dirname $(which ironic-inspector)) + register: ironic_install_prefix + environment: "{{ bifrost_venv_env if enable_venv else '{}' }}" +- name: "Inspector - Place service" + 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-inspector', username: 'ironic', args: '--config-file /etc/ironic-inspector/inspector.conf'} +- name: "Inspector - Explicitly permit TCP/5050 for ironic-inspector callback" + command: iptables -I INPUT -p tcp --dport 5050 -i {{network_interface}} -j ACCEPT diff --git a/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml b/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml index b698dd703..825cb9b0d 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml @@ -21,65 +21,3 @@ include: pip_install.yml package=python-ironic-inspector-client state=latest -- name: "MySQL - Create database" - mysql_db: - login_user={{ mysql_username }} - login_password={{ mysql_password }} - name=inspector - state=present - encoding=utf8 - register: test_created_inspector_db -- name: "MySQL - Create user for inspector" - mysql_user: - login_user={{ mysql_username }} - login_password={{ mysql_password }} - name=inspector - password={{ ironic_db_password }} - priv=inspector.*:ALL - state=present -- name: "Inspector - Ensure /etc/ironic-inspector/ exists" - file: - dest=/etc/ironic-inspector - owner=ironic - group=ironic - mode=0755 - state=directory -- name: "Inspector - Place Configuration" - template: - src=ironic-inspector.conf.j2 - dest=/etc/ironic-inspector/inspector.conf - owner=ironic - group=ironic - mode=0740 -- name: "Inspector - create data folder" - file: - name="{{ inspector_data_dir }}" - state=directory - owner=ironic - group=ironic - mode=0755 -- name: "Inspector - create log folder" - file: - name="{{ inspector_data_dir }}/log" - state=directory - owner=ironic - group=ironic - mode=0755 -- name: "Upgrade inspector DB Schema" - shell: ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade - become: true - environment: "{{ bifrost_venv_env if enable_venv else '{}' }}" -- name: "Inspector - Get ironic-inspector install location" - shell: echo $(dirname $(which ironic-inspector)) - register: ironic_install_prefix - environment: "{{ bifrost_venv_env if enable_venv else '{}' }}" -- name: "Inspector - Place service" - 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-inspector', username: 'ironic', args: '--config-file /etc/ironic-inspector/inspector.conf'} -- name: "Inspector - Explicitly permit TCP/5050 for ironic-inspector callback" - command: iptables -I INPUT -p tcp --dport 5050 -i {{network_interface}} -j ACCEPT -- name: "Inspector - (re)starting ironic-inspector service" - service: - name=ironic-inspector - state=restarted diff --git a/playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml b/playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml new file mode 100644 index 000000000..38d57c956 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml @@ -0,0 +1,19 @@ +# 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: "Inspector - (re)starting ironic-inspector service" + service: + name=ironic-inspector + state=restarted diff --git a/playbooks/roles/bifrost-ironic-install/tasks/install.yml b/playbooks/roles/bifrost-ironic-install/tasks/install.yml new file mode 100644 index 000000000..5cdf11eac --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/install.yml @@ -0,0 +1,97 @@ +# 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 + when: ansible_os_family == 'Debian' +- name: "Install packages" + action: "{{ ansible_pkg_mgr }} name={{ item }} state=present" + with_items: required_packages +# Step required for Ubuntu 14.10 +- name: "Install Ubuntu 14.10 (and later) packages" + action: "{{ ansible_pkg_mgr }} name={{ item }} state=present" + with_items: + - pxelinux + when: > + ansible_distribution_version|version_compare('14.10', '>=') and + ansible_distribution == 'Ubuntu' +- name: "If running in CI, set source install facts just to be sure" + set_fact: + shade_source_install: true + ironicclient_source_install: true + when: ci_testing | bool == true +- name: "If VENV is set in the environment, enable installation into venv" + set_fact: + enable_venv: true + when: lookup('env', 'VENV') | length > 0 +# NOTE(TheJulia) While we don't necessarilly require /opt/stack any longer +# and it should already be created by the Ansible setup, we will leave this +# here for the time being. +- name: "Ensure /opt/stack is present" + file: name=/opt/stack state=directory owner=root group=root +- name: "proliantutils - Install from pip" + include: pip_install.yml + package=proliantutils + state=present + when: skip_install is not defined and testing | bool != true +- name: "UcsSdk - Install from pip" + include: pip_install.yml + package=UcsSdk + version=0.8.1.9 + when: skip_install is not defined and testing | bool != true +- name: "Install iSCSI client if PXE driver support is enabled" + action: "{{ ansible_pkg_mgr }} name={{ iscsi_client_package }} state=present" + when: skip_install is not defined and enable_pxe_drivers | bool == true +- name: "Shade - Install" + include: pip_install.yml + package=shade + state=latest + sourcedir={{ shade_git_folder }} + source_install={{ shade_source_install }} + when: skip_install is not defined +- name: "dib-utils - install from pip" + include: pip_install.yml + package=dib-utils + state=present + when: skip_install is not defined and install_dib | bool == true +- name: "Diskimage-builder - Install" + include: pip_install.yml + package=diskimage-builder + sourcedir={{ dib_git_folder }} + source_install=true + when: skip_install is not defined and install_dib | bool == true +- name: "Ironic Client - Install" + include: pip_install.yml + package=python-ironicclient + state=latest + sourcedir={{ ironicclient_git_folder }} + source_install={{ ironicclient_source_install }} + when: skip_install is not defined +- name: "Install configparser in venv if using" + include: pip_install.yml package=configparser virtualenv=bifrost_venv_dir + when: skip_install is not defined and (enable_venv | bool == true) +- name: "Install pymysql in venv if using" + include: pip_install.yml package=pymysql virtualenv=bifrost_venv_dir + when: skip_install is not defined and (enable_venv | bool == true) +- name: "Install Ironic using pip" + include: pip_install.yml + package=ironic + state=latest + sourcedir={{ ironic_git_folder }} + source_install=true + when: skip_install is not defined +- name: "Install ironic-inspector to permit use of inspection interface" + include: inspector_install.yml + when: enable_inspector | bool == true diff --git a/playbooks/roles/bifrost-ironic-install/tasks/main.yml b/playbooks/roles/bifrost-ironic-install/tasks/main.yml index 6475be90a..1eeb363e4 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/main.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/main.yml @@ -32,378 +32,12 @@ - "../defaults/required_defaults_{{ ansible_distribution }}_{{ ansible_distribution_release }}.yml" - "../defaults/required_defaults_{{ ansible_distribution }}_{{ ansible_distribution_version }}.yml" - "../defaults/dummy-defaults.yml" -- 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: "Update Package Cache" - apt: update_cache=yes - when: ansible_os_family == 'Debian' -- name: "Install packages" - action: "{{ ansible_pkg_mgr }} name={{ item }} state=present" - with_items: required_packages -# Step required for Ubuntu 14.10 -- name: "Install Ubuntu 14.10 (and later) packages" - action: "{{ ansible_pkg_mgr }} name={{ item }} state=present" - with_items: - - pxelinux - when: > - ansible_distribution_version|version_compare('14.10', '>=') and - ansible_distribution == 'Ubuntu' -- name: "If running in CI, set source install facts just to be sure" - set_fact: - shade_source_install: true - ironicclient_source_install: true - when: ci_testing | bool == true -- name: "If VENV is set in the environment, enable installation into venv" - set_fact: - enable_venv: true - when: lookup('env', 'VENV') | length > 0 -# NOTE(TheJulia) While we don't necessarilly require /opt/stack any longer -# and it should already be created by the Ansible setup, we will leave this -# here for the time being. -- name: "Ensure /opt/stack is present" - file: name=/opt/stack state=directory owner=root group=root -- name: "proliantutils - Install from pip" - include: pip_install.yml - package=proliantutils - state=present - when: skip_install is not defined and testing | bool != true -- name: "UcsSdk - Install from pip" - include: pip_install.yml - package=UcsSdk - version=0.8.1.9 - when: skip_install is not defined and testing | bool != true -- name: "Install iSCSI client if PXE driver support is enabled" - action: "{{ ansible_pkg_mgr }} name={{ iscsi_client_package }} state=present" - when: skip_install is not defined and enable_pxe_drivers | bool == true -- name: "Shade - Install" - include: pip_install.yml - package=shade - state=latest - sourcedir={{ shade_git_folder }} - source_install={{ shade_source_install }} - when: skip_install is not defined -- name: "dib-utils - install from pip" - include: pip_install.yml - package=dib-utils - state=present - when: skip_install is not defined and install_dib | bool == true -- name: "Diskimage-builder - Install" - include: pip_install.yml - package=diskimage-builder - sourcedir={{ dib_git_folder }} - source_install=true - when: skip_install is not defined and install_dib | bool == true -- name: "Ironic Client - Install" - include: pip_install.yml - package=python-ironicclient - state=latest - sourcedir={{ ironicclient_git_folder }} - source_install={{ ironicclient_source_install }} - when: skip_install is not defined -- name: "Install configparser in venv if using" - include: pip_install.yml package=configparser virtualenv=bifrost_venv_dir - when: skip_install is not defined and (enable_venv | bool == true) -- name: "Install pymysql in venv if using" - include: pip_install.yml package=pymysql virtualenv=bifrost_venv_dir - when: skip_install is not defined and (enable_venv | bool == true) -- name: "Start database service" - service: name={{ mysql_service_name }} state=started -- name: "Start rabbitmq-server" - service: name=rabbitmq-server state=started -- name: "RabbitMQ - Testing if hostname is defined 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: "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: "Install Ironic using pip" - include: pip_install.yml - package=ironic - state=latest - sourcedir={{ ironic_git_folder }} - source_install=true - when: skip_install is not defined -- 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: "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_install.yml - when: enable_inspector | bool -- 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: "Reload systemd configuration" - command: systemctl daemon-reload - when: init_template == 'systemd_template.j2' -- 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: "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. And the libvirt started dnsmasq processes -# are not controlled by upstart, so we need to manually kill those. -- 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 -- name: "Stop existing libvirt dnsmasq processes" - command: killall -w dnsmasq - when: "{{ testing | bool == true and include_dhcp_server | 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: "Ensure services are running with current config" - service: name={{ item }} state=restarted - with_items: - - xinetd - - nginx -- name: "Ensure dnsmasq is running with current config" - service: name={{ item }} state=restarted - with_items: - - dnsmasq - when: "{{ include_dhcp_server | bool == true }}" -- name: "Send services a reload signal" - service: name={{ item }} state=reloaded - with_items: - - xinetd - - nginx -- name: "Send services a force-reload signal" - service: name=dnsmasq state=restarted - when: "{{ include_dhcp_server | bool == true }}" -- 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 +- name: "Install Ironic deps" + include: install.yml + when: skip_package_install | bool != True +- name: "Bootstrap Ironic" + include: bootstrap.yml + when: skip_bootstrap | bool != True +- name: "Start Ironic services" + include: start.yml + when: skip_start | bool != True diff --git a/playbooks/roles/bifrost-ironic-install/tasks/start.yml b/playbooks/roles/bifrost-ironic-install/tasks/start.yml new file mode 100644 index 000000000..9bb3683e8 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/start.yml @@ -0,0 +1,57 @@ +# 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: "Reload systemd configuration" + command: systemctl daemon-reload + when: init_template == 'systemd_template.j2' +- name: "Start database service" + service: name={{ mysql_service_name }} state=started +- name: "Start rabbitmq-server" + service: name=rabbitmq-server state=started +- name: "start ironic-inspector" + include: inspector_start.yml + when: enable_inspector | bool == true +- 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 +# 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: "Stop existing libvirt dnsmasq processes" + command: killall -w dnsmasq + when: "{{ testing | bool == true and include_dhcp_server | bool == true }}" +- name: "Ensure services are running with current config" + service: name={{ item }} state=restarted + with_items: + - xinetd + - nginx +- name: "Ensure dnsmasq is running with current config" + service: name={{ item }} state=restarted + with_items: + - dnsmasq + when: "{{ include_dhcp_server | bool == true }}" +- name: "Send services a reload signal" + service: name={{ item }} state=reloaded + with_items: + - xinetd + - nginx +- name: "Send services a force-reload signal" + service: name=dnsmasq state=restarted + when: "{{ include_dhcp_server | bool == true }}" diff --git a/releasenotes/notes/decompose-ironic-install-role-75b9a431bba88bad.yaml b/releasenotes/notes/decompose-ironic-install-role-75b9a431bba88bad.yaml new file mode 100644 index 000000000..5bb2dd863 --- /dev/null +++ b/releasenotes/notes/decompose-ironic-install-role-75b9a431bba88bad.yaml @@ -0,0 +1,9 @@ +--- +features: + The ironic install role has been split into 3 phases. + (install) installs all ironic packages and dependencies + (bootstrap) the bootstrap pahse generates configs + and initializes the ironic db. + (start) starts all ironic services and dependencies. + Each phase is run by default and can be skiped by defining + skip_package_install,skip_bootstrap and skip_start respectively.