I’ve come to love PowerShells ability to perform reflection on any given object (I.e. Get-Member). The way the OnTap SDK was implemented does not support reflection… directly. The problem is the SDK consists of two classes that are able to interact with the ZAPI interfaces. Basically NaServer holds everything needed to connect->execute-> return results. Likewise the NaElement knows how to take input, and format that input into a valid XML request for ZAPI. NaElement also has all the logic needed to navigate, and use the information returned by a request. So what does that mean to us? Neither object has any knowledge of the actual API! This utterly kills the ability to “feel out” a given object. I can’t (new-object something|gm) till I find what I’m looking for, and I wanted that ability.
That small capability is almost a deal breaker for me. I’ve spent hours upon hours with the API on one monitor, and PowerShell on the other… it’s not fun! I sent out an open call during my last post, and was quickly taken up on it. As I sat down last night, and started digging through the API yet again. I decided enough was enough… I sat down and wrote a couple functions that more or less allow me to perform a primitive version of reflection. More accurately I can search the API reference right there from my console. I was so pleased with the outcome I decided to post a quick how to.
Before all that I should highlight one last time exactly what is needed to build a ZAPI request.
- You’ll always start with a New NaElement for the API.
- From here it’s a logic gate,
- If parameter is a primitive type (string,int,bool) then add with the AddNewChild method.
- If parameter is a NaType then start another New NaElement, and build that NaType, once complete add your new NaType to the request via the AddChildElement method.
- Submit your request via your NaServer object InvokeElem method.
the tool set consists of three small PowerShell functions:
Searches for a ZAPI request that contains a given text, and works similar to Get-Command.
Given an API to target, return any input/output parameters needed to perform that action.
There are only three primitive types in ZAPI (String, Int, Bool). In addition to those three there are 85+ NaTypes that are comprised of the three primitives. This function will return what is required to build an instance of that type.
Putting it to the test:
First off we need a task; we’ll start with something simple like renaming a volume, we’ll rename vol1 to vol2. As the old PowerShell Demo goes step one is look for a command. ZAPI has a strict naming convention similar to PowerShell only in reverse. For the most part every API call will follow Noun –Verb. With that knowledge I searched for any API call that had the noun volume.
Immediately I noticed volume-Rename… looks promising. At this point I could hop back in the SDK docs, but instead let’s just see what the parameters are.
As you can see at this point I think we have the right API. If we wanted to look and see what is returned from this command (I already know this particular command has no output) just add the –output switch. So at this point we’re ready to go! The code to rename a volume would be…
$NaElement = New-Object NetApp.Manage.NaElement("volume-rename")
$Results = $NaServer.InvokeElem($NaElement)
Not quite as good as real objects but you can derive the same result.