Amazon EBS Volume Status Check State Monitor Type

Amazon.AmazonWebServices.MonitorType.EbsScheduledEventWarningStateType (UnitMonitorType)

Element properties:

RunAsDefault
AccessibilityInternal
Support Monitor RecalculateFalse

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource Amazon.AmazonWebServices.ScriptedClientQueryDataSource Default
EventCodeFilter ConditionDetection System.ExpressionFilter Default
FilterHealthy ConditionDetection System.ExpressionFilter Default
FilterWarning ConditionDetection System.ExpressionFilter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval (sec)
SyncTimestring$Config/SyncTime$SyncTime
TimeoutSecondsint$Config/TimeoutSeconds$Timeout (sec)

Source Code:

<UnitMonitorType ID="Amazon.AmazonWebServices.MonitorType.EbsScheduledEventWarningStateType" Accessibility="Internal">
<MonitorTypeStates>
<MonitorTypeState ID="Healthy"/>
<MonitorTypeState ID="Warning"/>
</MonitorTypeStates>
<Configuration>
<IncludeSchemaTypes>
<SchemaType>System!System.ExpressionEvaluatorSchema</SchemaType>
</IncludeSchemaTypes>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:int"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SyncTime" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:int"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="VolumeId" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Expression" type="ExpressionType"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" ParameterType="int" Selector="$Config/IntervalSeconds$"/>
<OverrideableParameter ID="SyncTime" ParameterType="string" Selector="$Config/SyncTime$"/>
<OverrideableParameter ID="TimeoutSeconds" ParameterType="int" Selector="$Config/TimeoutSeconds$"/>
</OverrideableParameters>
<MonitorImplementation>
<MemberModules>
<DataSource ID="DS" TypeID="Amazon.AmazonWebServices.ScriptedClientQueryDataSource">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime>$Config/SyncTime$</SyncTime>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<ScriptName>EbsScheduledEventSource.ps1</ScriptName>
<ScriptBody><Script>param($AWSAccessKey, $AWSSecretKey)

# Valid Values: ok | impaired | insufficient-data

#TODO: Discuss event id
$SCRIPT_EVENT_ID = 4114

#Event Severity values
$INFORMATION_EVENT_TYPE = 0
$ERROR_EVENT_TYPE = 1

$ServiceUrl = "https://{0}.{1}.amazonaws.com"
$EC2Address = "ec2"

function Main {
param(
$AWSAccessKey,
$AWSSecretKey
)

try
{
#
# Prepare MOM API and property bag object
#
$api = New-Object -comObject "MOM.ScriptAPI"
#$propertyBag = $api.CreatePropertyBag()

$status_count = 0

#
# Retrieve Regoins
#
$ec2client = [Amazon.AWSClientFactory]::CreateAmazonEC2Client($AWSAccessKey, $AWSSecretKey)
$request = New-Object Amazon.EC2.Model.DescribeRegionsRequest;
$response = $ec2client.DescribeRegions($request)
foreach ($region in $response.DescribeRegionsResult.Region) {
#
# Discovering objects on ALL REGIONS
#
$regionName = $region.RegionName

#
# Discover EC2 Instances
#
$ec2Config = New-Object Amazon.EC2.AmazonEC2Config;
$ec2Config.ServiceURL = $serviceUrl -f $EC2Address, $regionName
$ec2client = [Amazon.AWSClientFactory]::CreateAmazonEC2Client($AWSAccessKey, $AWSSecretKey, $ec2Config)

$statuses = GetVolumesStatuses $ec2client $null
if ($statuses -ne $null) {
foreach ($status in $statuses) {
if ($status.IsSetVolumeStatusEvent()) {
$activeEvent = $null
$startedFirstDate = $null

foreach ($event in $status.VolumeStatusEvent) {

$propertyBag = $api.CreatePropertyBag()
$propertyBag.AddValue("VolumeId", $status.VolumeId )
$propertyBag.AddValue("EventType", $event.EventType)
$propertyBag.AddValue("Description", $event.Description)
$propertyBag.AddValue("NotBefore", $event.NotBefore)
$propertyBag.AddValue("NotAfter", $event.NotAfter)
$MonitorStatus = GetMonitorStatus $event.EventType $event.NotAfter
$propertyBag.AddValue("MonitorStatus",$MonitorStatus )

if ($startedFirstDate -eq $null){
$startedFirstDate = $event.NotBefore
$activeEvent = $propertyBag
}
else{
if ( (Get-Date $event.NotBefore) -lt (Get-Date $startedFirstDate)){
$startedFirstDate = $event.NotBefore
$activeEvent = $propertyBag2
}
}
}

#if we found an event then output it
if($activeEvent -ne $null){
$activeEvent
$status_count++
}
}
}
}
}

$msg = "{0} volume scheduled events received." -f $status_count
$header = "Elastic Block Store Volumes Scheduled Events monitor state successfully calculated"
$api.LogScriptEvent($header, $SCRIPT_EVENT_ID, $INFORMATION_EVENT_TYPE, $msg)
}
catch
{
$header = "Managegement Group: $Target/ManagementGroup/Name$. Script: {0}" -f ($MyInvocation.MyCommand).Name.ToString()
$msg = "Error occured during Elastic Block Store Volumes Scheduled Events state calculation.{0}Computer:{1} {0}Reason: {2}" -f [Environment]::NewLine, $env:COMPUTERNAME, $_.Exception.Message
$api.LogScriptEvent($header, $SCRIPT_EVENT_ID, $ERROR_EVENT_TYPE, $msg)
}
}

function GetMonitorStatus{
param($EventType, $endDate)

$result = "Healthy"
if (($EventType.Length -gt 0 ) -and ( (NoEndDate $endDate ) -or (EventStillActual $endDate )))
{
switch ($EventType)
{
"potential-data-inconsistency" { $result = "Warning" }
"io-performance:degraded" { $result = "Warning" }
"io-performance:severely-degraded" { $result = "Warning" }
"io-performance:stalled" { $result = "Error" }
default {"Warning"}
}
}

return $result
}

function NoEndDate($str) {
$trimmedString = $str -replace " ",""
if ($trimmedString) {$false} else {$true}
}

function EventStillActual{
param($endDate)

return ((Get-Date $endDate) -gt (Get-Date))
}

function GetVolumesStatuses {
param(
$ec2client,
$NextToken
)
$result = @()
$volumeStatusRequest = New-Object Amazon.EC2.Model.DescribeVolumeStatusRequest;
$volumeStatusRequest.MaxResults = 100
if (($NextToken -ne $null) -and ($NextToken -ne "")) {
$volumeStatusRequest = $volumeStatusRequest.WithNextToken($NextToken)
}
$response = $ec2client.DescribeVolumeStatus($volumeStatusRequest);

if ($response.DescribeVolumeStatusResult -ne $null) {
foreach ($status in $response.DescribeVolumeStatusResult.VolumeStatus) {
$result += $status
}
$NextToken = $response.DescribeVolumeStatusResult.NextToken
}

$moreStatuses = $null
if (($NextToken -ne $null) -and ($NextToken -ne "")) {
$moreStatuses = GetVolumesStatuses $ec2client $NextToken
}

if ($moreStatuses -ne $null)
{
foreach ($status in $moreStatuses) {
$result += $status
}
}
return $result
}

Main $AWSAccessKey $AWSSecretKey</Script></ScriptBody>
</DataSource>
<ConditionDetection ID="EventCodeFilter" TypeID="System!System.ExpressionFilter">
<Expression>$Config/Expression$</Expression>
</ConditionDetection>
<ConditionDetection ID="FilterHealthy" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='MonitorStatus']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">Healthy</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
<ConditionDetection ID="FilterWarning" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='MonitorStatus']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">Warning</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
</MemberModules>
<RegularDetections>
<RegularDetection MonitorTypeStateID="Healthy">
<Node ID="FilterHealthy">
<Node ID="EventCodeFilter">
<Node ID="DS"/>
</Node>
</Node>
</RegularDetection>
<RegularDetection MonitorTypeStateID="Warning">
<Node ID="FilterWarning">
<Node ID="EventCodeFilter">
<Node ID="DS"/>
</Node>
</Node>
</RegularDetection>
</RegularDetections>
</MonitorImplementation>
</UnitMonitorType>