Ansible & Cisco ACI

This is a straight forward guide on getting started with Ansible on Ubuntu with Cisco ACI APIC.

This guide uses;

  • VMware Workstation 12 Pro 12.5.2 build-4638234
  • Ubuntu 16.04.3
  • Python 2.7
  • Ansible
  • Cisco ACI 2.x  => 3.x. (dcloud virtual & real deployments)

Install Ubuntu Server

Install Ubuntu Server 16.04.3 LTS in VMware workstation using the Ubuntu ISO downloaded from

After installation, within console on Ubuntu, install ssh and change root password

# apt-get install ssh
# sudo passwd root


Install Python 2.7

Python 2.7 is likely to be installed already with the install of Ubuntu. Typing “python –version” at the command prompt will provide you with the currently installed version if it installed.2.7.x is required, if python is not installed or is not at version 2.7.x then follow the next steps to install.

# apt-get install python
# apt-get install python-pip
# pip install –upgrade pip


Install Ansible

The ansible installation guide can be found here, although the required steps are given below. This will install the latest version available through apt-get.

# apt-get install software-properties-common
# apt-add-repository ppa:ansible/ansible
# apt-get update
# apt-get install ansible

At this stage typing “ansible –version” at the command prompt will give you the version number which for this installation is


Install Cisco APIC Python Eggs

These eggs are the Cisco Cobra files which provide the interface between Python and the APIC. Create a temporary directory for downloads, in this install I created a folder on the root called \apicsetup, within this I created a folder called \eggs. The Cisco APIC controller provides the required version of the eggs, these are available via HTTP from the APIC.

Download the two .egg files from APIC ( to the current directory, i.e. /apicsetup/eggs/, example below for an APIC controller on v3.0.1k.

# wget “”
# wget “”

If you are not in the correct directory, adding ‘-O /apicsetup/eggs/’ will put in the /apicsetup/eggs/ folder

Both eggs files needs to be installed. The ‘acicobra’ egg must be installed first. Install the eggs;

# easy_install -Z /apicsetup/eggs/acicobra-X.Y_Zj-py2.7.egg
# easy_install -Z /apicsetup/eggs/acimodel-X.Y_Zj-py2.7.egg

This will complete the installation of the eggs for Cobra. The full installation guide can be found on the APIC controller at


Install Cisco Ansible Python Scripts

Cisco provides Python scripts to be used with Ansible and are available at Github. These files relate to each of the modules documented at, the Cisco module documentation for these modules is here. We will use the git command to clone the git repository into a new subdirectory (/aci-ansible) our temporary directory we created earlier (/apicsetup/aci-ansible). Before we clone the repository we need to install the git tools.

# apt-get install git

Then clone the repo. into  /apicsetup/aci-ansible

# git clone /apicsetup/aci-ansible

We need to copy some files from this cloned repo into the python folders as follows:

# cp /apicsetup/aci-ansible/module_utils/ /usr/lib/python2.7/dist-packages/ansible/module_utils/

# mkdir /usr/lib/python2.7/dist-packages/ansible/modules/network/aci-ansible

# cp /apicsetup/aci-ansible/library/* /usr/lib/python2.7/dist-packages/ansible/modules/network/aci-ansible/


In Ansible v2.4, Cisco scripts will be installed along with Ansible, although the above method will apply to new module scripts or to new modules for other systems.It is possible to place other module scripts into the same directories as the playbooks which restricts the use to those local playbooks. Ansible documentation provides more details on this.


Basic Ansible Configuration

We now have a running setup of Ansible with the files needed to support the Cisco ACI APIC. We now configure ansible with some basic information to allow ansible to connect to the Cisco APIC. The ansible getting started documentation can be foundhere.

Ansible Hosts File

The ansible hosts file contains at a minimum a list of hosts / devices that ansible will connect to. It may also contain passwords for logging (SSH) into those hosts. In this basic connectivity case we are going to add the Cisco APIC IP address and the user credentials. The ansible hosts file is located at /etc/ansible/hosts. We will replace all the content of the default file with the following. Replace the APIC IP, username & password with your own system information.


ansible_connection = local
aci_username = admin
aci_password = C1sco12345

This configuration sets up a group called ‘apic’ which we will refer to on our scripts and the section [apic:vars] provides a variables that can be used in scripts that refer to the [apic] hosts. So aci_username is a variable that can be refered to in a playbook (ansible script). Save the hosts file and check ansible can communicate wiith the APIC. We can check ansible can contact this host by using the following command.

# ansible apic -m ping

The ‘apic’ refers to the hosts listed in the [apic] group section of the hosts file. You may get a prompt to accept the certificate provided by the APIC, the APIC uses locally signed certificates when installes so unless publicly signed ones have been installed, you will need to verify the certificate fingerprint and accept if it is valid. This happens once only.

Creating Basic Playbooks

A playbook is (quoting from

At a basic level, playbooks can be used to manage configurations of and deployments to remote machines. At a more advanced level, they can sequence multi-tier rollouts involving rolling updates, and can delegate actions to other hosts, interacting with monitoring servers and load balancers along the way.

We will create two basic playbooks, one to create a bridge domain within an existing tenant on the APIC, the second to grab all of the bridge domains on the APIC and return them to us in JSON format. Keeping playbooks organised is important, there are a few recommended ways discussed at generally directory structures are created under /etc/ansible/… for example /etc/ansible/playbooks/

Creating a Bridge Domain

Create a new file in your chosen directory named newDB.yml. The syntax is YAML and is indent sensitive and does not allow tabs, indents must be spaces usually 2 per indent. In this file we will add the following content.

- name: apic bridge domains
hosts: apic
gather_facts: no

aci_login: &aci_login
hostname: '{{ inventory_hostname }}'
username: '{{ aci_username }}'
password: '{{ aci_password }}'
validate_certs: no

- name: Creating BD
<<: *aci_login
tenant: HugeCustomer
bd: IntranetWebFront
vrf: InternalNetwork
delegate_to: localhost

This playbook creates a Bridge Domain called ‘IntranetWebFront’ in a VRF(Context) called ‘InternalNetwork’ in a tenant called ‘HugeCustomer’. The variables for the username and password will look familiar from the /etc/ansible/hosts file. The ‘inventory_hostname’ variable is an internal ansible variable which provides the current host ansible is working with from the ‘apic’ groups in the host file. The ‘apic’ groups is defined at the top of the playbook as ‘hosts: apic’. The ‘aci_bd’ refers to a python script called which was copied from the Cisco git clone into the ‘/usr/lib/python2.7/dist-packages/ansible/modules/network/aci-ansible’ directory earlier. Take a look at this (and other) python files as they are usually documented with addtional parameters that can be used. This bridge domain script is also documented at the ansible website here as mentioed earlier.

To run this playbook, use the following command.

# ansible-playbook newBD.yml

This should complete with no errors. If errors occur they will likely be due to invalid credentials or syntax in the playbook with idents being the likely cause so review these first.

Get all Bridge Domains in Raw JSON Format

This time we will create a playbook to return all the bridge domains configured on the APIC. Create a new playbook called bridge.yml and add the following YAML.

- name: apic bridge domains
hosts: apic
gather_facts: no

aci_login: &aci_login
hostname: '{{ inventory_hostname }}'
username: '{{ aci_username }}'
password: '{{ aci_password }}'
validate_certs: no

- name: Get RAW APIC REST Data
<<: *aci_login
method: get
path: /api/node/class/fvBD.json
register: raw
delegate_to: localhost
- debug: var=raw

Run the following command.

# ansible-playbook getbridge.yml

which will return all the bridge domains configured on the APIC in JSON format. Grep’ing for the DN of each bridge domain provides a brief list of the full DN’s.

# ansible-playbook getbridge.yml | grep dn

For example:

"dn": "uni/tn-common/BD-default",
"dn": "uni/tn-common/BD-BD_Common",
"dn": "uni/tn-coke/BD-bd_ansible_1a",
"dn": "uni/tn-infra/BD-default",
"dn": "uni/tn-TSW_Tenant0/BD-tsw0ctx0BD0",
"dn": "uni/tn-TSW_Tenant0/BD-tsw0ctx0BD1",
"dn": "uni/tn-mgmt/BD-inb",
"dn": "uni/tn-HugeCustomer/BD-IntranetWebFront",


Simon Birtles

I have been in the IT sector for over 20 years with a primary focus on solutions around networking architecture & design in Data Center and WAN. I have held two CCIEs (#20221) for over 12 years with many retired certifications with Cisco and Microsoft. I have worked in demanding and critical sectors such as finance, insurance, health care and government providing solutions for architecture, design and problem analysis. I have been coding for as long as I can remember in C/C++ and Python (for most things nowadays). Locations that I work without additional paperwork (incl. post Brexit) are the UK and the EU including Germany, Netherlands, Spain and Belgium.

One thought on “Ansible & Cisco ACI

Comments are closed.