Automation Win: Configure Cisco ACI with an Ansible Playbook

This blog post was initially sent to subscribers of my mailing list. Subscribe here.

Following on his previous work with Cisco ACI Dirk Feldhaus decided to create an Ansible playbook that would create and configure a new tenant and provision a vSRX firewall for the tenant when working on the Create Network Services hands-on exercise in the Building Network Automation Solutions online course.

The most interesting part of his solution: the existing Ansible ACI modules didn’t provide all the functionality he needed to configure his tenants, so he had to create the data structure expected by a Cisco ACI REST API calls (create L3 external connection, create static port) with a Jinja2 template and use aci_rest module to execute them.

If you plan to make your Cisco ACI environment more consistent by automating common operations that would take dozens of (unreliable operator-driven) GUI clicks explore his solution and adapt it to your needs… and if you need more information, watch his presentation from autumn 2018 Building Network Automation Solutions online course.


  1. To even achieve more flexibility like working with 2FA/manual authentication uri module comes into rescue as it allows to reuse session cookie for any subsequent calls i.e. loop statements (ones ending up with subsequent authentication sessions). An example would be:


    • name: Login uri: url: https://{{ inventory_hostname }}/api/aaaLogin.json method: POST body: '"{ "aaaUser" : { "attributes" : { "name" : "{{ username }}" , "pwd" : "{{ password }}" } } }"' status_code: 200 validate_certs: False headers: Content-Type: "application/json" no_log: True register: login

    • name: Add Bridge Domain uri: url: https://{{ inventory_hostname }}/api/node/mo/uni/tn-{{ item.tenant }}/BD-{{ }}.json body: {"fvBD":{"attributes":{"dn":"uni/tn-{{ item.tenant }}/BD-{{ }}","name":"{{ }}","descr":"{{ item.description }}","unicastRoute":"{{ item.unicast }}","rn":"BD-{{ }}","status":"created"},"children":[{"fvRsCtx":{"attributes":{"tnFvCtxName":"{{ item.vrf }}","status":"created,modified"},"children":[]}}]}} method: POST body_format: json return_content: yes validate_certs: False headers: Cookie: "{{ login.set_cookie }}" loop: "{{ bd }}"

    Vars file for loop:

    bd: - {tenant: "common", name: "bd_192.168.1.0/24", description: "default", unicast: "false", vrf: "default"} - {tenant: "common", name: "bd_192.168.2.0/24", description: "default", unicast: "true", vrf: "default"} - {tenant: "common", name: "bd_192.168.3.0/24", description: "default", unicast: "false", vrf: "default"}

Add comment