Initial support for virtualenv installation

In order to avoid dependency issues, etc., we would like
the ability to use bifrost with a python venv. Provide
experimental support in the install role for venv but
leave it off by default.

Implements: blueprint bifrost-venv-use
Change-Id: I3d6e01825358fcd766ae890bde10fa14fb0b28be
This commit is contained in:
stephane 2015-10-16 11:29:49 -07:00
parent 3068f7ca6d
commit b360a0c3f2
8 changed files with 206 additions and 14 deletions

View File

@ -475,3 +475,21 @@ for mass node deployment.
The OneView documentation can be found
`here <http://docs.openstack.org/developer/ironic/drivers/oneview.html>`_.
Virtualenv installation support (EXPERIMENTAL)
==============================================
Bifrost can be used with a python virtual environment. At present,
this feature is experimental, so it's disabled by default. If you
would like to use a virtual environment, you'll need to modify the
install steps slightly. To set up the virtual environment and install
ansible into it, run ``env-setup.sh`` as follows::
export VENV=/opt/stack/bifrost
./scripts/env-setup.sh
Then run the install playbook with the following arguments::
ansible-playbook -vvvv -i inventory/localhost install.yaml
This will install ironic and its dependencies into the virtual environment.

View File

@ -193,6 +193,26 @@ inspector_store_ramdisk_logs: Boolean value, default true. Controls if the
inspector agent will retain logs from the
ramdisk that called the inspector service.
### Virtual Environment Install
Bifrost can install ironic into a python virtual environment using the
following configuration options:
enable_venv: Enables virtual environment support. Boolean value; the default
is false. enable_venv is automatically defined as true if VENV
is set in the user's environment.
bifrost_venv_dir: The full path of the virtual environment directory. The
default value is /opt/stack/bifrost. When VENV is set in
the user's environment, its contents will be used to set
bifrost_venv_dir.
bifrost_venv_env: An environment dictionary that includes the environment
variables used to run commands which require the virtual
environment. The default values are derived from the
standard 'activate' script which virtualenv installs.
It is best not to reset this value unless you know you
need to.
Notes
-----

View File

@ -113,3 +113,11 @@ enable_pxe_drivers: true
# Comma-separated list of PXE drivers to enable when
# enable_pxe_drivers is set to true
pxe_drivers: "pxe_amt,pxe_ssh,pxe_ipmitool,pxe_ilo"
# Settings related to installing bifrost in a virtual environment
enable_venv: false
bifrost_venv_dir: "{{ lookup('env', 'VENV') | default('/opt/stack/bifrost') }}"
bifrost_venv_env:
VIRTUAL_ENV: "{{ bifrost_venv_dir }}"
PATH: "{{ bifrost_venv_dir }}/bin:{{ ansible_env.PATH }}" # include regular path via lookup env
pydoc: "python -m pydoc"

View File

@ -70,10 +70,14 @@
group=ironic
mode=0755
- name: "Upgrade inspector DB Schema"
command: su ironic -c "ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade"
shell: ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade
become: true
become_user: ironic
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:

View File

@ -51,6 +51,10 @@
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.
@ -94,6 +98,12 @@
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"
@ -188,9 +198,11 @@
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 == 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 == false
- name: "Do RedHat-specific changes for libvirt"
include: redhat_libvirt_changes.yml
@ -247,6 +259,7 @@
- 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 }}"

View File

@ -18,11 +18,12 @@
name: "{{ package }}"
state: "{{ state | default(omit) }}"
version: "{{ version | default(omit) }}"
virtualenv: "{{ virtualenv | default(omit) }}"
when: source_install is not defined or (source_install | bool == false)
virtualenv: "{{ bifrost_venv_dir if enable_venv else 'undefined' }}"
when: source_install is not defined or source_install == false
# NOTE (cinerama): We should be able to use the pip module here and
# possibly merge these two tasks when
# https://github.com/ansible/ansible-modules-core/pull/2600 lands.
- name: "Install from {{ sourcedir }} using pip"
command: pip install --upgrade --force-reinstall {{ sourcedir }}
when: source_install is defined and (source_install | bool == true)
environment: "{{ bifrost_venv_env if enable_venv else '{}' }}"

View File

@ -28,6 +28,13 @@ if [ -x '/usr/bin/apt-get' ]; then
if ! $(dpkg -l wget &>/dev/null); then
sudo -H apt-get -y install wget
fi
if [ -n "${VENV-}" ]; then
if ! $(virtualenv --version &>/dev/null); then
if $(sudo -H apt-get -y install virtualenv); then
sudo -H apt-get -y install python-virtualenv
fi
fi
fi
elif [ -x '/usr/bin/yum' ]; then
if ! yum -q list installed python-devel; then
sudo -H yum -y install python-devel
@ -41,10 +48,35 @@ elif [ -x '/usr/bin/yum' ]; then
if ! $(wget --version &>/dev/null); then
sudo -H yum -y install wget
fi
if [ -n "${VENV-}" ]; then
if $(virtualenv --version &>/dev/null); then
sudo -H yum -y install python-virtualenv
fi
fi
else
echo "ERROR: Supported package manager not found. Supported: apt,yum"
fi
if [ -n "${VENV-}" ]; then
echo "NOTICE: Using virtualenv for this installation."
if [ ! -f ${VENV}/bin/activate ]; then
# only create venv if one doesn't exist
sudo -H -E virtualenv --no-site-packages ${VENV}
fi
# Note(cinerama): activate is not compatible with "set -u";
# disable it just for this line.
set +u
source ${VENV}/bin/activate
set -u
VIRTUAL_ENV=${VENV}
else
echo "NOTICE: Not using virtualenv for this installation."
fi
# If we're using a venv, we need to work around sudo not
# keeping the path even with -E.
PYTHON=$(which python)
# To install python packages, we need pip.
#
# We can't use the apt packaged version of pip since
@ -59,12 +91,12 @@ fi
if ! which pip; then
wget -O /tmp/get-pip.py https://bootstrap.pypa.io/get-pip.py
sudo -H -E python /tmp/get-pip.py
sudo -H -E ${PYTHON} /tmp/get-pip.py
fi
sudo -H -E pip install "pip>6.0"
sudo -H -E pip install -r "$(dirname $0)/../requirements.txt"
PIP=$(which pip)
sudo -H -E ${PIP} install "pip>6.0"
sudo -H -E ${PIP} install -r "$(dirname $0)/../requirements.txt"
u=$(whoami)
g=$(groups | awk '{print $1}')
@ -94,10 +126,21 @@ check_get_module `pwd`/lib/ansible/modules/core/cloud/openstack/os_ironic.py \
check_get_module `pwd`/lib/ansible/modules/core/cloud/openstack/os_ironic_node.py \
https://raw.githubusercontent.com/ansible/ansible-modules-core/stable-2.0/cloud/openstack/os_ironic_node.py
echo
echo "If you're using this script directly, execute the"
echo "following commands to update your shell."
echo
echo "source env-vars"
echo "source /opt/stack/ansible/hacking/env-setup"
echo
if [ -n "${VENV-}" ]; then
sudo -H -E ${PIP} install --upgrade /opt/stack/ansible
echo
echo "To use bifrost, do"
echo "source ${VENV}/bin/activate"
echo "source env-vars"
echo "Then run playbooks as normal."
echo
else
echo
echo "If you're using this script directly, execute the"
echo "following commands to update your shell."
echo
echo "source env-vars"
echo "source /opt/stack/ansible/hacking/env-setup"
echo
fi

85
scripts/test-bifrost-venv.sh Executable file
View File

@ -0,0 +1,85 @@
#!/bin/bash
# Note(TheJulia): If there is a workspace variable, we want to utilize that as
# the preference of where to put logs
LOG_LOCATION="${WORKSPACE:-..}/logs"
set -eux
set -o pipefail
export PYTHONUNBUFFERED=1
SCRIPT_HOME="$(cd "$(dirname "$0")" && pwd)"
BIFROST_HOME=$SCRIPT_HOME/..
export VENV=/opt/stack/bifrost
# Install Ansible
$SCRIPT_HOME/env-setup.sh
# Source Ansible
# NOTE(TheJulia): Ansible stable-1.9 source method tosses an error deep
# under the hood which -x will detect, so for this step, we need to suspend
# and then re-enable the feature.
set +x +o nounset
source /opt/stack/bifrost/bin/activate
set -x -o nounset
export PATH=${VENV}/bin:${PATH}
echo $(which pip)
echo $(which python)
# Change working directory
cd $BIFROST_HOME/playbooks
echo $(which ansible-playbook)
${VENV}/bin/ansible-playbook -vvvv -i inventory/localhost test.yaml
# Syntax check of dynamic inventory test path
${VENV}/bin/ansible-playbook -vvvv \
-i inventory/localhost \
test-bifrost-create-vm.yaml \
--syntax-check \
--list-tasks \
-e enable_venv=true
${VENV}/bin/ansible-playbook -vvvv \
-i inventory/localhost \
test-bifrost-dynamic.yaml \
--syntax-check --list-tasks \
-e testing_user=cirros \
-e enable_venv=true
# Create the test VM
${VENV}/bin/ansible-playbook -vvvv \
-i inventory/localhost \
test-bifrost-create-vm.yaml \
-e enable_venv=true
set +e
# Set BIFROST_INVENTORY_SOURCE
export BIFROST_INVENTORY_SOURCE=/tmp/baremetal.csv
# Execute the installation and VM startup test.
# NOTE(TheJulia): The variables defined on the command line are to
# drive the use of Cirros as the deployed operating system, and
# as such sets the test user to cirros, and writes a debian style
# interfaces file out to the configuration drive as cirros does
# not support the network_info.json format file placed in the
# configuration drive.
${VENV}/bin/ansible-playbook -vvvv \
-i inventory/bifrost_inventory.py \
test-bifrost-dynamic.yaml \
-e use_cirros=true \
-e testing_user=cirros \
-e write_interfaces_file=true \
-e enable_inspector=true \
-e enable_venv=true
EXITCODE=$?
if [ $EXITCODE != 0 ]; then
echo "****************************"
echo "Test failed. See logs folder"
echo "****************************"
fi
$SCRIPT_HOME/collect-test-info.sh
exit $EXITCODE