Exchange Server Maintenance Functions

Here’s a couple of PowerShell functions that can be used to put an Exchange 2013/2016 server into “maintenance mode.”

There hasn’t been an official maintenance mode for Exchange Server since Server 2010, which introduced DAG capabilities that greatly improved failover and reduced the need for an official maintenance mode for the servers. With Server 2016, the need for putting a server into maintenance mode has returned due to AutoReseed and AutoDAG features that re-mount databases on their primary server if possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#    .SYNOPSIS
#    This cmdlet will initiate maintenance status of an Exchange Server.
#    .DESCRIPTION
#    Initiates maintenance of an Exchange server for Exchange 2013 and 2016 (2010 has a different process).
#    Script will make the following changes:
#    1. Block database activation and move all databases to a different server.
#    2. Configure Hub transport services to drain email (prevents server from accepting email and completes existing transactions)
#    3. Restart transport services on the server (must pass valid admin creds)
#    4. Verify that all databases have been moved to a new server. If databases are still mounted, it will force a move
#       with the option to skip checks on active database limits.
#    5. Set the server components to "ServerWideOffline." This disables Exchange functionality while keeping services active.
#    .PARAMETER server
#    Pass Exchange Server name of system being taken offline
#    .PARAMETER credential
#    Pass the credentials used to restart transport services.
#    .EXAMPLE
#    start-exchangemaint -server server1 -credential (get-credential)
function start-exchangemaint{
[cmdletbinding()]
param(
[parameter(Mandatory=$true)]
$server,
$credential)
try{
get-exchangeserver $server | Out-Null
$isvalid = $true
}
catch{
$output = $server + " is not a valid Exchange Server"
$isvalid = $false
}
if ($isvalid = $true){
set-mailboxserver $server -DatabaseCopyActivationDisabledAndMoveNow $true
#Sleep script for 30 seconds to allow failover to succeed
start-sleep -s 30
Set-ServerComponentState $server -Component Hubtransport -state draining -Requester Maintenance
"Restarting transport services to apply state change"
Invoke-Command -ComputerName $server -ScriptBlock {get-service | where {$_.displayname -like "*transport*"} | Restart-Service} -Credential $credential
#Sleep the script execution for 1.5 minutes each time a check against the submission queue shows messages in queue
$queue = $server + "\submission"
while ((get-queue -Identity $queue).messagecount -ne 0){start-sleep -m 1}
if((get-mailboxserver $server).DatabaseCopyAutoActivationPolicy -notlike "blocked"){set-mailboxserver $server -DatabaseCopyAutoActivationPolicy blocked}
start-sleep -s 5
#Checks for any databases that were not successfully moved and moves them with a "manual" switchover
$dbs = get-mailboxdatabasecopystatus -server $server|where{$_.status -like "mounted"}
foreach ($dbname in $dbs){
$db = $dbname.name.split("")[0]
$preference = (get-mailboxdatabase $db).activationpreference[1].split("[,")[1]
Move-ActiveMailboxDatabase $db -ActivateOnServer $preference -SkipMaximumActiveDatabasesChecks -Confirm:$false
}
#Sets server state to offline
Set-ServerComponentState $server -Component serverwideoffline -state inactive -Requester maintenance
#Notification of success
$output = $server + "has been placed in maintenance mode"
}
}
# .SYNOPSIS
# Takes a server out of maintenance mode
# .DETAILS
# This cmdlet will end maintenance mode set by start-exchangemaint cmdlet by:
# 1. Disabling ServerWideOffline state
# 2. Reactivating HubTransport (And restarting transport services
# 3. Resetting server to allow database activation
# Databases that have been dismounted on the server should re-mount if AutoReseed/AutoDAG is enabled.
# .PARAMETER server
# Passes the server name to take out of maintenance mode
# .PARAMETER credential
# Passes credentials used to restart transport services
# .EXAMPLE
# end-exchangemaint -server server1 -credential (get-credential)

function end-exchangemaint{
[cmdletbinding()]
param(
[parameter(Mandatory=$true)]
$server,
[parameter(mandatory=$true)]
$credential)
try{
get-mailboxserver $server
$isvalid = $true
}
catch{
$isvalid = $false
$output = $server + " is not a valid exchange server."
}
if($isvalid = $true){
"Disabling ServerWideOffline"
Set-ServerComponentState $server -Component serverwideoffline -state active -Requester maintenance
#Wait 15 seconds for status change to apply
start-sleep -s 15
"Implementing HubTransport Activation"
Set-ServerComponentState $server -Component hubtransport -state active -requester maintenance
#wait 15 seconds for status change to apply
start-sleep -s 15
"Restarting Transport Services to apply state change"
Invoke-Command -ComputerName $server -ScriptBlock {get-service | where {$_.displayname -like "*transport*"} | Restart-Service} -Credential $credential
"Resetting Activation policy"
set-mailboxserver $server -DatabaseCopyAutoActivationPolicy unrestricted -DatabaseCopyActivationDisabledAndMoveNow $false
}
}
start-exchangemaint -server ustxcr00exc27i -credential (get-credential)

Leave a Reply

Your email address will not be published. Required fields are marked *