Documentation

7. Using virtualenv with Ansible Tower

Ansible Tower 3.0 and later uses virtualenv. Virtualenv creates isolated Python environments to avoid problems caused by conflicting dependencies and differing versions. Virtualenv works by simply creating a folder which contains all of the necessary executables and dependencies for a specific version of Python. Ansible Tower creates two virtualenvs during installation–one is used to run Tower, while the other is used to run Ansible. This allows Tower to run in a stable environment, while allowing you to add or update modules to your Ansible Python environment as necessary to run your playbooks. For more information on virtualenv, see the Python Guide to Virtual Environments and the Python virtualenv project itself.

By default, the virtualenv is located at /var/lib/awx/venv/ansible on the file system but starting with Ansible Tower 3.5, you can create your own custom directories and use them in inventory imports. This allows you to choose how you run your inventory imports, as inventory sources use custom virtual environments.

Tower also pre-installs a variety of third-party library/SDK support into this virtualenv for its integration points with a variety of cloud providers (such as EC2, OpenStack, Azure, etc.) Periodically, you may want to add additional SDK support into this virtualenv, which is described in further detail below.

Note

It is highly recommended that you run umask 0022 before installing any packages to the virtual environment. Failure to properly configure permissions can result in Tower service failures. An example follows:

# source /var/lib/awx/venv/ansible/bin/activate
# umask 0022
# pip install --upgrade pywinrm
# deactivate

In addition to adding modules to the virtualenv that Tower uses to run Ansible, you can create new virtualenvs as described below.

7.1. Preparing a new custom virtualenv

You can specify a different virtualenv for running Job Templates in Tower. In order to do so, you must specify which directories those venvs reside. You could choose to keep custom venvs inside /var/lib/awx/venv/, but it is highly recommended that a custom directory be created. The following examples use a placeholder directory /opt/my-envs/, but you can replace this with a directory path of your choice anywhere this is specified.

  1. First, create a directory for your custom venvs:
$ sudo mkdir /opt/my-envs
  1. Make sure to give your directory the appropriate write and execution permissions:
$ sudo chmod 0755 /opt/my-envs
  1. Optionally, you can specify in Tower which directory to look for custom venvs by adding this directory to the CUSTOM_VENV_PATHS setting as follows:
$ curl -X PATCH 'https://user:[email protected]/api/v2/settings/system/' \
    -d '{"CUSTOM_VENV_PATHS": ["/opt/my-envs/"]}'  -H 'Content-Type:application/json'

If you have venvs spanned over multiple directories, add all the paths and Tower will aggregate venvs from them:

$ curl -X PATCH 'https://user:[email protected]/api/v2/settings/system/' \
    -d '{"CUSTOM_VENV_PATHS": ["/path/1/to/venv/", "/path/2/to/venv/", "/path/3/to/venv/"]}' \
    -H 'Content-Type:application/json'
  1. Now that a venv directory has been set up, create a virtual environment in that location:
$ sudo virtualenv /opt/my-envs/custom-venv

Note

Multiple versions of Python are supported, but the syntax for creating virtualenvs in Python 3 has changed slightly: $ sudo python3 -m venv /opt/my-envs/custom-venv

  1. Your newly created virtualenv needs a few base dependencies to properly run playbooks (eg., fact gathering):
$ sudo /opt/my-envs/custom-venv/bin/pip install psutil

From here, you can install additional Python dependencies that you care about, such as a per-virtualenv version of Ansible itself:

$ sudo /opt/my-envs/custom-venv/bin/pip install -U "ansible == X.Y.Z"

Or you can add an additional third-party SDK that is not included with the base Tower installation:

$ sudo /opt/my-envs/custom-venv/bin/pip install -U python-digitalocean

If you want to copy them, the libraries included in Tower’s default virtualenv can be found using pip freeze:

$ sudo /var/lib/awx/venv/ansible/bin/pip freeze

In a clustered Tower installation, you need to ensure that the same custom virtualenv exists on every local file system at /opt/my-envs/. Custom virtualenvs are supported on isolated instances. If you are using a custom virtual environment, it needs to also be copied or replicated on any isolated node you would be using, not just on the Tower node. For setting up custom virtual environments in containers, refer to the Build custom virtual environments section of the Ansible Tower Administration Guide.

7.2. Assigning custom virtualenvs

Once you have created a custom virtualenv, you can assign it at the Organization, Project, or Job Template level to use it in job runs. You can set the custom venv on an inventory source to run inventory updates in that venv. However, starting in Ansible Tower 3.5, Ansible 2.4 or later is required to run inventory updates. Jobs using that inventory follow their own rules and will not use this venv. If an SCM inventory source does not have a venv selected, it can use the venv of its linked project. You can assign a custom venv on the organization, but if you do, it will not be used by inventory updates in the organization, as it is only used in job runs.

The following shows the proper way to assign a custom venv at the desired level.

PATCH https://awx-host.example.org/api/v2/organizations/N/
PATCH https://awx-host.example.org/api/v2/projects/N/
PATCH https://awx-host.example.org/api/v2/job_templates/N/
PATCH https://awx-host.example.org/api/v2/inventory_sources/N/

Content-Type: application/json
{
        'custom_virtualenv': '/opt/my-envs/custom-venv'
}

An HTTP GET request to /api/v2/config/ provides a list of detected installed virtualenvs:

{
        "custom_virtualenvs": [
                "/opt/my-envs/custom-venv",
                "/opt/my-envs/my-other-custom-venv",
        ],
...
}

You can also specify the virtual environment to assign to an Organization, Project, and Job Template from their respective edit screens in the Ansible Tower User Interface. Select the virtualenv from the Ansible Environment drop-down menu, as shown in the example below:

_images/organizations-ansible-env-virtualenv-list.png

When you launch a job template, you will also see the virtualenv specified in the Job Details pane:

_images/jobs-show-job-details-venv.png