<DataSourceModuleType ID="ScriptInstanceDST.Execute_Troubleshoot_DatabaseSpace_diagnostic_script." Accessibility="Public">
<Configuration/>
<ModuleImplementation>
<Composite>
<MemberModules>
<DataSource ID="DS" TypeID="Microsoft_Exchange_2010_Execute_Database_Space_Troubleshooter">
<IntervalSeconds>3600</IntervalSeconds>
<SyncTime>$Target/Host/Property[Type="Microsoft.Exchange.2010.ServerRole"]/CmdletSyncTime$</SyncTime>
<TimeoutSeconds>1200</TimeoutSeconds>
<ScriptName>Troubleshoot-DatabaseSpace.ps1</ScriptName>
<Arguments>-Server $Target/Host/Host/Property[Type='Windows!Microsoft.Windows.Computer']/PrincipalName$ -MonitoringContext</Arguments>
<ScriptBody><Script>
# Copyright (c) 2010 Microsoft Corporation. All rights reserved.
#
# THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK
# OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
[parameter(
ParameterSetName = "Server",
Mandatory = $true,
HelpMessage = "The mailbox server to troubleshoot.")]
[String]
[ValidateNotNullOrEmpty()]
$Server,
[parameter(
Mandatory = $false,
HelpMessage = "The percentage of disk space for the EDB file at which we should start quarantining users.")]
[int]
[ValidateRange(1, 99)]
[ValidateNotNullOrEmpty()]
$PercentEdbFreeSpaceThreshold,
[parameter(
Mandatory = $false,
HelpMessage = "The percentage of disk space for the logs at which we should start quarantining users.")]
[int]
[ValidateRange(1, 99)]
[ValidateNotNullOrEmpty()]
$PercentLogFreeSpaceThreshold,
[parameter(
Mandatory = $false,
HelpMessage = "The number of hours we can wait before running out of space.")]
[int]
[ValidateRange(1, 1000000000)]
[ValidateNotNullOrEmpty()]
$HourThreshold,
[parameter(
Mandatory = $false,
HelpMessage = "Whether or not to quarantine heavy users.")]
[switch]
$Quarantine,
[parameter(
Mandatory = $false,
HelpMessage = "Whether or not we're running under the monitoring context.")]
[switch]
$MonitoringContext
)
#
# Check a single database for free space
#
function Troubleshoot-DatabaseCopySpace([Microsoft.Exchange.Data.Directory.SystemConfiguration.MailboxDatabase] $database, [int] $PercentEdbFreeSpaceThreshold, [int] $PercentLogFreeSpaceThreshold, [int] $HourThreshold, [bool] $Quarantine, [bool] $MonitoringContext)
{
if ($database -eq $null)
{
$argError = new-object System.ArgumentException ($error[0].Exception.ToString())
throw $argError
}
# Event log source name for application log
$appLogSourceName = "Database Space Troubleshooter"
# Event log source name for crimson log
$crimsonLogSourceName = "Database Space"
# The Arguments object is needed for logging
# events.
$Arguments = new-object -typename Arguments
$Arguments.Server = $database.MountedOnServer
$Arguments.Database = $database
$Arguments.MonitoringContext = $MonitoringContext
$Arguments.WriteApplicationEvent = $false
# Check the Edb drive for space
$edbGrowthRateThreshold = -1
$edbVolume = Get-WmiVolumeFromPath $database.EdbFilePath $database.MountedOnServer
$Arguments.InstanceName = $edbVolume.Name -replace "\\$", "" # Remove any trailing backslash if exists since SCOM discovery removes it from the instance name
Log-Event `
-Arguments $Arguments `
-EventInfo $StoreLogEntries.DatabaseSpaceTroubleShooterStarted `
-Parameters @($Arguments.InstanceName, $database)
$edbVolumeFreeSpace = $edbVolume.FreeSpace + $database.AvailableNewMailboxSpace
$edbPercentFreeSpace = ($edbVolumeFreeSpace * 100) / $edbVolume.Capacity
# Check the Log drive for space
$logGrowthRateThreshold = -1
$logVolume = Get-WmiVolumeFromPath $database.LogFolderPath $database.MountedOnServer
$logVolumeFreeSpace = $logVolume.FreeSpace
$logPercentFreeSpace = ($logVolumeFreeSpace * 100) / $logVolume.Capacity
if ($logPercentFreeSpace -lt $PercentLogFreeSpaceThreshold)
{
$logGrowthRateThreshold = $logVolume.FreeSpace / $HourThreshold
}
$growthRateThreshold = -1
# Figure out which of the 2 thresholds is lower
# to determine whether or not we need to quarantine
# some users
if ($logGrowthRateThreshold -ne -1)
{
$growthRateThreshold = $logGrowthRateThreshold
}
# Check if we are low on space compared to any of the thresholds
$problemDetected = $false
if ($edbPercentFreeSpace -lt $PercentEdbFreeSpaceCriticalThreshold)
{
# Log an event that will trigger paging alert for critical space issue
Log-Event `
-Arguments $Arguments `
-EventInfo $StoreLogEntries.DatabaseSpaceTroubleDetectedCriticalSpaceIssue `
-Parameters @($Arguments.InstanceName, $database, $PercentEdbFreeSpaceCriticalThreshold)
$problemDetected = $true
}
elseif ($edbPercentFreeSpace -lt $PercentEdbFreeSpaceAlertThreshold)
{
# Log an event that will trigger non-paging alert for low space issue
Log-Event `
-Arguments $Arguments `
-EventInfo $StoreLogEntries.DatabaseSpaceTroubleDetectedAlertSpaceIssue `
-Parameters @($Arguments.InstanceName, $database, $PercentEdbFreeSpaceAlertThreshold)
# Log a warning event for low space issue
Log-Event `
-Arguments $Arguments `
-EventInfo $StoreLogEntries.DatabaseSpaceTroubleDetectedWarningSpaceIssue `
-Parameters @($Arguments.InstanceName, $database, $PercentEdbFreeSpaceThreshold)
$problemDetected = $true
}
# Format to show only 2 decimal places in event log
$edbPercentFreeSpace = "{0:N2}" -f $edbPercentFreeSpace
$logPercentFreeSpace = "{0:N2}" -f $logPercentFreeSpace
$edbVolumeFreeSpaceInGB = "{0:N2}" -f ($edbVolumeFreeSpace/1GB)
$logVolumeFreeSpaceInGB = "{0:N2}" -f ($logVolumeFreeSpace/1GB)
if ($problemDetected)
{
# Exclude the database from provisioning as we are below one of the space thresholds
Set-MailboxDatabase $database -IsExcludedFromProvisioning $true
}
else
{
# We have enough free space that we are not going to even bother looking for outliers causing rapid growth to try to qurantine.
if ($growthRateThreshold -eq -1)
{
Log-Event `
-Arguments $Arguments `
-EventInfo $StoreLogEntries.DatabaseSpaceTroubleShooterNoProblemDetected `
-Parameters @($Arguments.InstanceName, $database, $edbVolumeFreeSpaceInGB, $edbPercentFreeSpace, $logVolumeFreeSpaceInGB, $logPercentFreeSpace, $PercentEdbFreeSpaceThreshold, $PercentLogFreeSpaceThreshold, $HourThreshold, $counterValue, $PercentEdbFreeSpaceCriticalThreshold, $PercentEdbFreeSpaceAlertThreshold, $QuarantineValue)
# Do we need to quarantine users?
if (($currentGrowthRate -lt $growthRateThreshold))
{
Log-Event `
-Arguments $Arguments `
-EventInfo $StoreLogEntries.DatabaseSpaceTroubleShooterFoundLowSpaceNoQuarantine `
-Parameters @($Arguments.InstanceName, $database, $edbVolumeFreeSpaceInGB, $edbPercentFreeSpace, $logVolumeFreeSpaceInGB, $logPercentFreeSpace, $PercentEdbFreeSpaceThreshold, $PercentLogFreeSpaceThreshold, $HourThreshold, $growthRateThreshold, $counterValue, $currentGrowthRate, $PercentEdbFreeSpaceCriticalThreshold, $PercentEdbFreeSpaceAlertThreshold, $QuarantineValue)
return
}
# We have to quarantine some users now, so
# get the least of the most active users
# and figure out which ones we need to quarantine
# so that the current log generation rate drops
# below our maximum calculated growth rate
$topLogGenerators = @(Get-TopLogGenerators $database)
$iNextUserToQuarantine = 0
# Since we're in strict mode we must declare all variables we use
$script:monitoringEvents = $null
if (!$MyInvocation.BoundParameters.ContainsKey("PercentEdbFreeSpaceThreshold"))
{
$PercentEdbFreeSpaceThreshold = $PercentEdbFreeSpaceDefaultThreshold
}
if (!$MyInvocation.BoundParameters.ContainsKey("PercentLogFreeSpaceThreshold"))
{
$PercentLogFreeSpaceThreshold = $PercentLogFreeSpaceDefaultThreshold
}
if (!$MyInvocation.BoundParameters.ContainsKey("HourThreshold"))
{
$HourThreshold = $HourDefaultThreshold
}
if ($Quarantine)
{
$QuarantineValue = $true
}
if ($MonitoringContext)
{
$MonitoringContextValue = $true
#E14:303295 Add a monitoring event to suppress SCOM failure alerts
#Use a guid for each invocation so that we can identify
#start and finish events for each unique invocation
$InvocationGuid = [System.Guid]::NewGuid().ToString()
$messageStart = "Database Space TS started successfully for Invocation Guid {0}" -f $InvocationGuid
Add-MonitoringEvent -Id $StoreLogEntries.DatabaseSpaceTroubleShooterStarted[0] -Type $EVENT_TYPE_INFORMATION -Message $messageStart
}
foreach($database in $databases)
{
#Get the status right before invoking the function
#so we can narrow down failover related issues
$database = Get-MailboxDatabase $database -Status
#Run only if the database is specified or in case of server,
#on the active copy to avoid running it multiple times
#against the same database
if (($MailboxServer -eq $null) -or
($database.MountedOnServer -match $MailboxServer))
{
Troubleshoot-DatabaseCopySpace `
-database $database `
-PercentEdbFreeSpaceThreshold $PercentEdbFreeSpaceThreshold `
-PercentLogFreeSpaceThreshold $PercentLogFreeSpaceThreshold `
-HourThreshold $HourThreshold `
-Quarantine $QuarantineValue `
-MonitoringContext $MonitoringContextValue
}
}
if ($MonitoringContext)
{
#Monitoring event to suppress SCOM failure alerts
#Also lets us know that TS did finish successfully
$messageFinish = "Database Space TS finished successfully for Invocation Guid {0}" -f $InvocationGuid
Add-MonitoringEvent -Id 5102 -Type $EVENT_TYPE_INFORMATION -Message $messageFinish