Michael Solberg, Red Hat chief architect, walks you through using the new Python Shade library modules to configure a simple playbook.

image

In my previous article, Using Ansible for continuous integration on OpenStack, we looked at how to use the nova_compute module in Ansible 1.9 to launch instances and configure them in a simple Ansible playbook. A set of new modules for interacting with OpenStack were released in Ansible 2.0. In this article, we’ll look at how to use the new modules to launch and configure a web server in a simple playbook.

The new modules in Ansible 2.0 use the Python Shade library. Shade isn’t currently packaged for CentOS or Red Hat Enterprise Linux and if you’re on one of those distributions, you’ll need to install it using pip. Shade is available as an operating system package for the latest versions of Ubuntu and Fedora and can be installed via the normal mechanisms.

The next biggest change in how these modules work is around authentication. With the nova_compute module, authentication details were specified as options in the task. With the new os_server module, authentication is pulled from the environment variables which are set by the “openrc” script. Most OpenStack installations will have an option to download the openrc for your specific tenant in Horizon under “Access & Security”. To set these variables, just source the openrc script before running the playbook like so:

$ . ./openrc.sh

The script you download from Horizon will ask for you to enter your OpenStack user password and then will load that into an environment variable. If you’re running your playbook non-interactively as a part of a CI work flow, you’ll want to specify a password in the openrc script by setting the OS_PASSWORD environment variable.

Once Shade is installed, writing and running the playbook are very similar to the previous example. Here’s an example play which will launch an instance in an OpenStack cloud:

- name: Deploy on OpenStack
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Deploy an instance
      os_server:
      state: present
      name: webserver
      image: centos-7-x86_64-genericcloud
      key_name: root
      wait: yes
      flavor: m1.small
      auto_floating_ip: yes
      network: private
      meta:
        hostname: webserver.localdomain

The play is a local action, similar to the nova_compute module, and we specify the same basic parameters. One thing that’s a little different is that there are several options for specifying the network settings for the instance. In this example, we’re attaching a VIF to the “private” network and requesting a floating IP. You can also specify multiple networks or you can create a port with the os_port module and use that for your network interface. To run the play, source your openrc script and call ansible-playbook on a file which has the above contents.

$ . ./openrc.sh
$ ansible-playbook openstack_deploy.yaml

This should deploy an instance on OpenStack named “webserver”. The output will look something like this:

PLAY [Deploy on OpenStack] 
****************************************************

TASK: [Deploy an instance] 
****************************************************
changed: [localhost]

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

To configure the instance after launch, we’ll use the same strategy we employed with the nova_compute module. The first play will launch the instance and add it to the in-memory inventory with the add_host module and then we’ll run a second play on the instance once it’s in the inventory. I’ve also added a wait condition to make sure that the instance is responding to SSH before we try to execute the second play.

- name: Deploy on OpenStack
  hosts: localhost
  gather_facts: false
  tasks:
  - name: Deploy an instance
    os_server:
      state: present
      name: webserver
      image: centos-7-x86_64-genericcloud
      key_name: root
      wait: yes
      flavor: m1.small
      auto_floating_ip: yes
      network: private
      meta:
        hostname: webserver.localdomain
      register: webserver

  - name: Wait for SSH on the Instance
    command: >
      ssh -oBatchMode=yes -oStrictHostKeyChecking=no
      centos@{{webserver.server.public_v4}} true
    register: result
    until: result|success
    retries: 30
    delay: 10

  - name: Add CentOS Instance to Inventory
    add_host: name=webserver groups=webservers
              ansible_ssh_host={{ webserver.server.public_v4 }}

- hosts: webservers
  remote_user: centos
  sudo: yes
  Tasks:
    - name: ensure apache is at the latest version
      yum: name=httpd state=latest
    - name: make sure apache is running
      service: name=httpd state=running

Another change to note in the example given above is that we’re referencing the facts of the newly created instance by the name of the instance (i.e. “webserver.server”). This is particularly helpful in plays which launch several instances – each instance is referenced by the unique name given to it. Assuming everything goes well, you should now have a running instance in OpenStack which has a floating IP assigned and has the Apache web server running on it. The second play can then be embellished to include downloading the latest build of your software from a Jenkins job or a code repository.

The os_server module is well documented with examples. The full list of OpenStack modules is also available, along with the modules used to interact with other cloud providers. Additional modules for things like launching Heat stacks were added to the “extras” collection in Ansible 2.2.

Michael Solberg contributed this original post.

Superuser is always interested in opinion pieces and how-tos. Please get in touch: [email protected]

Cover Photo // CC BY NC