[updated: July 20, 2015] Script: putting Exchange Server 2013 into Maintenance Mode

Latest Update:

v1.8 (07/20/2015): fixed a copy/paste error in the script and cleaned up the code to be a little more efficient (removed redundant IF-statement. Published the script to the TechNet Script Gallery for easier download access.

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. To help clearing out the queues, existing messages on the server will be moved to another server. Please note that the TargetServer value has to be a FQDN:

Set-ServerComponentState  -Component HubTransport -State Draining -Requester Maintenance
Redirect-Message -Server  -Target <server_fqdn>

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

Suspend-ClusterNode
Set-MailboxServer  -DatabaseCopyActivationDisabledAndMoveNow $true
Set-MailboxServer  -DatabaseCopyAutoActivationPolicy Blocked

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

Set-ServerComponentState  -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  -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
Set-MailboxServer  -DatabaseCopyActivationDisabledAndMoveNow $false
Set-MailboxServer  -DatabaseCopyAutoActivationPolicy Unrestricted

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

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

Although not explicitly required, it’s best to restart the transport services after changing their component states. This ensures they ‘pick up’ the changed component states immediately rather than having to wait for Managed Availability (Health Service) to take action.

Using the scripts

Sometimes it can take a while before active queues are drained. Because I do not always want to wait in front of the screen and periodically check the queues myself, I created two little script that fully automate the process explained above. Besides the required steps, the scripts also perform additional safety-checks and inform you about other server component states which might prevent a server from working correctly.

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.

Version history

v1.8 (07/20/2015): fixed copy/paste bug; removed duplicate code and made some overall improvements to script efficiency.

v1.7 (07/08/2015): removed the requirement to dot-source the script. Published the script to the TechNet Script Gallery for easier download access.

v1.6 (29/11/2013): some minor bug fixes in the Start-ExchangeMaintenanceMode script.

v1.5 (28/11/2013): Based on feedback from several readers, I’ve improved the scripts by rewriting parts of the code and, as such, making it more lenient and more usable in scenarios where you want to run the script from a remote Exchange server. The script now also restarts the Transport service(s) after changing their component states. This ensures that the new component states are picked up immediately, rather than after Managed Availability kicks in. Without the change it could take anywhere from a few minutes to a few hours before the transport services were really inactive/active again. The download links at the bottom of the page are updated to point to the new versions of the scripts. Last, but not least, when ending a maintenance mode, the script will query the server for any components that might still be inactive and display a warning if any are found. A special thanks to Dave Stork for some of the ideas!

v1.4: update the script to include some additional error checks. First it will check whether the person who is executing the script has local admin rights. If not, the script will throw a warning and exit. Secondly it will also check whether the TargetServer name can be resolved. If it’s not an FQDN, it will resolve it to an FQDN. If it cannot be resolved, an error will be thrown.

v1.3: after some feedback from Brian Reid (thanks Brian!), I’ve finally updated the script to include the “Redirect-Message” cmdlet. This will ensure that the queues will drain more quickly on the server by moving messages from one server to another. Have a look at Brian’s blog if you need more info: http://blog.c7solutions.com/2012/10/placing-exchange-2013-into-maintenance.html

v1.2: Maarten Piederiet emailed me pointing out that he had encountered some issues while using the script. Apparently, while draining the message queues, the script ran forever because it waits for every queue to become empty; including Poison- & Shadow Redundancy queues. To avoid this from happening, he made a minor change to the script to now excluded both queues. Thanks for the tip!

The scripts

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

Start-ExchangeServerMaintenanceMode (v1.8)

Stop-ExchangeServerMaintenanceMode (v1.5)

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!

Blog Exchange PowerShell

Exploring Exchange Server Component States

As described in a previous article, an Exchange 2013 server can be placed into a sort of maintenance mode, not only by temporarily pausing a DAG node from the cluster, but also by putting Exchange components on that server into an inactive state using the Set-ServerComponentState cmdlet.

The most obvious reason why a component is in an inactive state is because someone put it into that state as part of a maintenance task. However, there can be several other reasons why a component is inactive. The most common reason is when the Health Management service (part of Managed Availability) has taken a component offline because it was deemed unhealthy.

The tricky part comes when one or more “requesters” have put a component into an Inactive state which might lead to confusing situations. There are 5 requesters that can switch the state of a component:

  • HealthAPI
  • Maintenance
  • Sidelined
  • Functional
  • Deployment

Consider the following scenario. As part of the upgrade to the latest CU, you decide to put a server into maintenance mode using the Set-ServerComponentState cmdlet. After the upgrade, you take the server back “online” by changing the state of the component back to “Active”. However, when running the Get-ServerComponentState cmdlet, you notice that one or more components are still inactive… You investigate the issue and it turned out that the component was already in an inactive state before YOU put it in an inactive state. So why didn’t the state change AFTER you put it into an active state again?

The answer is pretty simple. As you know, only the requester that has put a component into a certain state, can put it back into an active state. So, as part of your maintenance task, you’ve put a component into maintenance using “Maintenance” as the requester, you are actually flagging the service inactive for a second time.

In fact, every time someone (or something) makes a component inactive, an entry gets added to the local server’s registry in the following location:

HKLM\SOFTWARE\Microsoft\Exchange Server\v15\ServerComponentStates\<componentname>

image
this image displays the different entries for the FrontEndTransport component in the local Exchange server’s registry

Each entry includes the following information, separate by a colon: [Unknown Value]:[State]:[TimeStamp]
By looking at the picture, you can see that the requester “Maintenance” has put this component into an active state on the given timestamp. FYI, the timestamp is saved in a binary format.

Now consider the following image:

image

As you can see, the component has multiple entries. Luckily, all of them are showing that the component is Active. However, if one of the entries would show the component was inactive, it would effectively be inactive. Even if a more recent entry would place that component into an active state, it would remain inactive until the same requester switches it back to active.

Why is that, you might wonder. Simply because there are cases where you don’t want someone to override the component state set by someone or something else. This could be the case when someone placed a server into maintenance mode (requester = Maintenance) and while the server is in maintenance, someone updates the Exchange server to the latest version. Exchange setup will actually place all components into an inactive state prior to starting the upgrade (requester  = Deployment) and switch them back after the upgrade completes. If this action would override the component state set by “Maintenance”, the server would effectively become operational again. Something you might not want in this case.

Script to query Component States

The output of the Get-ServerComponentState cmdlet does not show who placed a component into an inactive state, nor shows it if there’s more than one entry for that component. Of course, you could each time have a look in the local server’s registry. For convenience reasons, I put together a little script that will query the local registry and output the information on-screen:

image

Below you’ll find the code for the script. All you need to do is save it as a .ps1 file and run it from the Exchange Server that you want to query. Alternatively, you can download the script from here.

The current version of the script is a bit rough, but it works 🙂
In a future version, I’ll try to add remoting and clean up the code a bit by adding comments…

$components = Get-ChildItem HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\ServerComponentStates\ -Recurse | select PSPath

foreach($component in $components){

$componentstates = (Get-ItemProperty $component.PSPath | Select * -ExcludeProperty PS* ) | Get-Member -MemberType NoteProperty

$i=0

do {

$componentstate = ($componentstates[$i].Definition).split("=")
$statebreakdown = $componentstate[1].Split(":")

#$componentActualState = $statebreakdown[1]

switch($statebreakdown[1]){
1 {$componentActualState = "Active"}
0 {$componentActualState = "Inactive"}
}
$componentActualTime = [timezone]::CurrentTimeZone.ToLocalTime([datetime]::FromBinary($statebreakdown[2]))

$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name Component -Value $($component.PSPath.Split("\"))[7]
$obj | Add-Member -MemberType NoteProperty -Name Requester -Value $componentstates[$i].Name
$obj | Add-Member -MemberType NoteProperty -Name State -Value $componentActualState
$obj | Add-Member -MemberType NoteProperty -Name TimeStamp -Value $componentActualTime
$obj

$i++
}
while ($i -lt $componentstates.count)

}

What’s next?

In a follow-up article, I’ll discuss the Server Component States and why the entries also exist in Active Directory.

Exchange 2013 How-To's