Automating Cisco ACI with PowerCLI (Part II)

In part I of the blog I’ve outlined the basic principles of how to connect PowerCli to an Cisco ACI environment, In this blog I will describe how to create ACI-functions that behave exactly the same as PowerShell Cmdlets.

PowerShell basics

PowerShell Cmdlets let you do things (get, add, new, remove items) and the output of that cmdlet can be used as an input for a new cmdlet through a method called: piping.

Here is one example: “Get-VDSwitch | Get-VDPortgroup”.
The “Get-VDSwitch” cmdlet will retrieve all Distributed vSwitches from the connected vCenters and the “Get-VDPortgroup” cmdlet will retrieve the Portgroups from the retrieved DVSwitches.
This is what makes PowerShell so powerfull, you can modify your entire environment with a few simple commands.

For the execution of REST API calls towards Cisco ACI I’m using “Functions” instead of cmdlets: Not really a big difference, but an function are easier to create (and I’m lacking Cmdlet-creation skills).
A function is a (repeatable) named block of code: by simply referring to the (function-)name the block of code is executed.
A function may contain parameters, which can be utilized during the executing of the function-code. The function also can return information to the parent-script a.k.a. the function-caller.

For the creation of the ACI functions I use the “advanced version” of a PowerShell Function:

Function <FunctionName> 
{
#contains all input parameters for the function
Param
(
)
#This scriptblock will be executed one-time at the beginning of the function
Begin
{
}
#This scriptblock will be executed one or multiple times depending on the variables 
Process
{
}
#This scriptblock will be executed one-time at the end of the function
End
{
#The Return cmdlet will return the variable to the function-caller.
Return $responsevalue
}
}

When calling a function, it will return information to the parent script which can be used via the piping-method for other functions. When using the piping-method the used variable(s) must be unique, because otherwise the other functions will not behave as expected.

REST API vs PowerShell

For the execution of REST API calls towards Cisco ACI, I will use the Execute-API-Call function which is created in part I . REST API calls use the methods ‘Get’, ‘Post’ and ‘Delete’, as powershell uses ‘Get-‘, ‘Add-‘, ‘New-‘ and ‘Remove-‘ constructs.
The challenge is to merge those two languages/worlds!

Cisco ACI’s policy model is based on a Management Information Tree (MIT) database.
The MIT is built upon hierarchical structured objects, which can be access by their distinguished name (DNs) and can be created, modified and deleted through REST API calls (if permissions allow it).
Each object consist of a unique class and one or more attributes.
You can use leverage REST API to look for particular class-objects.
The MIT can be accessed directly via VISORE by browsing to https://<APIC-IP-Address>/visore.html or you can leverage the API inspector from within the APIC GUI or right click an object and “save as..” to get the necessary DN or ObjectClass information in a JSON (or XML) format.

The MIT contains 3 important top-level objects:
– uni – The policy UNIverse, where all logical data and policies are stored in. This piece of the MIT is what makes ACI unique.
– CompUNI – The computed UNIverse, which contain all inventorised data from Virtual Machine Managers (like for example all inventory data contained by a vCenter server). This data cannot be modified through API call’s
– FabricTopology – All logical objects from the physical component connected within the ACI fabric.

When creating functions we will scope into one of those top-level objects.

a Function example

let’s start with an example: Retrieve (get) all VMware Virtual Machine Manager-domains.

By examining the (Visore) Object Browser on the APIC controller the REST-API call to retrieve all VMware VMM domains is:

GET https://<APICHOSTNAME>/api/node/mo/uni/vmmp-VMware.xml?query-target=children

This call will return all Managed Object’s (MO’s) with the “vmmDomP”-class including all attributes.

We’ve discovered the REST method and the URI; so let’s create a PowerShell function for this call:

Function Get-ACI-VMware-VMMDomain
{
Param ( 
#accept method:piping and variable is not mandatory
[Parameter(ValueFromPipelineByPropertyName=$true, Mandatory=$false)] 
[string]$APICHostname,
[Parameter(Mandatory=$false)] 
[string]$vmmDomPName 
) 
begin {
#define return variable array (for multiple VMM domains)
$returnarray = @()
#if no APIC hostname input is given use the global default.
if (!$APICHostname) {$APICHostname = $global:DefaultAPICController}
}
process {
# This is the URL we're going to be logging in to
$url = "https://" + $APICHostname + "/api/node/mo/uni/vmmp-VMware.json?query-target=children"
if ($vmmDomPName) {$url += "&query-target-filter=and(eq(vmmDomP.name,""$($vmmDomPName)""))"}
# Execute the API Call
$resultjSON = Execute-API-Call -method "GET" -ContentType "application/json" -url $url
#convert JSON layout to Powershell layout
$result = ConvertFrom-Json -InputObject $resultjSON.httpResponse
#store all necessary information in return array
foreach ($vmmDomP in ($result.imdata.vmmDomP.attributes)) {
$return = New-Object PsObject -Property @{
vmmDomPdn = $vmmDomP.dn
vmmDomPName = $vmmDomP.name}
$returnarray += $return}}
end {return $returnarray}
}

This function creates the REST API call and returns all necessary information from the ‘vmmDomP’-class objects, which can be used in other functions.
You can also filter on the ‘vmmDomP.name’ attribute to narrow the output.

So let’s make an function that retrieve all VMware VMM controllers

Function Get-ACI-VMware-VMMController
{
Param ( 
#accept method:piping and variable is not mandatory
[Parameter(ValueFromPipelineByPropertyName=$true, Mandatory=$false)] 
[string]$APICHostname,
[Parameter(ValueFromPipelineByPropertyName=$true, Mandatory=$false)] 
[string]$vmmDomPname,
[Parameter(ValueFromPipelineByPropertyName=$false, Mandatory=$false)] 
[string]$vmmCtrlrPname

) 
begin {
#define return variable array (for multiple VMM domains)
$returnarray = @()
#if no APIC hostname input is given use the global default.
if (!$APICHostname) {$APICHostname = $global:DefaultAPICController}
}
process {
# This is the URL we're going to be logging in to
if (!$vmmDomPName) {
#if no VMMDomain is given return all vmmCtrlrP-class objects
$url = "https://$($APICHostname)/api/node/class/vmmCtrlrP.json?"
if ($vmmCtrlrPname) {$url += "query-target-filter=and(eq(vmmCtrlrP.name,""$($vmmCtrlrPname)""))"}

} ELSE {
#if VMMDomain is given return all vmmCtrlrP-class objects only from those vmmDomP-class objects
$url = "https://$($APICHostname)/api/node/mo/uni/vmmp-VMware/dom-$($vmmDomPName).json?query-target=children&target-subtree-class=vmmCtrlrP"
}
# Execute the API Call
$resultjSON = Execute-API-Call -method "GET" -ContentType "application/json" -url $url
#convert JSON layout to Powershell layout
$result = ConvertFrom-Json -InputObject $resultjSON.httpResponse
#store all necessary information in return array
foreach ($vmmCtrlrP in ($result.imdata.vmmCtrlrP.attributes)) {
$return = New-Object PsObject -Property @{
'vmmCtrlrPname'= $vmmCtrlrP.name
'vmmCtrlrPdvsVersion' = $vmmCtrlrP.dvsVersion
'vmmCtrlrPhostOrIp' = $vmmCtrlrP.hostOrIp
'vmmCtrlrProotContName' = $vmmCtrlrP.rootContName}
$returnarray += $return}}
end {return $returnarray}
}

This second function almost looks the same as the ‘Get-ACI-VMware-VMMDomain’ function only with small, but important, differences: the changed URI’s and DN’s.

But here’s the fun part: You can not only use these as standalone functions , you can also connect those 2 functions with the powershell piping method!

Get-ACI-VMware-VMMDomain -vmmDomPName VMMDOMAINNAME | Get-ACI-VMware-VMMController

This command, with both functions, will return only the VMM controllers from the VMMDomain with the name ‘VMMDOMAINNAME’ (if there are any).

So now you’re able to make proper ACI-functions.

In my next blog I will use PowerCli output (VMware) to get information from ACI.
Stay tuned for Part 3 #CodeOn

1 Comment

  1. […] VorigeVolgende […]

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top