Introduction to ACI Programmability
The Cisco ACI programmability model allows complete programmatic access to the application centric infrastructure. With this access, customers can integrate network deployment into management and monitoring tools and deploy new workloads programmatically.
ACI Fabric is configured using an abstract policy model on the Cisco Application Policy Infrastructure Controller (APIC). The APIC has a very rich and complete object model that is accessible through a programmatic REST API. The API accepts and returns HTTP or HTTPS messages that contain JavaScript Object Notation (JSON) or Extensible Markup Language (XML) documents. You can use any programming language to generate the messages and the JSON or XML documents that contain the API methods or managed object (MO) descriptions.
In addition to standard REST interface, Cisco provides several open source tools/frameworks to automate and program the APIC: ACItoolkit, Cobra (Python), ACIrb (Ruby), Puppet, Ansible etc.
This section introduces the user to some basic APIC configuration use cases such as Physical domain config, VLAN pool creation and Tenant config.
Configuration
Authentication
POST http://APIC-IP/api/aaaLogin.json HTTP/1.1
Content-Type: application/json
{
"aaaUser" : {
"attributes" : {
"name" : "APIC_USER",
"pwd" : "APIC_PASSWORD"
}
}
}
In order to execute a request the login needs to be performed first. A cookie will get generated and stored for subsequent execution. In this script replace APIC-IP in the URL with the IP or hostname of the APIC server. If you do not have access to an ACI environment, you can use the ACI Simulator in the DevNet Sandbox.
Using Postman
If you are more comfortable with a GUI, use Postman which is a Google Chrome Browser application to make REST API calls.
Executing ACI-REST using Postman for first time:
- Enter the IP address of the APIC server in your browser and accept the certificate if asked.
- Copy POST URL, mentioned in Authentication section to the right, after replacing APIC-IP with IP address of APIC.
- Select method as POST
- Open raw JSON section.
- Copy BODY JSON to raw JSON body section of postman.
- Replace APIC_USERNAME with apic user.
- Replace APIC_PASSWORD with apic password.
- Click send button
Note: If the cookie gets expired you might have to perform the above steps again.
For subsequent REST call:
- Copy POST URL, after replacing APIC-IP with IP address of APIC.
- Select method as POST
- Open raw JSON section.
- Copy BODY JSON to raw JSON body section of postman.
- Click send button
Using ACI Toolkit
If you are ready to start programming, download and install the ACI Toolkit.
Environment
Required
- Python 2.7+
- setuptools package
Downloading
If you have git installed, clone the repository
git clone https://github.com/datacenter/acitoolkit.git
Installing
After downloading, install using setuptools.
cd acitoolkit
python setup.py install
If you plan on modifying the actual toolkit files, you should install the developer environment that will link the package installation to your development directory.
cd acitoolkit
python setup.py develop
ACI Toolkit Samples
This directory contains sample scripts that use the python library.
Set up
In order to use the examples in this directory, it is important to set the PYTHONPATH variable to include the path to the ACI toolkit or have installed the acitoolkit using setup.py.
credentials.py
Many of the samples in this directory use the file credentials.py to login to the APIC. Before running, edit the credentials.py with the username, password, and IP address for your environment.
To execute the sample files
- cd samples
- vi example.py (Copy the script here)
- Execute the script. example: python example.py
Sample scripts
These scripts can also be found at https://github.com/datacenter/aci-examples
Physical Domain
HTTP
POST http://APIC-IP/api/node/mo/uni.json HTTP/1.1
Content-Type: application/json
Cache-Control: no-cache
{
"physDomP": {
"attributes": {
"name": "test_phy_dmn",
"dn": "uni/phys-test_phy_dmn"
},
"children": [{
"infraRsVlanNs": {
"attributes": {
"tDn": "uni/infra/vlanns-[test_vlan]-dynamic"
}
}
}]
}
}
Python
import acitoolkit.acitoolkit as aci
# Define static values to pass (edit these if you wish to set differently)
DEFAULT_PHY_DOMAIN_NAME = 'test_phy_dmn'
def main():
"""
Main create tenant routine
:return: None
"""
# Get all the arguments
description = 'It logs in to APIC and will create the physical domain.'
creds = aci.Credentials('apic', description)
creds.add_argument('-p', '--phy_domain',
help='The name of physical domain',
default=DEFAULT_PHY_DOMAIN_NAME)
args = creds.get()
# Login to the APIC
session = aci.Session(args.url, args.login, args.password)
resp = session.login()
if not resp.ok:
print('%% Could not login to APIC')
# Create the physical Domain
phy_dmn = aci.PhysDomain(args.phy_domain)
# Push the physical domain to the APIC
resp = session.push_to_apic(phy_dmn.get_url(),
phy_dmn.get_json())
if not resp.ok:
print('%% Error: Could not push configuration to APIC')
print(resp.text)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
Configure physical domain and attach VLAN pool to it
The physical domain profile, which stores the physical resources (ports and port-channels) and encapsulate resources (VLAN/VXLAN) that should be used for endpoint groups associated with this domain. The following example shows the creation of the physical domain by attaching AEP and VLAN pools.
VLAN Pool
HTTP
POST http://APIC-IP/api/node/mo/uni/infra/vlanns-[test_vlan]-dynamic.json HTTP/1.1
Content-Type: application/json
Cache-Control: no-cache
{
"fvnsVlanInstP":{
"attributes":{
"name":"test_vlan"
},
"children":[
{
"fvnsEncapBlk":{
"attributes":{
"from":"vlan-222",
"to":"vlan-223"
}
}
}
]
}
}
Python
import acitoolkit.acitoolkit as aci
# Define static values to pass (edit these if you wish to set differently)
DEFAULT_VLAN_NAME = 'test_vlan'
def main():
"""
Main create tenant routine
:return: None
"""
# Get all the arguments
description = 'It logs in to the APIC and will create the vlan pool.'
creds = aci.Credentials('apic', description)
creds.add_argument('-v', '--vlan', help='The name of vlan pool',
default=DEFAULT_VLAN_NAME)
args = creds.get()
# Login to the APIC
session = aci.Session(args.url, args.login, args.password)
resp = session.login()
if not resp.ok:
print('%% Could not login to APIC')
# Create the VLAN pool
vlan_pool = aci.NetworkPool(args.vlan, 'vlan', '222', '223', 'dynamic')
# Push the VLAN pool to the APIC
resp = session.push_to_apic(vlan_pool.get_url(),
vlan_pool.get_json())
if not resp.ok:
print('%% Error: Could not push configuration to APIC')
print(resp.text)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
Configure VLAN Pool with VLAN range
The provider access function is defined when the hypervisor is using an encapsulation protocol, such as VxLAN/NVGRE, and provides the policies to impacting VxLAN/NvGRE packets from NVGRE. You do not need to provide the encapsulation VLAN and endpoint for the provider access function. The system uses the Infra VLAN (provided during APIC bootup) as the encapsulation and associates it to the default endpoint group under the default tenant. This section describe how you can manage and configure VLAN-pool on APIC using different configuration management code snippet.
Tenant Configuration
HTTP
POST http://APIC-IP/api/mo/uni.json HTTP/1.1
Content-Type: application/json
Cache-Control: no-cache
{
"fvTenant": {
"attributes": {
"name": "test_tenant"
}
}
}
Python
import acitoolkit.acitoolkit as aci
# Define static values to pass (edit these if you wish to set differently)
DEFAULT_TENANT_NAME = 'test_tenant'
def main():
"""
Main create tenant routine
:return: None
"""
# Get all the arguments
description = 'It logs in to the APIC and will create the tenant.'
creds = aci.Credentials('apic', description)
creds.add_argument('-t', '--tenant', help='The name of tenant',
default=DEFAULT_TENANT_NAME)
args = creds.get()
# Login to the APIC
session = aci.Session(args.url, args.login, args.password)
resp = session.login()
if not resp.ok:
print('%% Could not login to APIC')
# Create the Tenant
tenant = aci.Tenant(args.tenant)
# Push the tenant to the APIC
resp = session.push_to_apic(tenant.get_url(),
tenant.get_json())
if not resp.ok:
print('%% Error: Could not push configuration to APIC')
print(resp.text)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
Configure a tenant
A tenant is a logical container for application policies that enable an administrator to exercise domain-based access control. A tenant represents a unit of isolation from a policy perspective, but it does not represent a private network. Tenants can represent a customer in a service provider setting, an organization or domain in an enterprise setting, or just a convenient grouping of policies. This section describe how you can manage and configure tenant on APIC using different configuration management code snippet.