Skip to content

Instantly share code, notes, and snippets.

@ConanChiles
Created October 3, 2022 10:04
Show Gist options
  • Save ConanChiles/9a69d1bdfeff84fccd617f184266b479 to your computer and use it in GitHub Desktop.
Save ConanChiles/9a69d1bdfeff84fccd617f184266b479 to your computer and use it in GitHub Desktop.
janky begins of a script for Exchange cluster maintenance
# https://docs.microsoft.com/en-us/exchange/managing-database-availability-groups-exchange-2013-help
# !! *** this isn't a "script" you can just run *** !!
# more something to be ran manually in stages, with a human reading checking output before progressing
# assumes each DAG has 2 members, will need to tweak for >2 members
$ErrorActionPreference = 'stop'
Set-StrictMode -Version 'latest'
Add-PSSnapin -Name 'Microsoft.Exchange.Management.PowerShell.SnapIn'
$otherClusterMember = Get-ClusterNode | Where-Object -FilterScript {$PSItem.Name -ne $env:COMPUTERNAME}
Get-ClusterNode | Format-Table -AutoSize
# put server into maintenance mode
"local server, the one to reboot $env:COMPUTERNAME" | Write-Host -ForegroundColor Cyan
"other cluster member, the one staying online $($otherClusterMember.Name)" | Write-Host -ForegroundColor Cyan
if ( 'Up' -ne $otherClusterMember.State ) {
'other node is down' | Write-Host -ForegroundColor Red
} else {
'both nodes are up' | Write-Host -ForegroundColor Green
}
Set-ServerComponentState -Identity $env:COMPUTERNAME -Component HubTransport -State Draining -Requester Maintenance
Restart-Service -Name 'MSExchangeTransport'
Set-ServerComponentState $env:COMPUTERNAME -Component UMCallRouter -State Draining -Requester Maintenance
Redirect-Message -Server $env:COMPUTERNAME -Target "$($otherClusterMember.Name).corp.oktedi.internal" -Confirm:$false
Suspend-ClusterNode $env:COMPUTERNAME
Set-MailboxServer $env:COMPUTERNAME -DatabaseCopyActivationDisabledAndMoveNow $True
Set-MailboxServer $env:COMPUTERNAME -DatabaseCopyAutoActivationPolicy Blocked
Set-ServerComponentState $env:COMPUTERNAME -Component ServerWideOffline -State Inactive -Requester Maintenance
# verify the server has been placed into maintenance mode
Get-ServerComponentState -Identity $env:COMPUTERNAME | Format-Table -AutoSize -Property ('Component', 'State')
# verify the server is not hosting any active database copies
Get-MailboxServer -Identity $env:COMPUTERNAME | Format-Table -AutoSize -Property '*DatabaseCopy*'
# verify that the node is paused
Get-ClusterNode $env:COMPUTERNAME | Format-List
Get-ClusterNode | Format-Table -AutoSize
# verify that all transport queues have been drained
Get-Queue | Format-Table -AutoSize
Get-MailboxDatabase | Sort-Object -Property 'Server' | Format-Table -AutoSize
##############################################
# install updates, reboot, maintenance stuff #
##############################################
# pull server out of maintenance mode
$ErrorActionPreference = 'stop'
Set-StrictMode -Version 'latest'
Add-PSSnapin -Name 'Microsoft.Exchange.Management.PowerShell.SnapIn'
Set-ServerComponentState -Identity $env:COMPUTERNAME -Component ServerWideOffline -State Active -Requester Maintenance
Set-ServerComponentState -Identity $env:COMPUTERNAME -Component UMCallRouter -State Active -Requester Maintenance
Resume-ClusterNode -Name $env:COMPUTERNAME
Set-MailboxServer -Identity $env:COMPUTERNAME -DatabaseCopyActivationDisabledAndMoveNow $False
Set-MailboxServer -Identity $env:COMPUTERNAME -DatabaseCopyAutoActivationPolicy Unrestricted
Set-ServerComponentState -Identity $env:COMPUTERNAME -Component HubTransport -State Active -Requester Maintenance
Restart-Service -Name 'MSExchangeTransport'
# verify the server is not in maintenance mode
Get-ServerComponentState -Identity $env:COMPUTERNAME | Format-Table -AutoSize -Property ('Component', 'State')
Get-Queue | Format-Table -AutoSize
Get-MailboxDatabase | Sort-Object -Property 'Server' | Format-Table -AutoSize
Get-ClusterNode | Format-Table -AutoSize
Get-ClusterNode | ForEach-Object -Process {
if ( $PSItem.State -ne 'Up' ) {
$PSItem | Out-String | Write-Host -ForegroundColor Cyan
Write-Host
throw "$($PSItem.Name) is not 'Up'"
} else {
return ($PSItem)
}
} | ForEach-Object -Process {
Get-MailboxDatabaseCopyStatus -Server $PSItem.Name
} | Format-Table -AutoSize
(Get-ClusterNode).Name | ForEach-Object -Process {
Get-MailboxDatabaseCopyStatus -Server $PSItem
} | Format-Table -AutoSize
Get-DatabaseAvailabilityGroup -Identity ((Get-Cluster).Name) `
| Select-Object -ExpandProperty 'Servers' `
| Test-ReplicationHealth `
| Sort-Object -Property @(
'Error'
'Result'
'Check'
'Server'
)
###
Get-ExchangeCertificate | Sort-Object -Property 'NotAfter' | Format-Table -AutoSize -Property @(
'DnsNameList'
'IsSelfSigned'
'RootCAType'
'Services'
'Status'
'PrivateKeyExportable'
'PublicKeySize'
'Identity'
'FriendlyName'
'NotBefore'
'NotAfter'
)
@ConanChiles
Copy link
Author

for each DAG
log into each member server
put one into maintenance mode using the above
other DAG member will be active
do maintenance (updates, reboot, whatever)
pull out of maintenance
repeat for other DAG member
repeat for next DAG

DAG1

  • server1
  • server2

DAG2

  • server3
  • server4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment