Group Maintenance Mode PowerShell Script Updated

Update – 07, Dec, 2012: the script in this post has been updated to address 2 bugs explained here: Bug Fixes for the Group Maintenance Mode Script

Steve Rachui has posted a wonderful PowerShell script to place a group into maintenance mode in SCOM: Place a Group in Maintenance Mode with PowerShell back in 2010.

I’ve updated the script today to use SDK rather than SCOM 2007 PS Snap-in so the script works on both SCOM 2007 and OM12.

I’ve also made few other changes including change the duration from number of hours to number of minutes to suit my needs.

Here’s the script:

#===========================================================================================
# AUTHOR: Tao Yang
# Script Name: GroupMaintenanceMode.ps1
# DATE: 20/11/2012
# Version: 1.1
# COMMENT: - Script to place a group into maintenance mode (at once) using SDK
# - Update History:
# 1.1 - Bug fix when the group is already in maint. mode condition
# - Added Recursive switch when creating maint. mode to ensure
# group members are also placed into maint. mode.
#===========================================================================================
Param (
[Parameter(Mandatory=$true)]
[string]$RMS,
[Parameter(Mandatory=$true)]
[string]$GroupName,
[Parameter(Mandatory=$true)]
[int]$DurationInMinutes,
[Parameter(Mandatory=$true)]
[string]$Comments)

#Region FunctionLibs
function Load-SDK()
{
 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.EnterpriseManagement.OperationsManager.Common") | Out-Null
 [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.EnterpriseManagement.OperationsManager") | Out-Null
}
#EndRegion

#Firstly validate input
#duration has to be between 5 minutes and 2 years
IF ($DurationInMinutes -lt 5 -or $DurationInMinutes -gt 1051200)
{
 Write-Host "Invalid Duration entered. the duration has to be between 5 minutes and 2 years!"
 $host.setShouldExit(1)
}

#Connection to management group
Load-SDK
$MGConnSetting = New-Object Microsoft.EnterpriseManagement.ManagementGroupConnectionSettings($RMS)
$MG = New-Object Microsoft.EnterpriseManagement.ManagementGroup($MGConnSetting)
$query = "DisplayName= '$GroupName'"
$MonitoringClassCriteria = New-Object Microsoft.EnterpriseManagement.Configuration.MonitoringClassCriteria($query)
$GroupMonitoringClasses = $MG.GetMonitoringClasses($MonitoringClassCriteria)

If ($GroupMOnitoringClasses)
{
 Foreach ($Group in $GroupMonitoringClasses)
 {
 $StartTime = ([DateTime]::Now).ToUniversalTime()
 $EndTime = $StartTime.AddMinutes($DurationInMinutes)
 $MonitoringGUID = $Group.Id
 $MonitoringObject = $MG.GetMonitoringObject($MonitoringGUID)
 Write-Host "Monitoring Object GUID: $MonitoringGUID"
 Write-Host "Monitoring Object DisplayName: $($MonitoringObject.DisplayName)"
 If (!$MonitoringObject.InMaintenanceMode)
 {
 $Reason = "PlannedOther"
 Write-Host "Placing $($MonitoringObject.Displayname) into Maintenance Mode..." -ForegroundColor Green
 $MonitoringObject.ScheduleMaintenanceMode($StartTime, $EndTime, $Reason, $Comments, "Recursive")

 } else {
 $CurrentMaintWindow = $MonitoringObject.GetMaintenanceWindow()
 $CurrentEndTime = $CurrentMaintWindow.ScheduledEndTime
 $CurrentReason = $CurrentMaintWindow.Reason
 $CurrentComments = $CurrentMaintWindow.Comments
 If ($CurrentEndTime -lt $EndTime)
 {
 Write-Host &quot;Updating existing maintenance mode for $($MonitoringObject.DisplayName)<code>...&quot; -ForegroundColor Yellow
 $MonitoringObject.UpdateMaintenanceMode($EndTime, $CurrentReason, $CurrentComments)
 } else {
 Write-Host &quot;The end time of the existing Maintenance mode on $($MonitoringObject.DisplayName) is later than specified end time. The existing maintenance mode will not be updated</code>!&quot; -ForegroundColor Yellow
 }

 }
 }
} else {
 Write-Host &quot;Unable to find the monitoring object with the name <code>&quot;$GroupName</code>&quot;!&quot; -ForegroundColor Red
}

Or download the script HERE.

14 comments

  1. How to stop maintenance before the end time? Do you have a switch to turn maintenance mode off? (or simply use minimum time 5 to stop it?)

    Scenario: I planed a 5 hours’ downtime, and at last, it takes 3 hours.

    1. Samuel,
      This script does not end maint mode. you can’t use minimum 5 minutes to stop because the script compares the new maint. mode length with existing maint. mode end time, it would not update the existing maint. mode if the new time is shorter than the existing one.

      if you are to end the maint. mode manually, wouldn’t it be easier to do it via the console?

      1. Hi Tao,
        I didn’t batch un-maint. the agents in SCOM console. IMHO, a command line is easier, since not everyone in the one environment is familiar with SCOM.
        If you can add a swtich ($startMM($false) to turn On/OFF maint. mode, that would be better. Say, when the switch is $False, you simply update the end time, without comparing it with current end time.

        Here is the script I normally use:
        powershell “c:\GroupMM.ps1” -groupName:’All Computers’ -hours:10 -rmsServerName:’localhost’ -startMM:$false

        Still, your script is great, which runs much faster than the “GroupMM.ps1”.

  2. Would it be possible to modify this even more, so that it just iterates through each group member and puts that server in Maintenance Mode? Reason being, is if I have a server in a group in Maintenance Mode already, this script is going to overwrite the settings no matter what, since it’s only looking at the group, and not the group members.

  3. Where does this script have to run, on the management server? What if I wanted to run it remotely on a system that had no SCOM bits installed?

    1. For this script, you can run it on any machines that’s got the SCOM console installed. Alternatively, you can copy the SDK DLLs to a machine that doesn’t have any SCOM components installed, and modify the Load-SDK function to load the assemblies from the DLLs (instead of the GAC).

      1. Sorry just getting into SCOM SDK. I would need to modify the Load-SDK to use ‘[System.Reflection.Assembly]::LoadFile(“[fully qualified path]\Microsoft.EnterpriseManagement.OperationsManager.Common.dll”)’ instead of LoadwithPartialName?

          1. Just an FYI, I got this working on machines with no SCOM Bits other than the two SCOM 2007 DLL Bits. There is an additional requirement of .Net Framework and the need to load two additional assemblies.

            [System.Reflection.Assembly]::LoadwithPartialName(“System.ServiceModel”)
            [System.Reflection.Assembly]::LoadwithPartialName(“SMDiagnostics”)
            [System.Reflection.Assembly]::LoadFrom(“c:\lib\Microsoft.EnterpriseManagement.OperationsManager.Common.dll”)
            [System.Reflection.Assembly]::LoadFrom(“c:\lib\Microsoft.EnterpriseManagement.OperationsManager.dll”)

  4. Hi Tao,
    Would it be possible to enhance the script with a additional check? We use your script in combination with Orchestrator to put remote sites in Maintenance Mode in case the router on a particular site is not responding. This could mean a line issue or some other issue at the site itself. Therefore we put the objects, based on a group, in Maintenance Mode to prevent alerts.

    Anyhow, when one puts servers in Maintenance Mode by hand (for whatever reason), and the script checks the accommodating site, it will take the objects out of Maintenance Mode ‘because the router is available’. So i would like to improve the script so it can recognize if objects have been put in Maintenance Mode by the script itself or by something or someone else. If the latter applies, do no touch the objects. Otherwise proceed with setting / updating Maintenance Mode.

    I hope you understand my case!

    Thanks

    Tommy

  5. Do we have an updated script to this PS script – looking to put cluster resources / health watchers on MM when we place a computer object on Maintenance Mode. That would help stop the unnecessary alerts /incidents creations??

Leave a Reply

%d bloggers like this: