Hello Readers/Viewers!

The final (and 4th) post of my 2-part mini-series (after Douglas Adams) has finally arrived!

Let’s Level Set

So, let’s take a moment to see where we are in this mini-series. As introduced in Part 1.5, here is the collection of Intro to SMA posts so far: http://aka.ms/IntroToSMA

In this collection, you will find Part 1, Part 1.5, and a Utility Runbook Spotlight for VMM Custom Property Management (as well as a couple others not directly related to this mini-series). And while Part 1 and some of Part 1.5 are not pre-requisites for Part 2, I do strongly recommend them. The functionality explained in the VMM Custom Property Management post will be used extensively here in Part 2.

SMA_thumb[4]


Got it, get to the content!

Sure.

This is Part 2 (of 2) in my mini-series for the SMA Runbook Spotlight on Virtual Machine Startup by Priority. While Part 1 was what I would consider a simple example, Part 2 dives into a couple more complex topics/features. We are still leveraging PowerShell v3 Workflow. We are still calling the workflows from SMA Runbooks. We are still even starting Hyper-V VMs through VMM.

The differences?

  • We are no longer relying on the Delay start up (seconds) field
  • We are no longer leveraging Start-Sleep with that Delay
  • We are no longer guessing when to start the next VM

What are we doing?

  • Storing the actual Startup Group in a VM scope level VMM Custom Property
  • Calculating the number of unique Startup Priority Groups from the Startup Group data stored/retrieved from the VM scope level VMM Custom Property
    Note     Previously we were actually storing the number of Startup Priority Groups in a Cloud scope level VMM Custom Property
  • Retrieving these values to build a PowerShell hash table containing Priority + Array of VM Names (with corresponding priority)
  • Leveraging the hash table data to Start VMs by Priority and verify VM Startup by checking for Hyper-V Integration Services

On With the Example(s)!

As “the process” for creating, testing, importing, running, etc., SMA Runbooks has been covered extensively in the previous posts, I will just jump right in…

Pre-Requisites

First order of business is to ensure your VMM environment is ready for these Workflows/Runbooks. As mentioned above, the VMM Custom Property Management Workflows/Runbooks are pre-requisites for this post’s example. This is due to the fact that this post’s example relies on VMM Custom Property Data. The VMM Custom Property Management Workflows/Runbooks help you to create Custom Properties and populate them with values. Those values will dictate the VM Startup Priority.

So, be sure to perform the following tasks (leveraging the VMM Custom Property Management Workflows/Runbooks is recommended, but not required):

  • Create a Custom Property at the VM scope level with the Name “Startup Group”
  • Create or find a Cloud with VMs you wish to start by priority group
  • Update the “Startup Group” Custom Property for each of the VMs in this Cloud
  • Test that you can retrieve the “Startup Group” Custom Property Values via PowerShell

Note     Recent developments have made me realize that the Custom Property at the Cloud scope level is no longer necessary. Please see the next section for more details.


Recent Developments

Second order of business, is to admit that while the Get-VMMCustomPropertyValue.ps1 example that I provided in the pre-requisite post is good, it is not ideal for this solution (as it would take more distinct remote calls into VMM to leverage it as is, than I would like). So, what do I do when something needs to be improved?

Improve it!

Get-VMMCustomPropertyValuesforCloudVMs

Here we are, a new and improved version of that same PowerShell v3 Workflow / SMA Runbook. It has been optimized for this scenario. It takes in a smaller set of parameters and produces a more complex (yet more useful) output. Let’s take a look:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
workflow Get-VMMCustomPropertyValuesforCloudVMs
{
    param
    (
    [PSCredential]$Creds,
    [string]$VMMServer,
    [string]$CloudName,
    [string]$CustomPropertyName
    )

    InlineScript
    {
        $VMData = @{}

        Import-Module virtualmachinemanager
        Get-VMMServer -ComputerName $Using:VMMServer | Out-Null

        $Cloud = Get-SCCloud -Name $Using:CloudName
        $VMsInCloud = Get-SCVirtualMachine -Cloud $Cloud

        foreach ($VM in $VMsInCloud)
        {
            $CustomProperty = Get-SCCustomProperty -Name $Using:CustomPropertyName
            $VMData.Add($VM,(Get-SCCustomPropertyValue -InputObject $VM -CustomProperty $CustomProperty).Value)
        }

        Return $VMData

    } -PSComputerName $VMMServer -PSCredential $Creds

}

Note     Because it performs a different function (different inputs and outputs), it does not replace its predecessor. In fact, both work rather nicely for their specific intentions. Let me put it this way, if you find a use for one, you will likely find a use for the other.

A quick rundown of what this new and improved version actually does:

  • Takes in fewer parameters, narrowing it down and simplifying
  • Output is more complex, yet has lots more data

Essentially, I needed a script that would take in a Cloud Name, query VMM for its associated VMs, and output a hash table of data based on VM name and related Custom Property. This is exactly what this script does. The hash table output can then be used to calculate (or measure) the unique count of priority startup groups to satisfy $StartupPriorityGroups. This makes the requirement of the Cloud level Custom Property obsolete (as mentioned in the previous section), but you can still leverage it if you would like.

Calling the Get-VMMCustomPropertyValuesforCloudVMs Workflow/Runbook

And while the execution of this PowerShell Workflow / SMA Runbook is handled in the below example, I figured I would place it here as well, in case you just want to leverage this bit of script:

001
002
003
$VMs = Get-VMMCustomPropertyValuesforCloudVMs -Creds $Creds -VMMServer $VMMServer -CloudName $CloudName -CustomPropertyName "Startup Group"
 
$StartupPriorityGroups = ($VMs.Values | sort -Unique | measure).Count

Note     I have included its initial usage to get an idea of how it can be leveraged during execution.


Start-VMs-by-Priority-Group

The following PowerShell v3 Workflow example has been implemented and tested in PowerShell ISE. It can be copy/pasted from here, or imported from the available PS1 file included in the TechNet Gallery Contribution (the link can be found below).

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
workflow Start-VMs-by-Priority-Group
{
    param
    (
    [string]$VMMServer,
    [string]$CloudName,
    [PSCredential]$Creds
    )

    $VMs = Get-VMMCustomPropertyValuesforCloudVMs -Creds $Creds -VMMServer $VMMServer -CloudName $CloudName -CustomPropertyName "Startup Group"
 
    $StartupPriorityGroups = ($VMs.Values | sort -Unique | measure).Count

    $StartupGroupListOrdered = InlineScript
    {
 
        if ($Using:StartupPriorityGroups -gt 0) {
            $StartupGroupList = @{}
   
            for( $i = 1; $i -le $StartupPriorityGroups; $i++ ) {
   
                $VMList = @()
                $VMs = $Using:VMs

                foreach ($VM in ($VMs.GetEnumerator() | Where-Object {$_.Value -eq $i})) {
               
                    $VMList += $VM.Name
                }
   
                $StartupGroupList.Add($i,$VMList)
            }
           
            Return $StartupGroupList.GetEnumerator() | Sort-Object Name

        } else {Return $null}
    }

    if ($StartupGroupListOrdered) {
   
        foreach ($PriorityGroup in $StartupGroupListOrdered) {
   
            foreach -parallel ($PriorityGroupVM in $PriorityGroup.Value) {
   
                InlineScript
                {
                    Import-Module virtualmachinemanager
                    Get-VMMServer -ComputerName $Using:VMMServer | Out-Null

                    $Cloud = Get-SCCloud -Name $Using:CloudName
                    $VM = Get-SCVirtualMachine -Name $Using:PriorityGroupVM -Cloud $Cloud
                   
                    Start-SCVirtualMachine -VM $VM | Out-Null
                   
                    do {Start-Sleep -Seconds 15} 
                        until ((Read-SCGuestInfo -VM $VM -Key FullyQualifiedDomainName -ErrorAction SilentlyContinue).KvpMap.Values)
                }
            }
        }
    }
}

Note     Some portions of this PowerShell do not function with the currently available Release Preview version of System Center 2012 R2 - SMA. The PowerShell itself was developed on currently released Windows Server 2012, so executing it against current technology works just fine, just not from within Release Preview SMA. I have tested it against later builds of SMA, and it works just fine. So, unfortunately, if you want to test this in SMA, you will have to wait until the final release build. See the “SMA Version Differences Example” section below for more information.

Calling the Start-VMs-by-Priority-Group Workflow/Runbook

The following PowerShell v3 Workflow contains the necessary script to call the above Runbook/Workflow example.

001
002
003
004
005
006
007
008
009
010
011
$VMMServer = "VMM01"
$CloudName = "Primary Cloud"
$Creds = Get-Credential

<# Alternate method for getting credential when leveraging SMA:
 
$Creds = Get-AutomationPSCredential -Name 'Contoso Creds'
 
#>


Start-VMs-by-Priority-Group -VMMServer $VMMServer -CloudName $CloudName -Creds $Creds

Note     I have included two methods (the SMA Credential Variable method is commented out) for defining the $Creds variable which is a parameter for the Start-VMs-by-Priority-Group Workflow. Other methods are certainly possible and acceptable, feel free to leverage whichever works best for you. Also, this example PS is not part of the TechNet Gallery Contribution, as it is simply just an in-line PowerShell Workflow call.


SMA Version Differences Example

Here is an example of what works in both PowerShell v3 Workflow and current builds of SMA, but not the Release Preview version of SMA:

001
002
003
004
005
006
007
008
workflow Test-HashTable
{
    $VMData = @{"spftest01" = 1; "spftest02" = 1; "spftest03" = 2; "spftest04" = 3}
    $StartupPriortiyGroups = ($VMData.Values | sort -Unique | measure).Count
    $StartupPriortiyGroups
}

Test-HashTable

Results:

image

Note     This is critical functionality for my Workflow/Runbook. I didn’t want to have to script around it since it works in native PowerShell v3 Workflow as well as the current builds of SMA.


Before I get to this post’s examples, I wanted to remind you…

The VMM Custom Property Management Runbooks / PowerShell v3 Workflows are pre-requisites to this post and example. They can be found here: SMA Example – VMM Custom Property Management (w/PowerShell v3 Workflow)

The recommended steps to complete (PS1 files to leverage) from that set are as follows:

  • Create-VMMCustomProperty.ps1
  • Update-VMMCustomPropertyValue.ps1
  • Get-VMMCustomPropertyValue.ps1  (which can be replaced by Get-VMMCustomPropertyValuesforCloudVMs.ps1 like in this post’s example)

Download the SMA Runbook / PowerShell v3 Workflow Example(s)

As promised, the above example(s) have been included in a TechNet Gallery Contribution…

The download includes the following (2) PS1 files which represent the (2) examples above:

  • Start-VMs-by-Priority-Group.ps1
  • Get-VMMCustomPropertyValuesforCloudVMs.ps1

Download the SMA Example – Start VMs by Priority Groups (w/PS v3 Workflow) from TechNet Gallery here:

BC-DLButtonDark


That’s it! I hope this Start VMs by Priority Groups post provided you with another useful example for leveraging SMA in your daily Datacenter tasks!

Oh, and if you want more examples for SMA and PowerShell v3 Workflow, be sure to check out this list (to be updated as more examples are provided):

And for more information, tips/tricks, and example solutions for SMA, be sure to watch for future blog posts in the Automation Track!

enJOY!