Examples

Before You Begin

Before applying these examples, refer to the APIC documentation to understand the Cisco Application Centric Infrastructure (ACI) and the APIC. The APIC documentation contains explanations and examples of these and other tasks using the APIC GUI, CLI, and REST API. See the Cisco APIC Getting Started Guide for detailed examples.

Initial Statements for All Examples

The following setup statements or their equivalents are assumed to be present in any APIC Python API program using these code examples.

from cobra.mit.access import MoDirectory
from cobra.mit.session import LoginSession
session = LoginSession('https://sample-host.coolapi.com', 'admin',
                       'xxx?xxx?xxx')
moDir = MoDirectory(session)
moDir.login()

The above code snippet creates an MoDirectory, connects it to the endpoint and then performs authentication. The moDir can be used to query, create/delete Mos from the end point.

Creating a Tenant

The tenant (fv:Tenant object) is a container for policies that enable an administrator to exercise domain based access control so that qualified users can access privileges such as tenant administration and networking administration. According to the Cisco APIC Management Information Model Reference, an object of the fv:Tenant class is a child of the policy resolution universe (‘uni’) class. This example creates a tenant named ‘ExampleCorp’ under the ‘uni’ object.

# Import the config request
from cobra.mit.request import ConfigRequest
configReq = ConfigRequest()

# Import the tenant class from the model
from cobra.model.fv import Tenant

# Get the top level policy universe directory
uniMo = moDir.lookupByDn('uni')

# create the tenant object
fvTenantMo = Tenant(uniMo, 'ExampleCorp')

The command creates an object of the fv.Tenant class and returns a reference to the object. A tenant contains primary elements such as filters, contracts, bridge domains and application network profiles that we will create in later examples.

Application Profiles

An application profile (fv.Ap object) is a tenant policy that defines the policies, services, and relationships between endpoint groups (EPGs) within the tenant. The application profile contains EPGs that are logically related to one another. This example defines a web application profile under the tenant.

# Import the Ap class from the model
from cobra.model.fv import Ap

fvApMo = Ap(fvTenantMo, 'WebApp')

Endpoint Groups

An endpoint group is a collection of network-connected devices, such as clients or servers, that have common policy requirements. This example creates a web application endpoint group named ‘WebEPG’ that is contained in an application profile under the tenant.

# Import the AEPg class from the model
from cobra.model.fv import AEPg

fvAEPgMoWeb = AEPg(fvApMo, 'WebEPG')

Physical Domains

This example associates the web application endpoint group with a bridge domain.

# Import the related classes from the model
from cobra.model.fv import RsBd, Ctx, BD, RsCtx

# create a private network
fvCtxMo = Ctx(fvTenantMo, 'private-net1')

# create a bridge domain
fvBDMo = BD(fvTenantMo, 'bridge-domain1')

# create an association of the bridge domain to the private network
fvRsCtx = RsCtx(fvBDMo, tnFvCtxName=fvCtxMo.name)

# create a physical domain associated with the endpoint group
fvRsBd1 = RsBd(fvAEPgMoWeb, fvBDMo.name)

Contracts and Filters

A contract defines the protocols and ports on which a provider endpoint group and a consumer endpoint group are allowed to communicate. You can use the directory.create function to define a contract, add a subject, and associate the subject and a filter.

This example creates a Web filter for HTTP (TCP port 80) traffic.

# Import the Filter and related classes from model
from cobra.model.vz import Filter, Entry, BrCP, Subj, RsSubjFiltAtt

# create a filter container (vz.Filter object) within the tenant
filterMo = Filter(fvTenantMo, 'WebFilter')

# create a filter entry (vz.Entry object) that specifies bidirectional
# HTTP (TCP/80) traffic
entryMo = Entry(filterMo, 'HttpPort')
entryMo.dFromPort = 80    # HTTP port
entryMo.dToPort = 80
entryMo.prot = 6          # TCP protocol number
entryMo.etherT = "ip"     # EtherType

# create a binary contract (vz.BrCP object) container within the
# tenant
vzBrCPMoHTTP = BrCP(fvTenantMo, 'WebContract')

# create a subject container for associating the filter with the
# contract
vzSubjMo = Subj(vzBrCPMoHTTP, 'WebSubject')
RsSubjFiltAtt(vzSubjMo, tnVzFilterName=filterMo.name)

Namespaces

A namespace identifies a range of traffic encapsulation identifiers for a VMM domain or a VM controller. A namespace is a shared resource and can be consumed by multiple domains such as VMM and L4-L7 services. This example creates and assigns properties to a VLAN namespace.

# Import the namespaces related classes from model
from cobra.model.fvns import VlanInstP, EncapBlk

fvnsVlanInstP = VlanInstP('uni/infra', 'namespace1', 'dynamic')
fvnsEncapBlk = EncapBlk(fvnsVlanInstP, 'vlan-5', 'vlan-20',
                            name='encap')
nsCfg = ConfigRequest()
nsCfg.addMo(fvnsVlanInstP)
moDir.commit(nsCfg)

VM Networking

This example creates a virtual machine manager (VMM) and configuration.

# Import the namespaces related classes from model
from cobra.model.vmm import ProvP, DomP, UsrAccP, CtrlrP, RsAcc
from cobra.model.infra import RsVlanNs

vmmProvP = ProvP('uni', 'VMWare')
vmmDomP = DomP(vmmProvP, 'Datacenter')
vmmUsrAccP = UsrAccP(vmmDomP, 'default', pwd='password', usr='administrator')
vmmRsVlanNs = RsVlanNs(vmmDomP, fvnsVlanInstP.dn)
vmmCtrlrP = CtrlrP(vmmDomP, 'vserver-01', hostOrIp='192.168.64.9')
vmmRsAcc = RsAcc(vmmCtrlrP, tDn=vmmUsrAccp.dn)

# Add the tenant object to the config request and commit
confgReq.addMo(fvTenantMo)
moDir.commit(configReq)

Creating a Complete Tenant Configuration

This example creates a tenant named ‘ExampleCorp’ and deploys a three-tier application including Web, app, and database servers. See the similar three-tier application example in the Cisco APIC Getting Started Guide for additional description of the components being configured.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from __future__ import print_function
# Copyright 2015 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#!/usr/bin/env python


# Import access classes
from cobra.mit.access import MoDirectory
from cobra.mit.session import LoginSession
from cobra.mit.request import ConfigRequest

# Import model classes
from cobra.model.fvns import VlanInstP, EncapBlk
from cobra.model.infra import RsVlanNs
from cobra.model.fv import Tenant, Ctx, BD, RsCtx, Ap, AEPg, RsBd, RsDomAtt
from cobra.model.vmm import DomP, UsrAccP, CtrlrP, RsAcc


# Policy information
VMM_DOMAIN_INFO = {'name': "mininet",
                   'ctrlrs': [{'name': 'vcenter1', 'ip': '192.0.20.3', 
                               'scope': 'vm'}],
                   'usrs': [{'name': 'admin', 'usr': 'administrator',
                             'pwd': 'pa$$word1'}],
                   'namespace': {'name': 'VlanRange', 'from': 'vlan-100',
                                 'to': 'vlan-200'}
                  }

TENANT_INFO = [{'name': 'ExampleCorp',
                'pvn': 'pvn1',
                'bd': 'bd1',
                'ap': [{'name': 'OnlineStore',
                        'epgs': [{'name': 'app'},
                                 {'name': 'web'},
                                 {'name': 'db'},
                                ]
                       },
                      ]
                }
              ]

def main(host, port, user, password):

    # CONNECT TO APIC
    print('Initializing connection to APIC...')
    apicUrl = 'http://%s:%d' % (host, port)
    moDir = MoDirectory(LoginSession(apicUrl, user, password))
    moDir.login()

    # Get the top level Policy Universe Directory
    uniMo = moDir.lookupByDn('uni')
    uniInfraMo = moDir.lookupByDn('uni/infra')

    # Create Vlan Namespace
    nsInfo = VMM_DOMAIN_INFO['namespace']
    print("Creating namespace %s.." % (nsInfo['name']))
    fvnsVlanInstPMo = VlanInstP(uniInfraMo, nsInfo['name'], 'dynamic')
    #fvnsArgs = {'from': nsInfo['from'], 'to': nsInfo['to']}
    EncapBlk(fvnsVlanInstPMo, nsInfo['from'], nsInfo['to'], name=nsInfo['name'])
    
    nsCfg = ConfigRequest()
    nsCfg.addMo(fvnsVlanInstPMo)
    moDir.commit(nsCfg)

    # Create VMM Domain
    print('Creating VMM domain...')

    vmmpVMwareProvPMo = moDir.lookupByDn('uni/vmmp-VMware')
    vmmDomPMo = DomP(vmmpVMwareProvPMo, VMM_DOMAIN_INFO['name'])
    
    vmmUsrMo = []
    for usrp in VMM_DOMAIN_INFO['usrs']:
        usrMo = UsrAccP(vmmDomPMo, usrp['name'], usr=usrp['usr'],
                        pwd=usrp['pwd'])
        vmmUsrMo.append(usrMo)

    # Create Controllers under domain
    for ctrlr in VMM_DOMAIN_INFO['ctrlrs']:
        vmmCtrlrMo = CtrlrP(vmmDomPMo, ctrlr['name'], scope=ctrlr['scope'],
                            hostOrIp=ctrlr['ip'])
        # Associate Ctrlr to UserP
        RsAcc(vmmCtrlrMo, tDn=vmmUsrMo[0].dn)
    
    # Associate Domain to Namespace
    RsVlanNs(vmmDomPMo, tDn=fvnsVlanInstPMo.dn)
   
    vmmCfg = ConfigRequest()
    vmmCfg.addMo(vmmDomPMo)
    moDir.commit(vmmCfg)
    print("VMM Domain Creation Completed.")

    print("Starting Tenant Creation..")
    for tenant in TENANT_INFO:
        print("Creating tenant %s.." % (tenant['name']))
        fvTenantMo = Tenant(uniMo, tenant['name'])
        
        # Create Private Network
        Ctx(fvTenantMo, tenant['pvn'])
        
        # Create Bridge Domain
        fvBDMo = BD(fvTenantMo, name=tenant['bd'])
        
        # Create association to private network
        RsCtx(fvBDMo, tnFvCtxName=tenant['pvn'])
        
        # Create Application Profile
        for app in tenant['ap']:
            print('Creating Application Profile: %s' % app['name'])
            fvApMo = Ap(fvTenantMo, app['name'])
            
            # Create EPGs 
            for epg in app['epgs']:
                
                print("Creating EPG: %s..." % (epg['name'])) 
                fvAEPgMo = AEPg(fvApMo, epg['name'])
                
                # Associate EPG to Bridge Domain 
                RsBd(fvAEPgMo, tnFvBDName=tenant['bd'])
                # Associate EPG to VMM Domain
                RsDomAtt(fvAEPgMo, vmmDomPMo.dn)

        # Commit each tenant seperately
        tenantCfg = ConfigRequest()
        tenantCfg.addMo(fvTenantMo)
        moDir.commit(tenantCfg)
    print('All done!')

if __name__ == '__main__':
    from argparse import ArgumentParser
    parser = ArgumentParser("Tenant creation script")
    parser.add_argument('-d', '--host', help='APIC host name or IP',
                        required=True)
    parser.add_argument('-e', '--port', help='server port', type=int,
                        default=80)
    parser.add_argument('-p', '--password', help='user password',
                        required=True)
    parser.add_argument('-u', '--user', help='user name', required=True)
    args = parser.parse_args()
    
    main(args.host, args.port, args.user, args.password)

Creating a Query Filter

This example creates a query filter property to match fabricPathEpCont objects whose nodeId property is 101.

# Import the related classes from model
from cobra.model.fabric import PathEpCont

nodeId = 101
myClassQuery.propFilter = 'eq(fabricPathEpCont.nodeId, "{0}")'.format(nodeId)

The basic filter syntax is ‘condition(item1, “value”)’. To filter on the property of a class, the first item of the filter is of the form pkgClass.property. The second item of the filter is the property value to match. The quotes are necessary.

Accessing a Child MO

This example shows how to access a child MO, such as a bridge-domain, which is a child object of a tenant MO.

dnQuery = DnQuery('uni/tn-coke')
dnQuery.subtree = 'children'
tenantMo = moDir.query(dnQuery)
defaultBDMo = tenantMo.BD['default']

Iteration for a Child MO

This example shows how to user iteration for a child MO.

dnQuery = DnQuery('uni/tn-coke')
dnQuery.subtree = 'children'
tenantMo = moDir.query(dnQuery)
for bdMo in tenantMo.BD:
    print str(bdMo.dn)