PowerNSX Tips

I've recently had the opportunity to do some work with NSX during some server migrations.  That work has been fairly repetitive for each group of servers that we're migrating so, you guessed it, I looked for an easy scripting/automation solution, and PowerNSX proved to be the right tool for the job!

As the name implies, PowerNSX is the NSX portion of PowerCLI.  Installing it is a breeze - just use a relatively up-to-date PowerShell window and fire off install-module PowerNSX.  That'll give you access to a whole set of NSX-oriented PowerShell cmdlets.  It's still in beta, so there's a lot of rough edges, but it's still proven to be an excellent tool for many tasks, including manipulating large numbers of VM Security Group Membership settings and creating Firewall rules.

One of those "rough edges" involves cached instances of objects.  For example, if I want to add a bunch of VMs to various security groups based on a CSV input, I'd often write a script like this psuedo-code:

$allSecGroups = get-nsxsecuritygroup
$allVMs = get-vm
foreach ($line in $vmInputCSV){
$vm = $allVMs | ? {$_.name -eq $line.name}
$secGroup = $allSecGroups | ? {$_.name -eq $line.secGroup}
Add-NsxSecurityGroupMember -SecurityGroup $secGroup -member $vm

That code will add the first VM to each Security Group (at least, as of the PowerNSX version that was available a couple of months ago, when I was running it) and then error out on every VM thereafter.  A general "rough edge" that I've noticed with PowerNSX cmdlets is that cached instances of objects become invalid once they've been edited. 

So, that bit of script will successfully modify each Security Group once, but after it's been modified, it will fail on subsequent actions because the stored object is no longer valid.  If you do a $secGroup = get-nsxSecurityGroup $line.secGroup instead of trying to pull the stored one from the initial list, it'll work fine... but wow it will be slow (it can take quite a long time to pull those objects and now, it'll have to do that for each iteration of the loop).  Fortunately, there's a better structure that we can use:

$allSecGroups = get-nsxsecuritygroup
foreach ($uniqueSecGroup in ($vmInputCSV.secGroup | sort | select -unique)){
$vms = get-vm ($vmInputCSV | ? {$_.secGroup -eq $uniqueSecGroup}).name
$secGroup = $allSecGroups | ? {$_.name -eq $uniqueSecGroup}
Add-NsxSecurityGroupMember -SecurityGroup $secGroup -member $vms

In that case, we only modify each Security Group once.  We're taking advantage of the fact that Add-NsxSecurityGroupMember can accept an array of VM objects under its -Member parameter in order to pass it all of the appropriate VMs in a single change.  That way, we don't need to pull updated SecurityGroup objects over and over throughout the script, allowing it to run much faster.

The new-NsxFirewallRule cmdlet has a similar situation with its -Section parameter.  When a firewall rule is created, it is typically assigned to a specific section for organizational purposes.  That section must be gathered, then passed as an object to the new-NsxFirewallRule cmdlet.  Once one rule has been created however, the instance of the section is no longer valid and so the section must be collected again for the next rule.  Unfortunately, there's no batch way to create firewall rules though, so for this one, you'll have to go through that repetitive get-NsxFirewallSection process on each iteration.


Popular posts from this blog

Deleting Orphaned (AKA Zombie) VMDK Files

Clone a Standard vSwitch from one ESXi Host to Another

vCenter Server Appliance Crash due to Full /Storage/SEAT Partition