server cluster patching with opalis – part 2

In my last post on this subject I set up the cluster patching framework in Opalis.  In this post I’m going to modify the policy initiation phase to use PowerShell & some text manipulation to make it more dynamic.

I’d set this up originally to simply read the cluster nodes from a text file.  There are more options available to us though – we could use PowerShell to query the cluster for a list of cluster nodes, or in this case I’m going to use PowerShell to query Virtual Machine Manager to get the list of Hyper-V cluster nodes.

I’ve got a simple PowerShell script which is as follows:

Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager
$cluster=get-vmhostcluster -name "democluster.contoso.com" -vmmserver "vmm.contoso.com"
$vmhosts=get-vmhost -vmhostcluster $cluster | select -property Name

Running this script will return me a variable $vmhosts which contains text as follows:

@{Name=clusternode1.contoso.com}

@{Name=clusternode2.contoso.com}

That’s not quite in the format that I want and I could do some further processing in PowerShell to get it right, but I’m lazy, and also want to show off some of the text manipulation features in Opalis.

First thing though, I want to execute this in Opalis.  Because I’m using Virtual Machine Manager objects I’ll need to have the VMM 2008 R2 console installed on my Opalis machine.

Once I’ve got it installed I can then modify my policy.  I’m going to add a “Run .NET script” object.  “Run .NET Script” is pretty powerful and lets us run scripts in C#, JScript, VB.NET or PowerShell.  I just drag and drop my object into my policy, and then double click it to open the properties.

My policy looks like this:

overall policy

When I open the properties, I can simply paste my script in there, and change the language to PowerShell:

net script

Now I need some way to get the output from the script.  The great thing about Opalis is that it makes this really easy.  I go to the “Published Data” area and tell the policy which variable I want to return as published data.  In this case my vmhosts variable is the data I want, so I simply add that in.  Now when I need to retrieve the published data from the data bus, vmhosts will appear as available.

published data

As I said before the data that comes out of that script isn’t exactly in the format I want – I only want hostnames, not all the other text so I need some way of stripping that out.  Fortunately this is another area that Opalis makes really easy.

In my “Trigger Policy” task I previously set it up to pass the Computer Name parameter through to the next policy.  I’m going to continue to do this, but manipulate the text that I pass through.

There is a screen shot below that shows the start of this, but I will expand further.  Opalis will treat information in square brackets as data manipulation functions, so I start with that.  In this case there is a consistent set of data coming out of the script – there is effectively a header (“@{Name=”) , the data (“clusternodex.contoso.com”) and a footer (“}”.  I’m going to use a combination of three functions – the Mid function, the Sum function and the Len function.  Mid allows me to retrieve text from the middle of a string, and Len will allow me to get the length of a string.  Sum just allows me to add two numbers together.

Because my data is in a consistent format the information I want always starts at the 8th character, and the data I need to retrieve is from that point through to the second last character.  The length of text I need to grab is the overall length of the string less 8 characters (the 7 in the header plus the 1 in the footer).  For this I use the Sum function to add –8 to the length of the string.  I could equally use the Diff function to subtract 8.

I then build my function as:

[Mid('<vmhosts published data>’,8, Sum(Len(‘<vmhosts published data>’),-8))]

I insert my published data by right clicking where I want to insert it and choosing “Subscribe…published data”.  I choose the “Run .NET Script” task, and the vmhosts data.

Trigger Policy

So now when my trigger policy task runs it will pass the ComputerName parameter as clusternodex.contoso.com, having stripped off the header and footer.

If you wanted to simply use the Windows 2008 R2 Failover Cluster PowerShell cmdlet’s to get the cluster nodes you could do this:

Import-Module -Name FailoverClusters
Get-ClusterNode -cluster democluster | Format-Table -Property Name –HideTableHeaders

This actually gives nicer output than the VMM Cmdlets but the VMM ones were slightly easier to work with in my case (I can execute them locally on the Opalis server).

Next time we’ll look at some of the pre-patching checks.

Edit: Should have made clear, the Opalis service account needs to have permission in VMM to execute this script.  As there is no concept of an "Operator" in VMM the Opalis account will need to be a delegated administrator.  To run the standalone Failover Cluster scripts the Opalis account simply needs to have Read-only permissions on the cluster.