Search code examples
ansibledevopsapache-cloudstack

Ansible CloudStack modules do not find CloudStack python library cs


I'm trying to use Ansible together with its CloudStack modules to e.g. create a computing instance at a cloud provider supporting CloudStack (here: Exoscale, shouldn't matter in this case).

tl;dr:

The CloudStack python library cs is not found by ansible:

fatal: [localhost]: FAILED! => {"changed": false, "msg": "python library cs required: pip install cs"}

despite being installed.

Details:

My inventory/host file consists of one single line:

localhost ansible_connection=local

I now run a minimal test playbook play.yml with ansible-playbook play.yml

The play.yml content is:

---
- hosts: localhost
  become: no
  gather_facts: no

  tasks:
    - name: Include global variables
      include_vars: vars/vars.yml
    - name: Include global secrets
      include_vars: vars/vault.yml

    - name: python version
      command: python --version
      register: python_version

    - name: print python version
      debug:
        msg: "{{ python_version }}"

    - name: manual code execution
      command: python -c "from cs import CloudStack; print(CloudStack)"
      register: cs_output

    - name: print manual code execution
      debug:
        msg: "{{ cs_output }}"

    - name: Create debian instance
      cs_instance:
        api_key: "{{ vault.exoscale.key }}"
        api_secret: "{{ vault.exoscale.secret }}"
        api_url: "{{ exoscale.endpoints.compute }}"
        name: test-vm-1
        iso: Linux Debian 7 64-bit
        hypervisor: VMware

Running this yields the following:

PLAY [localhost] *******************************************************************************************************

TASK [Include global variables] ****************************************************************************************
ok: [localhost]

TASK [Include global secrets] ******************************************************************************************
ok: [localhost]

TASK [print python version] ********************************************************************************************
ok: [localhost] => {
    "msg": {
        "changed": true,
        "cmd": [
            "python",
            "--version"
        ],
        "delta": "0:00:00.014565",
        "end": "2018-04-20 08:14:04.997040",
        "failed": false,
        "rc": 0,
        "start": "2018-04-20 08:14:04.982475",
        "stderr": "Python 2.7.14",
        "stderr_lines": [
            "Python 2.7.14"
        ],
        "stdout": "",
        "stdout_lines": []
    }
}

TASK [manual code execution] *******************************************************************************************
changed: [localhost]

TASK [print manual code execution] *************************************************************************************
ok: [localhost] => {
    "msg": {
        "changed": true,
        "cmd": [
            "python",
            "-c",
            "from cs import CloudStack; print(CloudStack)"
        ],
        "delta": "0:00:00.263650",
        "end": "2018-04-20 08:14:05.687666",
        "failed": false,
        "rc": 0,
        "start": "2018-04-20 08:14:05.424016",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "<class 'cs.client.CloudStack'>",
        "stdout_lines": [
            "<class 'cs.client.CloudStack'>"
        ]
    }
}

TASK [Create debian instance] ******************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "python library cs required: pip install cs"}

PLAY RECAP *************************************************************************************************************
localhost                  : ok=7    changed=2    unreachable=0    failed=1    

which python (python installed with anaconda, conda environment named ansible)

/Users/ccauet/anaconda3/envs/ansible/bin/python

python --version

Python 2.7.14

which ansible (installed via pip in the same conda environment)

/Users/ccauet/anaconda3/envs/ansible/bin/ansible

ansible --version (incl definition of used python version)

ansible 2.5.0
  config file = /Users/ccauet/Repositories/p8/exoscale/ansible.cfg
  configured module search path = [u'/Users/ccauet/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/ccauet/anaconda3/envs/ansible/lib/python2.7/site-packages/ansible
  executable location = /Users/ccauet/anaconda3/envs/ansible/bin/ansible
  python version = 2.7.14 | packaged by conda-forge | (default, Mar 30 2018, 18:21:11) [GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)]

pip freeze

ansible==2.5.0
asn1crypto==0.24.0
bcrypt==3.1.4
certifi==2018.4.16
cffi==1.11.5
chardet==3.0.4
cryptography==2.2.2
cs==2.1.6
enum34==1.1.6
idna==2.6
ipaddress==1.0.22
Jinja2==2.10
MarkupSafe==1.0
paramiko==2.4.1
pyasn1==0.4.2
pycparser==2.18
PyNaCl==1.2.1
PyYAML==3.12
requests==2.18.4
six==1.11.0
urllib3==1.22

As you can see cs is installed and can be invoked by hand inside the playbook. Nevertheless the CloudStack module does not find the library.

Tried so far:

  • Tested with python 2.7 and 3.6

Any help is welcome!


Solution

  • It sounds to me like the cs_instance module is possibly using the system Python rather than conda virtual environment. I've had this problem before with other Ansible modules running locally.

    You can make Ansible use the Python interpreter in your Conda virtual environment by setting the ansible_python_interpreter fact in the inventory of localhost. You can do this as a pre-task, if you're running Ansible in the same Conda environment that you want the local task to use as follows:

    ---
    - hosts: localhost
      become: no
      gather_facts: no
    
      pre_tasks:
    
       - name: Get local python interpreter
         command: which python
         register: local_python_interpreter
    
       - name: Set ansible_python_interpreter to local python interpreter
         set_fact:
           ansible_python_interpreter: "{{ local_python_interpreter.stdout }}"
    
      tasks:
      ...