Cisco ACI Configuration Using Easy Automation Techniques

My organization is currently going through its first ACI deployment. While ACI is still shiny and new to us, we don’t have a lot of time to be mesmerized by SDN. Although it’s our first exposure and deployment with ACI, we are deploying a complex multi-tenant design right out of the gate. It’s great because we get the benefits that SDN offers, and we get it for each tenant that we are configuring it for, so there’s a cumulative effect.

After the initial fabric discovery, and initialization, my exposure to ACI has been repeatedly creating tenants, bridge domains (BDs), end-point groups (EPGs), contracts, attachable access entity profiles (AAEPs), and other objects. With multiple tenants, this leads to a lot of windshield time clicking through screens to create the entities, and policies, and associate them. The names and values of the policies are very similar based on our conventions, but have subtle differences based on things like tenant ID, VLAN ranges, and IP subnets. After going through the process a few times to create some of this config the “new car smell” of ACI wore off quickly for me, and I knew I needed some kind of automation to save time, and reduce the likelihood of human (me) error.

high repetition + high errors likely = AUTOMATE

To date, I’ve mostly used automation to:

  • Collect, and parse device configurations
  • Create inventory reports for life cycle management
  • Make bulk configuration updates to multiple devices
  • Create custom graphs for monitoring

This was different than the other automation work I have done in the past, so I saw this as an opportunity to both document and learn. I started with configuration that was the most time consuming and prone to errors. The automation of this config would provide a good way to dip my toes into ACI automation and knock out a lot of repetitive configuration at the same time.

To keep this post from suffering from scope creep, I will focus specifically on the automated creation of bridge domains (BDs) in ACI. Bridge domains are a high touch configuration object in ACI, especially for multi-tenancy. Once you get the hang of it for one object, it’s natural to progress to others as they will be similar. Some other areas that I have also looked into automating the configuration of are:

  • End Point Group (EPG) creation, and configuration
  • Contract creation, and association
  • Attachable Access Entity Profiles (AAEP) creation, and configuration
  • Tenant configuration
  • Fabric configuration

Bridge Domain Automation Example 1 – Create Once, Clone Many

The first cool thing I found with Cisco ACI automation is that if you right-click an object in the GUI, you can download the structured data for it in XML or JSON. There are actually multiple options here that are useful, but we will only cover “Save As …” and “Post …” in this article.

Right-click a tenant, and select “Save as…” to download the configuration

In the save as dialogue box, select how you want to save it. I choose “Only Configuration”, “Subtree”, and “JSON”. This downloads just the configuration for the object in JSON. If you select a scope of “Self”, you’ll only get the data for the object at that level and none of the sub-tree data.

Click download after you make your selections

Once you have the data downloaded, you can open the JSON file in your favorite editor to see the structured data. You could put your Python skills to good use, and write code to read, or change the JSON for specific use cases. Like Kevin Garnett says, “ANYTHING IS POSSIBLE!!!”

To create multiple bridge domains quickly and efficiently, you can manipulate the downloaded tenant JSON to add more definitions. First, you will need to create at least one object to use as a template before you download the JSON. You can use your favorite text editor to open the JSON download and turn off line wrap so the whole file is on one line. Next, find the beginning of your BD definition, and put each entry on its own line. You will end up with the first line being everything up to the bridge domain definitions, an empty line, then one line for each template bridge domain. Everything after the definitions can be removed. Your JSON should look similar to the image below. Note, bridge domain definitions start with {“fvBD”:

Two template bridge domain definitions

Now, you can copy and paste your template bridge domain definition to match the number of bridge domains you need to create for the tenant (minus the number of templates you already created). Once you have the right number of bridge domains defined, there are only two key-value pairs that we need to adjust for each unique bridge domain:

  • “name”:”<name>”
  • “ip”:”<ip/mask>”

Update the values, and save the JSON file. You need to be careful that you keep the JSON formatted correctly. If you want to validate your JSON before posting it, you can use a site like https://jsonlint.com.

Changing the names for five new bridge domains
Changing the subnets for five new bridge domains

Post the new JSON file through the GUI by right-clicking the tenant, selecting “post”, and selecting the JSON file.

Click “Browse” to select the updated JSON file.

Click “Post” to post the data to ACI. A POST will create, or update data in ACI.

Before – two bridge domains
After – seven bridge domains

Bridge Domain Automation Example 2 – Utilizing the ACI API

The previous example shows a down and dirty way to take an object’s config in JSON, and clone it as many times as you need. It’s useful and doesn’t delve too far down the automation rabbit hole. This next example goes a little further, to show you how to create the same bridge domains using the Cisco ACI API, and performing multiple API calls using Postman and Runner.

The steps below show how to create the CSV file for our iterations, Postman requests, and a custom Postman environment. I’ve included the templates for each of these at the end of the post if you just want to copy my templates, as opposed to creating your own from scratch.

Similar to the first example, we need to get the JSON for the object we want to use as a template. If needed, review the example above to see how to export JSON for an object. Once we have it opened and prettified, we can start to identify areas where we want to create variables. These variables are defined by using double curly brackets with a variable name string inside. Here’s an excerpt of the dn key-value pair in a bridge domain both before, and after variable substitution.

Pre-substitution:

"dn": "uni/tn-TENANT/BD-BRIDGEDOMAIN1",

Post-substitution:

"dn": "uni/tn-{{tenant_name}}/BD-{{bd_name}}",

All we have done is simply replace the static values with variables. Reviewing my bridge domain JSON, I created the following variables. Once you have created all of the variables, save the JSON file.

{{tenant_name}}
{{bd_name}}
{{subnet_ip-mask}}
{{vrf_name}}
{{l3out_name}}

Now we are ready to create a CSV file with the data that will populate the variables. You can create a CSV in Excel, or you can do it in your editor of your choice. The important points are that the variables are your header values, and be consistent with your delimiter and formatting.

tenant_name,bd_name,subnet_ip-mask,vrf_name,l3out_name
TENANT1,New1_BD,10.1.1.1/24,VRF-DEFAULT,TENANT1:DEFAULT_l3out
TENANT1,New2_BD,10.1.2.1/24,VRF-DEFAULT,TENANT1:DEFAULT_l3out
TENANT1,New3_BD,10.1.3.1/24,VRF-DEFAULT,TENANT1:DEFAULT_l3out
TENANT1,New4_BD,10.1.4.1/24,VRF-DEFAULT,TENANT1:DEFAULT_l3out
TENANT1,New5_BD,10.1.5.1/24,VRF-DEFAULT,TENANT1:DEFAULT_l3out

You now have all the data and structure you need to create the new bridge domains in ACI. For our next step, we will use Postman to craft the API calls needed to add an object, and we will use Runner to perform this for each line in our CSV file. If you haven’t used Runner before, think of it like a Python FOR loop (for bridge_domain in bridge_domains, make these API calls).

In order for the import to work correctly, you will need to create two POST requests. I created a collection for all of the ACI things I create. Inside of the collection, I created a folder called “Bridge Domain Creation” that contain both the authentication request, and the bridge domain creation request.

Postman Collection hierarchy

I also created an environment so I could use variables in Postman. I have my credentials, and APIC IP listed so I don’t have to re-type them every time (no these aren’t my actual values for my ACI deployment…thanks for asking). You need to make sure you select the environment in the upper-left hand corner of the Postman workspace (The default is “No Environment”).

The details for each POST request are below. Make sure to save each of them, so you can re-use them. You can also share your collection and environment data with your team members for collaboration in Postman, or create a workspace for everyone to use.

  • Name: ACI_AUTH
  • Description: Used to authenticate to ACI
  • Method: POST
  • URL: https://{{aciIp}}/api/aaaLogin.json
  • Headers: Content-type:application/json
  • Body: Raw
{
"aaaUser" : {
"attributes" : {
"name" : "{{username}}",
"pwd" : "{{password}}"
}
}
}
  • Name: Create_BD
  • Description: Used to create a BD in ACI
  • Method: POST
  • URL: https://{{aciIp}}/api/node/mo/uni.json
  • Headers: Content-type:application/json
  • Body: Raw
Paste the contents of the JSON file you created earlier with the variable substitutions.

{
"totalCount": "1",
"imdata": [
{
"fvBD": {
"attributes": {
"arpFlood": "yes",
"descr": "",
"dn": "uni/tn-{{tenant_name}}/BD-{{bd_name}}",
"ipLearning": "yes",
"limitIpLearnToSubnets": "yes",
"multiDstPktAct": "bd-flood",
"name": "{{bd_name}}",
"nameAlias": "",
....

You could run the request one time with info for one of your bridge domains, but you would need to change the body of each request to match each bridge domain. The last step to bring everything together is to use Runner to perform the request for each entry in our CSV file. You start Runner by clicking on the Runner button in the upper-left section of the application. It’s grayed-out, so it doesn’t really stand out.

Once you click on Runner, it will open in a new window. You’ll get an intuitive window that we need to fill in with our details:

  • In the upper-left area, choose the collection, and folder that contain the requests we created previously. You will see the two POST methods listed.
  • Select the environment if you created one
  • Click “Select File”, and choose the CSV you created earlier. Once it’s selected, you will be able to click the “Preview” box next to the data file type to see how your data will look when it’s imported. You want to verify the headers, data, and iterations look correct. You will also see the iterations value will change to match the number of rows of data in your CSV file.
  • I click “Save responses,” so I can see what is returned. It’s useful for verification and troubleshooting.
  • Leave the run order as is, with the authentication request first, and the create BD request second.
Preview of your CSV data in Runner

When you are ready, your Runner settings should look similar to the image below. You are now ready to click on the blue Run button!

Runner settings

The next page that you’ll see contains the results for each iteration. You’ll see that for each line in your CSV file, there is an iteration, along with the two requests (auth, and create BD). Most importantly, there is a response code for each request. In this case, all are HTTP code 200, which is OK. Yay!

Multiple successful iterations of our API calls to ACI to create new bridge domains

If you want to look at specifics of the request, or response, you can click on the name of a POST request for an iteration, and see the details such as the request headers and body, as well as the response headers and body. For example, if you click in the request body, you will see the JSON being passed, and the variables have been replaced with that specific iteration’s values from the CSV file. This is where the magic happens!

Reviewing iteration 1’s request body showing the variables are populated

Now for the moment of truth…

ACI BDs Before
ACI BDs After

Wrap-Up

As you can see, there are a lot of possibilities with automation in ACI. These two examples are just scratching the surface of what’s possible not only with ACI but automation in general. While these examples helped me get configuration done quickly, and more consistently, it doesn’t address questions such as, “Can I submit a ServiceNow request to fully build out a new ACI tenant automatically?” The answer is yes, and goes much deeper that what I covered above. My hope is you can see how a workflow could be built to accomplish exactly that using automation.

I’ve included a couple of links below if you want to look deeper into the ACI REST API. In my opinion, the API will become the standard way to interact with ACI. I’ve had multiple people tell me that the ACI GUI was specifically designed to be clunky, and hard to use, so you wouldn’t want to use it! How’s that for making the case for automation!?!

If you are looking for a really good book that covers a lot of different facets of automation written by and for network engineers, I highly recommend Network Programmability and Automation by O’Reilly. This was the book that really opened my eyes to the realization that there are better ways to configure network devices than the CLI and GUI.


Useful Links

Postman Templates:

Cisco ACI:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s