Using System Center 2012 for Host Cluster Remediation (Patching) and Host Cluster VM Rebalancing for Private Cloud – Part 1 of Many (Host Remediation)

So I’ve been working on Microsoft Private Cloud implementations for various customers. One of the common themes I run into deals with patching the fabric of the Private Cloud, meaning the actual virtual machine hosts. Using System Center 2012 Virtual Machine Manager you can easily orchestrate host remediation with built in functionality. This means that Virtual Machine Manager 2012 has an automated process to move virtual machines from each VM Host node being patched, installing the updates, and rebooting the VM Host machine. One scenario that I’m finding customers are looking for is keeping thier virtual machines on the actual VM Host it was prior to the host cluster remediation. Even thought Virtual Machine Manager will automate this sequence, often virtual machines are left on a single VM Host node in the cluster or on a different VM Host from when the host remediation started. In this first post of the series I will detail a solution that will automate host cluster remediation and prepare the virtual machines to be rebalanced to their VM Hosts they were running on prior to the System Center Virtual Machine Manager 2012 remediation job. The solution also takes in account using the local time zone of the VM host machines. This is used for environments using System Center Virtual Machine Manager 2012 that manage clusters in different time zones, but need host remediation to happen at a specific time local to the host cluster. You will see in later posts how I use System Center Orchestrator 2012 to determine the time zones of each host cluster and only remediate host clusters belonging to a particular time zone at a specified time. A few other things the script takes in account is ensuring the host clusters are assigned to an update baseline, has a compliance scan status, and that all of the guest virtual machine hosted in the cluster do not have DVD drives mounted with a local path. All of those situations mentioned can prohibit host remediation from being successful. I will provide guidance on all the Windows PowerShell scripts and System Center Orchestrator runbooks I developed to automate this process. The full automated end-to-end solution utilizes System Center products Virtual Machine Manager 2012, Operations Manager 2012, and Orchestrator 2012. Let’s begin managing your Microsoft Private Cloud.

 

Prerequisites

The following script assumes that you have already configured your System Center Virtual Machine Manager 2012 server with an Update Server. If you have not done this, please follow the guidance on managing fabric updates for System Center Virtual Machine Manager 2012 https://technet.microsoft.com/en-us/library/gg675084.aspx.

 

The Remediation Script Breakdown

Below is the remediation script that you can run against your Hyper-V host clusters in your System Center Virtual Machine Manager 2012 environment. One thing to note is that this script is intended to run as a runbook in System Center Orchestrator 2012 using the SCVMM 2012 Integration Pack. When using the run SCVMM script object you do not need to import the VirtualMachineManager module for Virtual Machine Manager 2012 because the object configuration does this for you. If you do want to utilized this script outside of Orchestrator 2012 you will have to add the Import-Module VirtualMachineManager to the script. The script itself is somewhat busy, but it will automate all the key activities needed to make the process 100% completely automated using System Center Orchestrator 2012. I will detail out the major parts in the script so that you can feel comfortable and confident using it in your Microsoft Private Cloud environments. Because the script is well documented, I will only explain the major parts. The script will also be available to download as a zip file.

 

Lines 12 – 97 - The script contains four globally declared functions WriteEvent, VMHostTimeZone, VMHostComplianceStatus, and UpdateRemediationBaseline. The functions are well documented and I will discuss them in more detail when the script uses them. For a quick description of the functions the WriteEvent function is used for tracing the script activity and logging to the event log. The VMHostTimeZone function will translate the VMHost time zone metric to the configured three letter time zone. The VMHostComplianceStatus function will initiate a compliancy status against VM Host Cluster. The UpdateRemediationBaseline function will add the VM Host Cluster to the approved baseline.

Lines 100 – 107 - Setting the error action setting for the PowerShell script. There are also two global variable being declared for the time zone and the baseline. These are static entries now, but when we move the script into System Center Orchestrator they will be variables using published data in the data bus.

Line 112 - Starts the Try,Catch in the scripts and does the search Where clause for the Host Clusters you are looking to target. You will have to edit this for your environment.

Line 125 – Ensures the Host Cluster is assigned to a baseline

Line 137 – Verifying the Nodes in the Host Cluster are in the required time zone.

Line 142 – Checking to see if the VM Host is not compliant. If compliant it is skipped and not added to the Job Group

Line 147 – 152 – This is a ForEach loop that will got through all the VMs on the VM Host and add the VM Host information to the Custom Field 1 property of the VM. This will be used in a later script to return the VM to the host it was running on prior to remediation. After the script runs through remediation, you will notice the Custom1 Property of the VM listed with the VM Host name that the VM is currently running on.

VM Custom Field 1 Property

 

Line 158 – 170 – This is a sequence to determine if the VM has the DVD drive mounted and then unmounts the the DVD drive if mounted on the VMs

Line 177 – Add the VM Host node of the VM Host Cluster to the Job Group if found not compliant.

Line 196 – Initiate the VM Host Cluster Remediation Job in SCVMM

Line 197 – Writing out the SCVMM Job GUID to the event log for System Center Operations Manager to monitor and execute a System Center Orchestrator runbook that will monitor the SCVMM Job until complete and report status. You will see this detailed out in later posts on this series.

Line 213 – Script Complete Smile

 

Feel free to post your comments or questions. You can also email me too.

Phil Gibson | Senior Consultant | Microsoft | System Center & Private Cloud Infrastructure & Development

 

SCVMMClusterRemediation.ps1

  1. <#
  2.   Purpose : Remediate Hyper-V Clusters using SCVMM 2012
  3.             
  4.   Author : pgibson.online@hotmail.com [MSFT]
  5.  
  6. Disclaimer: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  7.              EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  8.              WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  9.  
  10.         #>
  11.  
  12. ####### Functions ###############
  13. Function global:WriteEvent
  14.     {
  15.         <#
  16.             Purpose : Write events into the eventlog of the executing machine.
  17.             Setup : Please edit the $EventSoure variable to the EventLog source you want your script to utilize as default. Ex. $EventSource = "MyLogSource"
  18.             Example 1: WriteEvent -EventSource "TEST" -EventID 101 -EventType "Warning" -EventMessage "This is really a test."
  19.             Example 2: WriteEvent -Source "TEST" -ID 101 -Type "Warning" -Message "This is really a test."
  20.             **NOTE** : This function will default the EventLog source you supplied with a "Information" event to the "Application" log if the parameters are not used/overridden
  21.             Author : pgibson.online@live.com [MSFT]
  22.         #>
  23.         param (
  24.                [parameter(Mandatory=$false,Helpmessage="Please enter the source of the Eventlog entry. Example: -Source ""MyLogSource""")][alias("Source")][string]$EventSource = "SCVMMHostRemediation",
  25.                [parameter(Mandatory=$true,Helpmessage="Please enter the event ID of the Eventlog entry. Example: -ID 101")][alias("ID")][int]$EventID,
  26.                [parameter(Mandatory=$false)][alias("Type")][ValidateSet("Error", "Information", "Warning")][string]$EventType = "Information",
  27.                [parameter(Mandatory=$true,Helpmessage="Please enter the event description of the Eventlog entry. Example: -Message ""This is a test.""")][alias("Message")][string]$EventMessage,
  28.                [parameter(Mandatory=$false)][alias("Log")][ValidateSet("Application", "Security", "System")][string]$EventLog = "Application"
  29.               )
  30.         # Create event source if it does not exist
  31.         If (![System.Diagnostics.EventLog]::SourceExists($EventSource))
  32.             {
  33.                 [System.Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLog)
  34.                 write-eventlog -logname $EventLog -Source $EventSource -eventid $EventID -entrytype $EventType -message $EventMessage
  35.             }
  36.         Else
  37.             {
  38.                 write-eventlog -logname $EventLog -Source $EventSource -eventid $EventID -entrytype $EventType -message $EventMessage
  39.             }
  40.     }
  41.  
  42. Function global:VMHostTimeZone
  43.     {
  44.         <#
  45.             Purpose : Detects Time Zone of VMHost machine. Returns three letter time zone.
  46.             Example 1: VMHostTimeZone -TimeZone
  47.             **NOTE** : You MUST configure this function with additonal timezone if needed. Only EST,CST,MST, and PST are configured. Time Zone is represented in minutes minus GMT
  48.             Author : pgibson.online@hotmail.com [MSFT]
  49.         #>
  50.         param (
  51.                [parameter(Mandatory=$true,Helpmessage="Please enter the VMHost Time Zone Property. Example: -VMHostTimeZone -240")][int]$TimeZone
  52.               )
  53.         Switch ($TimeZone)
  54.             {
  55.                 -240 { return "EST" }
  56.                 -300 { return "CST" }
  57.                 -360 { return "MST" }
  58.                 -420 { return "PST" }
  59.                 default { return $Null }
  60.             }
  61.  
  62.     }
  63.  
  64. Function global:VMHostComplianceStatus
  65.     {
  66.         <#
  67.             Purpose : Detects the Compliance Status of a VMHost machine. Returns OverallComplianceState. Tested known status results are "NonCompliant", "Unknown", and "Compliant".
  68.             Example 1: VMHostComplianceStatus -VMHostName "MyVMHost"
  69.             **NOTE** :
  70.             Author : pgibson.online@hotmail.com [MSFT]
  71.         #>
  72.         param (
  73.                [parameter(Mandatory=$true,Helpmessage="Please enter the VMHost Name as string. Example: VMHostComplianceStatus -VMHostName ""MyVMHost""")][string]$VMHostName
  74.               )
  75.         $VMHost = Get-SCVMHost -ComputerName $VMHostName
  76.         $Compliance = Get-SCComplianceStatus -VMMManagedComputer $VMHost.ManagedComputer
  77.         return $Compliance.OverallComplianceState.ToString()
  78.  
  79.     }
  80.  
  81. Function global:UpdateRemediationBaseline
  82.     {
  83.         <#
  84.             Purpose : Updates a Baseline with a VMHost machine.
  85.             Example 1: UpdateRemediationBaseline -VMHostName "MyVMHost" -Baseline "MyBaseline"
  86.             **NOTE** :
  87.             Author : pgibson.online@live.com [MSFT]
  88.         #>
  89.         param (
  90.                [parameter(Mandatory=$true,Helpmessage="Please enter the Cluster Host Name as string. Example: UpdateRemediationBaseline -VMHostName ""MyVMHost"" -Baseline ""MyBaseline""")][string]$ClusterName,
  91.                [parameter(Mandatory=$true,Helpmessage="Please enter the Remediation Baseline Name as string. Example: UpdateRemediationBaseline -VMHostName ""MyVMHost"" -Baseline ""MyBaseline""")][string]$Baseline
  92.               )
  93.         $Cluster = Get-SCVMHostCluster -Name $ClusterName
  94.         $RemediationBaseline = Get-SCBaseline -Name $Baseline
  95.         Set-SCBaseline -Baseline $RemediationBaseline -AddAssignmentScope $Cluster -EA 0
  96.     }
  97. ####### End Functions ###############
  98.  
  99. ######## Start Main ###########
  100. $ErrorActionPreference = "Stop"
  101. WriteEvent -EventID 100 -EventMessage "Start Host Cluster Remediation Process."
  102.  
  103. # Set the Approved Time Zone property for the Host Cluster to be Remediated
  104. $global:ApprovedTimeZone = "EST"
  105.  
  106. # Set Baseline for Compliance Scan
  107. $global:ApprovedBaseline = "Pilot"
  108.  
  109.  
  110. Try
  111.     {
  112.         $HostClusters = Get-SCVMHostCluster | where { ($_.ClusterName -eq "HVCLSRV01")}
  113.    
  114.         ForEach ($HostCluster in $HostClusters)
  115.             {
  116.                 WriteEvent -EventID 100 -EventMessage "Processing Host Cluster $HostCluster."
  117.                 #Generate Remediation JobGroup SCJob GUID
  118.                 $JobGroupGUID = [System.Guid]::NewGuid()
  119.                 WriteEvent -EventID 100 -EventMessage "The SCVMM Host Cluster Remediation Job GUID for Host Cluster $HostCluster is $JobGroupGUID."
  120.         
  121.                 $Cluster = Get-SCVMHostCluster -Name $HostCluster.ToString()
  122.  
  123.                 WriteEvent -EventID 100 -EventMessage "Setting Baseline Assignment on Host Cluster $HostCluster to ensure Baseline is set for possible Remediation."
  124.                 ### NOTE: THIS WILL CREATE A JOB ERROR IS THE CLUSTER IS ALREADY ASSIGNED TO THE BASELINE. NO HARM DONE IF CLUSTER ALREADY EXISTS, BUT A FAILED JOB STATUS WILL BE PRODUCED ###
  125.                 UpdateRemediationBaseline -ClusterName $HostCluster.ToString() -Baseline $ApprovedBaseline
  126.       
  127.                 #Get all Nodes in Cluster
  128.                 $HostClusterNodes = $HostCluster.Nodes
  129.         
  130.                 ForEach ($Node in $HostClusterNodes)
  131.                     {
  132.                         $VMHost = Get-SCVMHost -ComputerName $Node -VMHostCluster $Cluster
  133.                         WriteEvent -EventID 100 -EventMessage "Processing Node $VMHost of Host Cluster $HostCluster."
  134.                         
  135.                         WriteEvent -EventID 100 -EventMessage "Verifying time zone of Node $VMHost of Host Cluster $HostCluster."
  136.                         #Detect TimeZone of $VMHost
  137.                         If ((VMHostTimeZone -TimeZone $VMHost.TimeZone) -eq $ApprovedTimeZone)
  138.                             {                                        
  139.                                 WriteEvent -EventID 100 -EventMessage "Node $VMHost of Host Cluster $HostCluster is in the correct time zone for remediation."
  140.  
  141.                                 WriteEvent -EventID 100 -EventMessage "Detecting Compliance Status of Node $VMHost of Host Cluster $HostCluster."
  142.                                 If ((VMHostComplianceStatus -VMHostName $VMHost.Name.ToString()) -ne "Compliant")
  143.                                     {
  144.                                         WriteEvent -EventID 100 -EventMessage "Begin VM to VMHost pairing on Node $VMHost of Host Cluster $HostCluster."
  145.                                         ##### - Start VM to VMHost Pairing Sequence - ###### # This will write the VMHost name in the Custom1 field property of the VM.
  146.                                         # This is used in a later process to rebalance the Host Cluster after remediation has taken place.
  147.                                         ForEach ($VM in $VMHost.VMs)
  148.                                             {
  149.                                                 WriteEvent -EventID 100 -EventMessage "Setting Custom Field 1 on VM $VM on Node $VMHost of Host Cluster $HostCluster"
  150.                                                 $CustomProperty1 = Get-SCCustomProperty -Name "Custom1"
  151.                                                 Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $CustomProperty1 -Value $VMHost.Name.ToString()
  152.                                             }
  153.                                         ##### - End VM to VMHost Pairing Sequence - ######
  154.                                         WriteEvent -EventID 100 -EventMessage "Completed VM to VMHost pairing for Node $VMHost of Host Cluster $HostCluster"
  155.                                 
  156.                                         WriteEvent -EventID 100 -EventMessage "Begin VM DVD Drive Unmount Sequence for each VM on Node $VMHost of Host Cluster $HostCluster"
  157.                                         ##### - Start VM DVD Drive Unmount Sequence - ###### # Remediation will fail if VMs have a local path ISO mounted. ex. C:\Windows\System32\vmguest.iso
  158.                                         $VMsWithDVDMounted = Get-VMHost $VMHost | Get-VM | Get-VirtualDVDDrive | where {$_.ISO -ne $null}
  159.             
  160.                                         If ($VMsWithDVDMounted.Count -gt 0)
  161.                                             {            
  162.                                                 ForEach ($VM in $VMsWithDVDMounted)
  163.                                                     {
  164.                                                         #$VM = Get-SCVirtualMachine -Name $strVMName
  165.                                                         WriteEvent -EventID 100 -EventMessage "Unmounting DVD drive on VM $VM.Name"
  166.                                                         $DVDDrive = Get-SCVirtualDVDDrive -VM $VM.Name.ToString() | where { $_.Bus -eq 1 -and $_.LUN -eq 0 }
  167.                                                         Set-SCVirtualDVDDrive -VirtualDVDDrive $DVDDrive -NoMedia -EA 0
  168.                                                         WriteEvent -EventID 100 -EventMessage "Completed Unmounting DVD drive on VM $VM.Name"
  169.                                                     }
  170.                                             }
  171.                                         ##### - End VM DVD Drive Unmount Sequence - ######
  172.                                         WriteEvent -EventID 100 -EventMessage "Completed VM DVD Drive Unmount Sequence for each VM on Node $VMHost of Host Cluster $HostCluster"
  173.                                 
  174.                                 
  175.                                         WriteEvent -EventID 100 -EventMessage "Adding Cluster Node Job Task for Node $VMHost of Host Cluster $HostCluster."
  176.                                         #Add Cluster Node Job Tasks to Job Group
  177.                                         Start-SCUpdateRemediation -JobGroup $JobGroupGUID.ToString() -VMHost $VMHost -VMHostCluster $Cluster
  178.                                         WriteEvent -EventID 100 -EventMessage "Finished Adding Cluster Node Job Task for Node $VMHost of Host Cluster $HostCluster."
  179.                                     }
  180.                                 Else
  181.                                     {
  182.                                         WriteEvent -EventID 100 -EventMessage "Node $VMHost of Host Cluster $HostCluster is currently Compliant. No Remediation will be done at this time."
  183.                                     }
  184.                                         
  185.                                 
  186.                             }
  187.                         Else
  188.                             {
  189.                                 WriteEvent -EventID 100 -EventMessage "Node $VMHost of Host Cluster $HostCluster is NOT in the correct time zone for remediation. No Remediation will be done at this time."
  190.                             }
  191.                         
  192.                                   
  193.                     }
  194.       
  195.                     WriteEvent -EventID 100 -EventMessage "Starting SCJob Remediation for Host Cluster $HostCluster."        
  196.                     Start-SCUpdateRemediation -BypassMaintenanceModeCheck -JobGroup $JobGroupGUID.ToString() -RunAsynchronously -StartNow -UseLiveMigration -VMHostCluster $Cluster
  197.                     WriteEvent -EventID 101 -EventMessage $JobGroupGUID
  198.                     #Clear JobGroupGUID variable
  199.                     WriteEvent -EventID 100 -EventMessage "Clearing Job Group GUID variable for Host Cluster $HostCluster."
  200.                     Clear-Variable -Name JobGroupGUID
  201.                     WriteEvent -EventID 100 -EventMessage "Cleared Job Group GUID variable for Host Cluster $HostCluster."
  202.                     
  203.             }
  204.     }
  205. Catch
  206.     {     
  207.         Throw $_.Exception
  208.         WriteEvent -EventID 200 -Type "Error" -EventMessage "Host Cluster Remediation Process Failed. Error message: $_.Exception.Message"
  209.     }
  210. Finally
  211.     {
  212.        WriteEvent -EventID 100 -EventMessage "Completed Host Cluster Remediation Process."
  213.     }