Showing posts with label MaintenanceMode. Show all posts
Showing posts with label MaintenanceMode. Show all posts

Friday, September 20, 2024

SCOM Maintenance Mode using Hashtable

Hi All,

In this post, we'll explore one of the most frequently used features in SCOM—placing servers into Maintenance Mode. As a SCOM admin, you've likely performed this task countless times, either via the SCOM Console or by using PowerShell scripts.

While the SCOM Console offers a simple way to put a server into Maintenance Mode, it has a limitation when dealing with multiple servers, as there's no built-in feature for bulk maintenance mode operations.

To address this, many turn to PowerShell scripts. However, if you've tried this approach, you may have noticed it works well for smaller numbers, like 10 or 20 servers. But what happens when you need to place 500 servers into Maintenance Mode?

Running the command Get-ScomClass | ?{$_.Name -eq 'Microsoft.Windows.Computer'} | Get-ScomClassInstance | ?{$_.DisplayName -eq 'ServerName'} for each of the 500 servers can be extremely time-consuming and may not even succeed as expected.

Fortunately, this challenge can be solved by using Hashtables in PowerShell. In the script below, we create a Hashtable of all WindowsComputer class instances and then efficiently match our list of servers against it, placing each one into Maintenance Mode.

This might not be the only solution to place bulk servers into Maintenance Mode, however it is one of the few solutions which I have been using and found to be pretty reliable with very less hassle.

Please check the Script Below.



#======== Script for Bulk Maintenance Mode ==============#
# Script Created By: Apoorv Katiyar
# Description: This script places multiple servers into maintenance mode in SCOM.
# The list of servers is read from a text file, and the user can specify the duration of maintenance mode.
#============== Starting Script =========================#

# Read the list of servers from the text file
[array]$File = Get-Content -Path "C:\path\ServerList.txt"
$StartTime = Get-Date
Write-Host "Initializing Script"
Write-Host "Please Ensure that FQDN (Fully Qualified Domain Name) are used to place servers into Maintenance Mode"
# Prompt user to proceed
$Input = Read-Host "Press.......1 to Continue"
# Check if the user input is 1
if ($Input -eq "1") {
    
    # Check if the file is not empty
    if (!($File)) {
        Write-Host "File is Empty"
        EXIT
    } else {
        # Get the number of servers in the list
        $Count = $File.count
        Write-Host "Found $Count Servers to be placed into Maintenance Mode"
        # Ask the user for the maintenance mode duration and comments
        $ETime = Read-Host "Please enter the time in minutes for which the servers need to be placed into Maintenance Mode."
        $Comment = Read-Host "Please enter Comments for Maintenance Mode"
        $Message = $Comment
        # Calculate the end time for maintenance mode
        $SCOMMMEND = (Get-Date).AddMinutes($ETime)
        # Retrieve all Windows Computer objects in SCOM
        [array]$WindowsObj = Get-SCOMClass -Name "Microsoft.Windows.Computer" | Get-SCOMClassInstance
        
        # Check if the Windows Computer objects were retrieved successfully
        if (!($WindowsObj)) {
            Write-Host "Status:"
            Write-Host "Unable to fetch all Windows Computer Objects"
        } else {
            $WindowsObjCount = $WindowsObj.count
            Write-Host `n"Found ($WindowsObjCount) Windows Computer objects in the Management Group"
            
            # Create a hash table to store the SCOM instances
            $HashTable = @{}
            foreach ($Object in $WindowsObj) {
                $HashTable.Add("$($Object.DisplayName)", $Object)
            }
            Write-Output "Starting Maintenance Mode Script"
            # Loop through each server in the file
            foreach ($Server in $File) {
                $Instance = $HashTable.($Server)
                
                # Check if the server exists in SCOM
                if (!($Instance)) {
                    Write-Host `n"Warning: $Server was not found as a Windows Computer object in SCOM. Skipping..."`n
                    $DeletedServer += $Server
                } else {
                    $SName = $Instance.DisplayName.ToString()
                    
                    # Check if the server is already in maintenance mode
                    if ($Instance.InMaintenanceMode) {
                        Write-Host "Status: "
                        Write-Host "$SName is already in Maintenance Mode"
                    } else {
                        try {
                            # Start maintenance mode for the server
                            Start-SCOMMaintenanceMode -Instance $SName -EndTime $SCOMMMEND -Comment $Message
                            Write-Host "Status: "
                            Write-Host "Enabled Maintenance Mode for $Instance till $SCOMMMEND (Pacific Time)"
                        } catch {
                            # Handle any errors
                            $ErrorMessage = $_.Exception.Message
                            Write-Host $ErrorMessage
                            Write-Host "Status: "
                            Write-Host "$ErrorMessage"
                        }
                    }
                }
            }
        }
    }
}

#======== End Of Script ==============#