Using Requests
SECTION
  • Introduction
  • Ansible and ACI
  • Cisco ACI API
  • Python Basics
  • Python ReST w/Requests
  • Javascript
  • Config ACI Programatically
  • Finished
  • References

In Python you could write the code to interact with the ACI library directly without the need of a library. Yet the advantage of some of these libraries is that another person has provided a foundation that is easier to work with than going at it alone. The Requests Library is a very popular library available in Python that really helps you when doing REST calls using Python.

The best description for Requests is available on their site as: "Requests is the only Non-GMO HTTP library for Python, safe for human consumption."

Step 1 - Create first file and edit

As we had mentioned we will be using this web based IDE. You have complete view of the files in the working directory ltrdcn-3225. From here you can create files in the different directories we will create for the different components in the lab.

To create a file you just use the IDE itself.


And name the file req-aci.py

Building the Authentication Request script

For our simple request script we are going to just interact directly with the fabric. We have to get the request library imported into our script, and then work with the authentication to the ACI fabric like we did in the Postman section of the lab.

Step 2 - import request library

On the first line of req-aci.py you will add:


import requests, json

These will import into our script the request library and the JSON library to be able to construct the ReST API calls to the ACI fabric.

Step 3 - Create variable and dictionary for authentication

Then add some crude credentials to login to the APIC.


import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'

With these now you will create a dictionary that will contain the structure of authentication into the APIC. This is a standard Python dictionary data structure that is the same for all authentication requests. You can also utilize XML to see the request and that request would look as:

  • <aaaUser name="admin" pwd="cisco.123"/>

but we will stick to JSON format for this lab.


import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'
credentials = {'aaaUser':
                {'attributes':
                    {'name': apic_username, 'pwd': apic_password }
                }
    }

Step 4 - Build URL to reach ACI fabric

Now that you have the structure of the authentication request, you have to build the code to send the request to the APIC controller. The first thing is to set the base URL that we will use to make the request against the AAA object models of the fabric to gain a authentication token. For better results we will create two variables. base_url and login_url where we can append to that base string, base_url, with the specific object we want to reach in the fabric.

If you remember when we talked about the API, you can see the structure was like:

So what we do is set a variable to be the protocol, APIC host and the API that is standard across all references of the ACI fabric.


import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'
credentials = {'aaaUser':
                {'attributes':
                    {'name': apic_username, 'pwd': apic_password }
                }
    }

base_url = 'https://%s/api/' % apic_ip
login_url = base_url + 'aaaLogin.json'

Step 5 - Push JSON request to the ACI APIC controller

With the login_url built for this fabric, we have to convert the dictionary for the credentials information to JSON. Using the JSON library that is part of Python, we will take the dictionary that we built for Python and create a variable that will be called json_credentials that is what will be sent to the APIC in the REST request using the request library.


import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'
credentials = {'aaaUser':
                {'attributes':
                    {'name': apic_username, 'pwd': apic_password }
                }
    }

base_url = 'https://%s/api/' % apic_ip
login_url = base_url + 'aaaLogin.json'

json_credentials = json.dumps(credentials)

With the credentials in JSON format, you can proceed to create the POST request to the ACI fabric. Since we are going to be sending data to the ACI fabric we will be using a REST POST request.

Now, the request library needs to invoke the POST request and the answer from the APIC will be injected into the post_response variable. We add a print message for the response to see what is the response from the APIC.

You may notice in the following section that we have added the parameter to the request call verify = False. This is to tell requests library to ignore the self signed certificate that is on the APIC controller.

import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'
credentials = {'aaaUser':
                {'attributes':
                    {'name': apic_username, 'pwd': apic_password }
                }
    }

base_url = 'https://%s/api/' % apic_ip
login_url = base_url + 'aaaLogin.json'

json_credentials = json.dumps(credentials)

post_response = requests.post(login_url, data=json_credentials, verify=False)
print(post_response)

At this point make sure you have saved your file. Then, return to your Terminal window.You will now execute the script in the terminal. Make sure you are in the correct directory.


    cd ~/ltrdcn-3225/requests

And then run the Python script.


    python3 req-aci.py

The output of the command should be similar to the following output:


InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See:
https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
<Response [200]>

The following table shows you just a couple of the various response codes to assist you understanding this concept.

CODE Description
200 The request has succeeded.
202 The request has been accepted, but processing hasn't completed
400 Bad request. The request could not be understood by the server due to malformed syntax.
401 Unauthorized. The request requires user authentication.
403 Forbidden. The server understood the request, but is refusing to fulfill it.
404 Not found. The server has not found anything matching the Request-URI
500 Internal Server Error. The server encountered an unexpected condition which prevented it from fulfilling the request.

The key in that output is going to be the proper Response code, that should be 200 for OK.

Step 6 - Extracting token from APIC Authentication response

In the response object created by the requests library is the authentication token that we are looking for to gain access to the APIC controller API. The simple print command that we did print(post_response) was to validate the response. You can extract more details on the response by simply doing a print to the same object but invoking the text method of the object print(post_response.text).

The output will be EXTENSIVE as the text of the response is printed in itself. You can make this change if you wish to see the output. If not you can jump straight to the code that we are interested in that would extract the token from the response directly. What we are looking for is the authentication token that is needed for you to issue commands into the ACI fabric in itself.

First, we have to take the response that the APIC sent back and convert that into a dictionary that Python can process. The response is in essence just text inside the response object of the request library. Using the json.loads command, the string response will be converted into a Python dictionary. At that point you can easily extract the login attributes field from the response to get the token.

Then you have to parse the object in return to extract the token. The response dictionary will look as follows (ordering of fields is different every time):

    {
  • "totalCount": "1",
  • "imdata": [
    • {
      • "aaaLogin": {
        • "attributes": {
          • "token": "the token",
          • "siteFingerprint": "",
          • "sessionId": "",
          • "lastName": "",
          • "firstName": "",
          • "version": "",
          • "node": "",

Return to your editor. To extract that value you have to select exactly the right position in the dictionary to get the value. In this case post_response_json['imdata'][0]['aaaLogin']['attributes']


import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'
credentials = {'aaaUser':
                {'attributes':
                    {'name': apic_username, 'pwd': apic_password }
                }
    }

base_url = 'https://%s/api/' % apic_ip
login_url = base_url + 'aaaLogin.json'

json_credentials = json.dumps(credentials)

post_response = requests.post(login_url, data=json_credentials, verify=False)

post_response_json = json.loads(post_response.text)
login_attributes = post_response_json['imdata'][0]['aaaLogin']['attributes']

With that you can extract the token directly as the token would be in login_attributes['token'] and we can built the cookie dictionary that will be needed for further connections.


import requests, json

apic_ip = '10.0.226.41'
apic_username = 'aciproglab04'
apic_password = 'cisco.123'
credentials = {'aaaUser':
                {'attributes':
                    {'name': apic_username, 'pwd': apic_password }
                }
    }

base_url = 'https://%s/api/' % apic_ip
login_url = base_url + 'aaaLogin.json'

json_credentials = json.dumps(credentials)

post_response = requests.post(login_url, data=json_credentials, verify=False)

post_response_json = json.loads(post_response.text)
login_attributes = post_response_json['imdata'][0]['aaaLogin']['attributes']

cookies = {}
cookies['APIC-Cookie'] = login_attributes['token']
print(cookies)

With that, make sure you save your Python file again and return to your Terminal window. Then, execute the script and see the cookie definition.


    python3 req-aci.py


{'APIC-Cookie': u'IP2IOcGIqUuf3u7Jb3EItLeZDDRknypcQPruHzVV25p5iveE/nACcT2jiTV56G
N051ZU61WGhj21tAM5sb5uSzOUgzjtt2hntR5MV7+em6Fgj7CEkni+4bWjAVi/Hlw9czDJp2hCCj
oOjuqZ5MExCmqHw4RNR+PXFPxLaSn0csTY+W4Kpyn2mIsLfWwfsXqsLydk4i+iiHgsZNxxKxL0H1
Woj4e6cRdBFX37W7b6ZP/RJ0Wlz1hDEd6+D+yUQQnZ0BCYrtYBWvf8q6ZsiOoR6g=='}

And with that token, all future requests to the ACI fabric can be performed. The token will expire over time, but you can write your code in such a way that it can execute all the sequence of requests to the fabric using the same authentication token. Then when completed, that token can expire and you would re-execute the authentication code to refresh and get a new token.