Pro-Exchange,Lync & Office 365
Belgian Microsoft Unified Communications Professionals
Microsoft Exchange Server, Microsoft Lync Server & Office 365
Script: putting Exchange Server 2013 into Maintenance Mode

Introduction

In Exchange 2010 one had the option to put a Mailbox server which was part of a DAG into “maintenance mode” by running the “StartDagServerMaintenance.ps1” script that was included with the product. Likewise StopDagServerMaintenance.ps1 was used to pull a server out of this so-called maintenance state. In fact, this script would move any active mailbox databases to another node in the DAG and mark this server as temporarily unavailable to the other servers. That way, if a failover would occur during the server was in ‘maintenance mode’ you wouldn’t risk that it ended up as a valid failover target.

Exchange 2013 now has the ability to go beyond what was possible before and extend this functionality. You now have the possibility to put an entire server into maintenance mode, meaning that also components like e.g. Transport Service or the Unified Messaging Call Router are temporarily put on hold why you do some work on your server.

There might be various reasons to put a server into maintenance mode. For instance when you need to install software or you want to do some troubleshooting without affecting users that might have a mailbox in an active mailbox database on that server. To facilitate the process, I created two scripts which will automatically put an Exchange 2013 Server in or take it back out of Maintenance Mode.

The manual process

The process for putting an Exchange 2013 server into maintenance mode is relatively straightforward. To enable the Maintenance Mode, you must run the commands below.

If the server is a Mailbox server and before you can disable the transport service, all active queues need to be drained first:

Set-ServerComponentState <server> -Component HubTransport -State Draining -Requester Maintenance

If the server is part of a DAG, you must also run these commands:

Suspend-ClusterNode $Server 
Set-MailboxServer <server> -DatabaseCopyActivationDisabledAndMoveNow $true 
Set-MailboxServer <server> -DatabaseCopyAutoActivationPolicy Blocked

Once all queues are empty, you can disable all components:

Set-ServerComponentState <server> -Component ServerWideOffline -State Inactive -Requester Maintenance

Taking the server out of Maintenance Mode is a matter of simply reversing the actions we took to put it into Maintenance Mode.

First, we reactive all components:

Set-ServerComponentState <server> -Component ServerWideOffline -State Active -Requester Maintenance

If the server is part of a DAG, you need to reactive it in the cluster (by resuming the cluster node):

Resume-ClusterNode <server>
Set-MailboxServer <server> -DatabaseCopyActivationDisabledAndMoveNow $false
Set-MailboxServer <server> -DatabaseCopyAutoActivationPolicy Unrestricted

If the server is a Mailbox Server, the transport queues need to be resumed as well:

Set-ServerComponentState –Identity $Server -Component HubTransport -State Active -Requester Maintenance

Using the scripts

Sometimes it can take a while before active queues are drained. Because I didn’t always want to wait before the screen and periodically check the queues myself, I created two little script that fully automate the process explained above.

The first script, Start-ExchangeServerMaintenanceMode.ps1 will put a server into Maintenance Mode, whereas Stop-ExchangeServerMaintenanceMode.ps1 can be used to take a server out of the maintenance state.

Please note that the scripts rely on built-in Exchange functions and therefore need to be run from the Exchange Management Shell.

To make sure that these scripts can be re-used easily, I created cmdlets for both actions. This means that examples and help are provided within the script. Also, if you dot-source the script in your PowerShell profile you will be able to call both functions/cmdlets at any time (without having to call the script again).

To dot-source a script in your profile, simple add the following code into your PS profile:

. ./<pathtoscript>/Start-ExchangeServerMaintenanceMode.ps1
. ./<pathtoscript>/Stop-ExchangeServerMaintenanceMode.ps1

Once that is done, you can call these cmdlets by simply running the following command from within the Exchange Management Shell:

Start-ExchangeServerMaintenanceMode –Server <Server>
Stop-ExchangeServerMaintenanceMode –Server <Server>

Additional information

I’ve added a loop in the Start-ExchangeServerMaintenanceMode script that will check the transport queues every minute until they’re empty. Only when the queues are empty, it will continue and mark a server as being in maintenance mode. This is done via a separate function in the script:

function evaluatequeues(){
    $MessageCount = Get-Queue -Server $Server | Select MessageCount
    $count = 0
    Foreach($message in $MessageCount){
        $count += $message.messageCount
    }
    if($count -ne 0){
        Write-Host "Sleeping for 60 seconds before checking the transport queues again..." -ForegroundColor Yellow
        Start-Sleep -s 60
        evaluatequeues
    }
    else{
        Write-Host "Transport queues are empty." -ForegroundColor Green
        Write-Host "Putting the entire server into maintenance mode..." -ForegroundColor Green
        Set-ServerComponentState $Server -Component ServerWideOffline -State Inactive -Requester Maintenance
        Write-Host ""
        Write-Host "Done! Server $Server is put succesfully into maintenance mode!"
    }

}

The scripts

Below you find links to my SkyDrive from where you can download the scripts. Enjoy!

Start-ExchangeServerMaintenanceMode

Stop-ExchangeServerMaintenanceMode

Disclaimer: these scripts are provided “as-is” and are to be used on your own responsibility. I do not and cannot take any reliability for the use of these scripts in your environment. Please use with caution and always test them before use.

If you have suggestions, comments or think things can be better: please let me know! Your feedback is greatly appreciated!


Posted 11-10-2012 7:59 by Michael Van Horenbeeck