Place a Group in Maintenance Mode with Powershell


Steve? Why are you writing a post on how to place a group in maintenance mode using powershell?  There are already LOTS of solutions out there to put a group in maintenance mode – why spend time on another?  Good question.  The reason?  Efficiency.

I recently was working on a project where we were placing groups in maintenance mode – some groups with as many as 500 agents in them.  Using the available powershell scripts we noticed a fair amount of latency to show in the UI that all of the agents in the group had entered maintenance mode. 

Looking at available script examples it seemed that all used the approach of identifying the group for maintenance mode and iterating though it to get a list of machines (with a for each statement) and then placing each individual agent contained in the group in maintenance mode from there.  So, for a group with 500 agents you would end up calling the routine to place the agents in maintenance mode (new-maintenancewindow) 500 times!  Not the most efficient approach.

I set out to find a method to allow calling new-maintenancewindow a single time and instead of specifying an agent, I specified a group name.  This works in the OpsMgr UI so figured it had to be workable in Powershell too.  The result of my work is the script below.  Definitely room for additional customization if needed.  I’ve done limited testing but it seems to work like a champ – and seems to be much more efficient than the individual agent approach.  Give it a spin and tell me how you like it!

Sample Commandline:
GroupatonceMM.ps1 GROUPNAME MMDURATIONINHOURS RMSSERVERNAME

Script name:  GroupatonceMM.ps1
param ($groupName, $MMDuration, $rmsServerName)

#Load the Operations Manager snapin and connect to the Root Management Server
add-pssnapin "Microsoft.EnterpriseManagement.OperationsManager.Client";
Set-Location "OperationsManagerMonitoring::";
$mgConn = New-ManagementGroupConnection -connectionString:$rmsServerName;
if($mgConn -eq $null)
{
[String]::Format("Failed to connect to RMS on ‘{0}’",$rmsServerName);
return;
}

Set-Location $rmsServerName;

$startTime = [DateTime]::Now
$endTime = $startTime.AddHours($MMDuration)
$MonitoringClassCG = get-monitoringclass | where {$_.DisplayName -eq $groupName}
$MonitoringGUID = get-monitoringobject $MonitoringClassCG.Id

New-MaintenanceWindow -startTime:$startTime -endTime:$endTime -reason:"ApplicationInstallation" -comment:"none" -monitoringObject:$MonitoringGUID

Comments (6)

  1. JonnyMaintenanceMode says:

    Thanks for the script, works nicely.  Any chance you could post how you use the script to remove the computers from maintenance mode?  That would be greatly appreciated.

  2. steverac says:

    Hi – you could just change the script to call set-maintenancewindow instead of rnew-maintenance window and pass the new end time for maintenance mode.

  3. Julius says:

    I second the request for taking objects out of maint. mode.  thanks!

  4. Gcotogno says:

    Hi all, I modified the script with a partner, and now you can select if you want to put the mainantance in or out. Here is the code:

    param ($groupName,$MMDuration,$rmsServerName,$startMM)

    #Load the Operations Manager snapin and connect to the Root Management Server

    add-pssnapin "Microsoft.EnterpriseManagement.OperationsManager.Client";

    Set-Location "OperationsManagerMonitoring::";

    $mgConn = New-ManagementGroupConnection -connectionString:$rmsServerName;

    if($mgConn -eq $null)

    {

    [String]::Format("Failed to connect to RMS on '{0}'",$rmsServerName);

    return;

    }

    Set-Location $rmsServerName;

    $startTime = [DateTime]::Now

    $endTime = $startTime.AddHours($MMDuration)

    $MonitoringClassCG = get-monitoringclass | where {$_.DisplayName -eq $groupName}

    $MonitoringGUID = get-monitoringobject $MonitoringClassCG.Id

    if($startMM -eq $true)

    {

    New-MaintenanceWindow -startTime:$startTime -endTime:$endTime -reason:"ApplicationInstallation" -comment:"none" -monitoringObject:$MonitoringGUID

    }

    else

    {

    if($MonitoringGUID.InMaintenanceMode -eq $true)

    {

    $MonitoringGUID.StopMaintenanceMode([DateTime]::Now.ToUniversalTime(),[Microsoft.EnterpriseManagement.Common.TraversalDepth]::Recursive);

    }

    }

    The command execution line is like this:

    Example:

    GroupMM.ps1 -groupName:'switch name' -hours:10 -rmsServerName:'rms server' -startMM:$true

    GroupMM.ps1 -groupName:'switch name' -hours:10 -rmsServerName:'rms server' -startMM:$false

    Enjoy!

  5. PJ77 says:

    Hi guys

    we have more than 1 SCOM server in our environment, any idea or changes to script that can target and check all the SCOM servers and put servers in MM?

    Thanks

  6. Warren Willsey says:

    Can't get groupmm.ps1 to work in a batch file or in the scheduler. No errors, just does nothing.