- How can you easily dump data on an APIC from the Object Store or API using Python.
The APIC used to have a quickly thrown together object dumper known as dekhore, however this seems to have been removed. The original dekhore script with some path mangling lines commented out can run as is if you just upload it to an APIC, but this is not ideal. Another way to dump data from the object store using python on the APIC is to do it manually using what we call pysdk directly. What follows are some examples.
Use a script or the python interactive shell. A python script would need the standard hashbang or would need to be run as python /path/to/script/script.py. The standard hashbang would look like this:
Also the scripts permissions would need to be changed via the command:
chmod +x /path/to/script/script.py
One other oddity that we discovered recently is that scripts saved in /bootflash are not allowed to be executed. So the script will need to be saved outside of /bootflash. The users home directory or a subdirectory of their homedirectory is probably fine.
To get into the interactive python shell you simply type python at the iBash prompt:
Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Importing the Fs Command Context and Getting a Context and MoDirectory
The easiest way to utilize pysdk is to import what is known as the FsCmdContext and then get a Managed Object Directory from it. Since we are on an APIC already, this will utilize the CLI to traverse the MIT directory and do lookups of Dn's and classes via Python. This can be done in a script or via the interactive Python shell as long as it is done on the APIC itself. Here I show how to do this in the interactive Python shell only but the same concept applies to an on APIC script:
>>> from insieme.cli.executor import FsCmdContext
>>> ctx = FsCmdContext()
>>> moDir = ctx.getMoDirectory()
Utilizing the MoDirectory
The MoDirectory object has many methods that can be seen if you execute a help(moDir) at this point.
| Methods defined here:
| __init__(self, **kwargs)
| commit(self, mo, reloadMo=True, **options)
| create(self, className, parentMoOrDn=None, **creationProps)
| createExplicitRelation(self, relClassName, srcMoOrDn, targetMoOrDn)
| createNamedRelation(self, relClassName, srcMoOrDn, **creationProps)
| endSubscription(self, subId, **options)
| exists(self, dn, **options)
| fetchChildren(self, parentMo, childClass=None, pfilter=None, **options)
| fetchRelations(self, parentMo, pfilter=None, **options)
| lookupByClass(self, className, parentDn=None, pfilter=None, **options)
| lookupByDn(self, dn, **options)
| lookupFaults(self, dn, pfilter=None, **options)
| lookupHealths(self, dn, pfilter=None, **options)
| lookupRecord(self, recType, affectedDn, id, **options)
| lookupRecords(self, recType, affectedDn, pfilter=None, **options)
| lookupStats(self, dn, className, filterObj=None, **options)
| lookupUrl(self, url, **options)
| setFaultAck(self, dn, code, ack, **options)
| subscribeToDn(self, dn, callback, **options)
| Data descriptors defined here:
| dictionary for instance variables (if defined)
| list of weak references to the object (if defined)
[These are going off the top of my head and have not been verified]
- parentMoOrDn arguments accept either an object for the parent Mo, a Dn object for the parent Mo or a string that represents the parent Mo's Dn.
- className and relClassName arguments require a string for the class name, examples "faultInst" or "aaaUser".
- parentMo and mo arguments require an actual object, a string will not do.
- pFilter arguments are property filters and they work similarly to the Cobra SDK property filters.
- the url argument is a string representing a url for the api that would map to a Dn.
- dn arguments require either a dn object or a string representing a dn.
Lookup By Class
Here is an example of doing a lookupByClass, note how just looking at an object it is printed and formatted pretty nicely for you.
>>> faultInst = moDir.lookupByClass('faultInst')
ack : no
cause : inoperable
changeSet : operState (Old: operable, New: inoperable)
code : F0023
created : 2014-08-05T08:33:18.092-07:00
descr : Provider inoperable
dn : topology/pod-1/node-1/local/svc-extXMLApi-id-255/uni/userext/tacacsext/tacacsplusprovider-172.23.96.196/fault-F0023
domain : security
highestSeverity : minor
lastTransition : 2014-08-05T08:35:41.703-07:00
lc : raised
modTs : 0
occur : 1
origSeverity : minor
prevSeverity : minor
rn : fault-F0023
rule : aaa-tacacs-plus-provider-tacacs-plus-provider-inoperable
severity : minor
subject : security-provider
type : operational
Another thing about the class query is that you get a list.
Lookup By Dn
You can also query by a specific Dn and again the result is printed nicely (but you don't get a list).
>>> uni = moDir.lookupByDn('uni')
dn : uni
lcOwn : local
modTs : 2014-08-03T16:43:28.164-07:00
monPolDn : uni/fabric/monfab-default
rn : uni
uid : 0