In this article, I'd like to focus on a few great tips that I've found while browsing through the PowerCLI forums. As I take you through these posts, I'll explain what it was that I found interesting in them, and why. I'll also provide background information on some of the techniques that were used.
Thinking outside of the PowerShell box
First up is a post titled, "Need a PowerShell script to find the process ID (PID) of VMs in a ESX box." The premise of this post is that the author needed to find a piece of information that he only knew how to obtain by logging into the ESX Console Operating System (COS). The reason why he needs this process ID isn't relevant at the moment, but it suffices to say that sometimes you have to log in to the COS to perform certain diagnostic tasks.
This post is interesting because it seems to expose a weak spot in the vSphere Application Programming Interface (API), upon which PowerCLI is based. Like all APIs, this one was created as an abstraction layer to make programming against a product or a product suite as consistent and as flexible as possible, while introducing features which help ease the task of developing software. The problem is that the COS that works with the ESX hypervisor is actually an operating system. Operating systems tend to have rather complicated, and in some cases, very fragmented user interfaces.
Back to the PowerCLI and the vSphere API. This vSphere API is a very structured thing layered atop the features which are exposed by the lowest levels of VMware's architecture. Operating systems aren't quite as structured! Unfortunately, the vSphere API does not represent a perfect map of everything that you can do while logged into the COS. Since PowerCLI is built on top of the same API, this means that you can't use PowerCLI to do things inside the console OS –at least not directly. And that's where the solution posted to the forum comes in.
Fortunately for us, and for the original poster, PowerCLI is built on PowerShell, and PowerShell can call an external process as a part of a script. The solution posted by LucD does just that. In this case, the external process is plink.exe, a very popular command-line secure shell (SSH) client made by the same team that wrote PuTTY. The script provided actually uses plink to log in to the ESX console, and then it remotely executes "vm-support". This utility is one way to gather the bit of information that the original poster was after.
You might say that this is a bit of a hack, because you aren't accessing the data through the "approved interface," but sometimes, you just have to find a way. The moral of this particular story is: don't be afraid to think outside of the box. The vSphere API is a pretty big box, but it wasn't intended to solve every problem you might encounter with your vSphere system. In fact, it might be accurate to say that it's not really intended for diagnostics at all.
When PowerCLI cmdlets don't cut it
This second post is titled, "Script to configure security on vSwitch error." Although the script in this post is fairly advanced, I thought this would be a really good example because it describes what I think is a common scenario once you move beyond the use of the PowerCLI cmdlets and into the realm of the vSphere API. The underlying premise is that the cmdlets (which I have talked about in previous articles) do not have 100% feature parity with the API. However, through the use of the Get-View cmdlet and some other tricks, you can do pretty much anything that needs to be done.
What the poster wanted to do in this case was toggle some security settings on a vSwitch. I'm referring to the ones on the security tab when you go into the properties of a virtual switch, as seen in this screenshot:
Unfortunately, you can't set these properties with a cmdlet, as seen in the help text for the Set-VirtualSwitch cmdlet:
The cmdlet lacks security settings. It's possible that VMware will continue to close the feature gap between the cmdlets and the API over time, but that doesn't help us today.
In order to move past this barrier, you have to use the Get-View cmdlet. Get-View is very useful -- it's like having a release valve that lets you bust out some really cool tricks. I'm not going to go into great detail about the cmdlet here, but what you need to know is that the PowerCLI cmdlets present an interface to the virtualization administrator which is customized to be consistent with how PowerShell works. This is great for administrators when it works, but when you hit against limits of the included cmdlets, you have to work with the underlying API objects. In other words, you need to understand a totally different interface -- the same one that programmers see when they develop software for vSphere.
Getting back to the forum post, the poster has a code sample that looks like this (edited slightly for readability):
Line 1 retrieves a list of host servers and assigns them to a variable. Line 2 iterates through every host server contained within that variable, and grabs the switch named "vSwitch2." Line 3 is where you can see the Get-View cmdlet used to obtain that raw object.
In lines 4-6, you get a glimpse of what the vSphere API has in the way of naming conventions as things are prepared to update a virtual switch "the hard way."
Line 7 is where things start to go wrong. The poster made a perfectly valid assumption that in order to edit a virtual switch, you would start with a new specification object (these are used commonly in the vSphere API to describe an object which you are creating or modifying).
The problem, as LucD so helpfully explained in his reply, is that the API is sometimes quite picky. It wants to see a specification object in which every optional field has been explicitly defined with a default value. At this point, you can either figure out what these defaults are supposed to be, or you can simply copy an existing spec and modify it to your heart's content. The updated code looks like this:
I wanted to highlight this particular forum post to highlight what should be a best practice when working with vSphere API objects with PowerShell. When you are modifying an existing object, clone that object's specification, and then modify the cloned spec. This will save you from having to wade through the API documentation to find the right default values that may be a headache when you go to try to use the newly created specification object. However, bear in mind that this shortcut won't help you when it's time to create new objects from scratch.
Hal Rottenberg is a Microsoft PowerShell MVP and VMware vExpert living in Woodstock, Georgia. He is well-known in system administrator circles for co-hosting the PowerScripting Podcast and heading up the PowerShellCommunity organization. He is also the author of a book titled "Managing VMware Infrastructure with PowerShell: TFM" published by SAPIEN Press in 2009.