VMware Cloud Community
Baoth
Enthusiast
Enthusiast
Jump to solution

Script to report RPO violations

Hi all

I have seen a few forums posts in regards to something similar to what I am trying to achieve, and although I understand getting replication status is somewhat difficult as there is no public API, I am hoping that something can be tweaked to get what I need via a script.

I am currently running the below which I found here:

Get-VIEvent -MaxSamples ([int]::MaxValue) | Where { $_.EventTypeId -match "hbr|rpo" } | Select CreatedTime, FullFormattedMessage, @{Name="VMName";Expression={$_.Vm.Name}} | export-csv -NoTypeInformation -Path ([Environment]::GetFolderPath("Desktop") + "\HBR-RPOEvents.csv")

However, that is returning everything under the FullFormattedMessage column. I'd like to filter that so it only contains "Virtual machine vSphere Replication RPO is violated by 1 minute(s)".

If possible, I would like to avoid the 1 minute part of the log though. The reason for this is that Alerts work well enough, and will email me when something is violated, but its constantly sending me the 1 minute messages, which subsequently clear under normal operation.

I'd ultimately like to get to a stage where I'm alerted if something is violated by more than 1 minute, and covers the last 24 hours.

Hope you can help.

Thanks.

29 Replies
Baoth
Enthusiast
Enthusiast
Jump to solution

Not tried that yet. Will have a look shortly.

However, this was much, much quicker:

Get-VIEventPlus -Start (Get-Date).adddays(-1) -MaxSamples ([int]::MaxValue) |

Where { $_.EventTypeId -match "hbr|rpo" -and $_.FullFormattedMessage -match "Virtual machine vSphere Replication RPO is violated" -and $_.FullFormattedMessage -notmatch "violated by 1 minute"} |

Select CreatedTime, FullFormattedMessage,

    @{Name="VMName";Expression={$_.Vm.Name}} |

Export-Csv -NoTypeInformation -Path ([Environment]::GetFolderPath("Desktop") + "\HBR-RPOEvents_24hrs_eventplus.csv")

Will try the version that includes the sort-object and let you know how that goes.

Thanks for the help with this.

0 Kudos
Baoth
Enthusiast
Enthusiast
Jump to solution

Worked an absolute treat Luc!

If I wanted to get this running from within the estate, and to send a daily email with the output forming part of the email to our operations and monitoring people, would the whole script have to look something like this:

function Get-VIEventPlus {

<#  

.SYNOPSIS  Returns vSphere events   

.DESCRIPTION The function will return vSphere events. With

    the available parameters, the execution time can be

   improved, compered to the original Get-VIEvent cmdlet.

.NOTES  Author:  Luc Dekens  

.PARAMETER Entity

   When specified the function returns events for the

   specific vSphere entity. By default events for all

   vSphere entities are returned.

.PARAMETER EventType

   This parameter limits the returned events to those

   specified on this parameter.

.PARAMETER Start

   The start date of the events to retrieve

.PARAMETER Finish

   The end date of the events to retrieve.

.PARAMETER Recurse

   A switch indicating if the events for the children of

   the Entity will also be returned

.PARAMETER User

   The list of usernames for which events will be returned

.PARAMETER System

   A switch that allows the selection of all system events.

.PARAMETER ScheduledTask

   The name of a scheduled task for which the events

   will be returned

.PARAMETER FullMessage

   A switch indicating if the full message shall be compiled.

   This switch can improve the execution speed if the full

   message is not needed.  

.EXAMPLE

   PS> Get-VIEventPlus -Entity $vm

.EXAMPLE

   PS> Get-VIEventPlus -Entity $cluster -Recurse:$true

#>

  param(

    [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$Entity,

    [string[]]$EventType,

    [DateTime]$Start,

    [DateTime]$Finish = (Get-Date),

    [switch]$Recurse,

    [string[]]$User,

    [Switch]$System,

    [string]$ScheduledTask,

    [switch]$FullMessage = $false

  )

  process {

    $eventnumber = 100

    $events = @()

    $eventMgr = Get-View EventManager

    $eventFilter = New-Object VMware.Vim.EventFilterSpec

    $eventFilter.disableFullMessage = ! $FullMessage

    $eventFilter.entity = New-Object VMware.Vim.EventFilterSpecByEntity

    $eventFilter.entity.recursion = &{if($Recurse){"all"}else{"self"}}

    $eventFilter.eventTypeId = $EventType

    if($Start -or $Finish){

      $eventFilter.time = New-Object VMware.Vim.EventFilterSpecByTime

    if($Start){

        $eventFilter.time.beginTime = $Start

    }

    if($Finish){

        $eventFilter.time.endTime = $Finish

    }

    }

  if($User -or $System){

    $eventFilter.UserName = New-Object VMware.Vim.EventFilterSpecByUsername

    if($User){

      $eventFilter.UserName.userList = $User

    }

    if($System){

      $eventFilter.UserName.systemUser = $System

    }

  }

  if($ScheduledTask){

    $si = Get-View ServiceInstance

    $schTskMgr = Get-View $si.Content.ScheduledTaskManager

    $eventFilter.ScheduledTask = Get-View $schTskMgr.ScheduledTask |

      where {$_.Info.Name -match $ScheduledTask} |

      Select -First 1 |

      Select -ExpandProperty MoRef

  }

  if(!$Entity){

    $Entity = @(Get-Folder -Name Datacenters)

  }

  $entity | %{

      $eventFilter.entity.entity = $_.ExtensionData.MoRef

      $eventCollector = Get-View ($eventMgr.CreateCollectorForEvents($eventFilter))

      $eventsBuffer = $eventCollector.ReadNextEvents($eventnumber)

      while($eventsBuffer){

        $events += $eventsBuffer

        $eventsBuffer = $eventCollector.ReadNextEvents($eventnumber)

      }

      $eventCollector.DestroyCollector()

    }

    $events

  }

}

Get-VIEventplus -Start (Get-Date).adddays(-1) -MaxSamples ([int]::MaxValue) |

Where { $_.EventTypeId -match "hbr|rpo" -and $_.FullFormattedMessage -match "Virtual machine vSphere Replication RPO is violated" -and $_.FullFormattedMessage -notmatch "violated by 1 minute"} |

Select CreatedTime, FullFormattedMessage,

    @{Name="VMName";Expression={$_.Vm.Name}} |

Group-Object -Property VMName |

ForEach-Object -Process {

    $_.Group | Sort-Object -Property CreatedTime -Descending |

    select -First 1

} |

Export-Csv -NoTypeInformation -Path ([Environment]::GetFolderPath("Desktop") + "\HBR-RPOEvents_24hrs_eventplus_sort.csv")

Not having tried getting the output into an email yet, I going to presume its the last line following the pipe that would need to change somewhat?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You could do something like this.
To make the report in the email more colourful and nicely formatted, you can use HTML style elements.

For examples, have a look at Re: Datastore Capacity Load and Re: Formatting report

$report = Get-VIEventplus -Start (Get-Date).adddays(-1) -MaxSamples ([int]::MaxValue) |

    Where { $_.EventTypeId -match "hbr|rpo" -and $_.FullFormattedMessage -match "Virtual machine vSphere Replication RPO is violated" -and $_.FullFormattedMessage -notmatch "violated by 1 minute" } |

    Select CreatedTime, FullFormattedMessage,

    @{Name = "VMName"; Expression = { $_.Vm.Name } } |

    Group-Object -Property VMName |

    ForEach-Object -Process {

        $_.Group | Sort-Object -Property CreatedTime -Descending |

        select -First 1

}


$sMail = @{

    To         = 'you@domain'

    From       = 'me@domain'

    Subject    = 'Report'

    SmtpServer = 'mail.domain'

    BodyAsHtml = $true

    Body       = $report | ConvertTo-Html | Out-String

}

Send-MailMessage @sMail


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Baoth
Enthusiast
Enthusiast
Jump to solution

Hi LucD

I have been trying to test, but couldn't for various reasons.

Finally have it working though, and it did send a mail, but the body was empty. That is expected, as there were no entries that had violations above 1 minute last night though.

Is there anything that can be added to put a message in the email body that "no violations found" in the case that there is nothing returned please?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You could do something like this

$report = Get-VIEventplus -Start (Get-Date).adddays(-1) -MaxSamples ([int]::MaxValue) |

    Where { $_.EventTypeId -match "hbr|rpo" -and $_.FullFormattedMessage -match "Virtual machine vSphere Replication RPO is violated" -and $_.FullFormattedMessage -notmatch "violated by 1 minute" } |

    Select CreatedTime, FullFormattedMessage,

    @{Name = "VMName"; Expression = { $_.Vm.Name } } |

    Group-Object -Property VMName |

    ForEach-Object -Process {

        $_.Group | Sort-Object -Property CreatedTime -Descending |

        select -First 1

}

if(-not $report){

    $report = 'no violations found'

}

$sMail = @{

    To         = 'you@domain'

    From       = 'me@domain'

    Subject    = 'Report'

    SmtpServer = 'mail.domain'

    BodyAsHtml = $true

    Body       = $report | ConvertTo-Html | Out-String

}


Send-MailMessage @sMail


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Baoth
Enthusiast
Enthusiast
Jump to solution

Email successfully received, with the below content:

*

19

Looks like it does contain cells / borders though.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Then try like this

$report = Get-VIEventplus -Start (Get-Date).adddays(-1) -MaxSamples ([int]::MaxValue) |

    Where { $_.EventTypeId -match "hbr|rpo" -and $_.FullFormattedMessage -match "Virtual machine vSphere Replication RPO is violated" -and $_.FullFormattedMessage -notmatch "violated by 1 minute" } |

    Select CreatedTime, FullFormattedMessage,

    @{Name = "VMName"; Expression = { $_.Vm.Name } } |

    Group-Object -Property VMName |

    ForEach-Object -Process {

        $_.Group | Sort-Object -Property CreatedTime -Descending |

        select -First 1

}

if(-not $report){

    $body = ConvertTo-Html -Body 'no violations found' | Out-String

}

else{

    $body = $report | ConvertTo-Html | Out-String

}

$sMail = @{

    To         = 'you@domain'

    From       = 'me@domain'

    Subject    = 'Report'

    SmtpServer = 'mail.domain'

    BodyAsHtml = $true

    Body       = $body

}


Send-MailMessage @sMail


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Baoth
Enthusiast
Enthusiast
Jump to solution

Amazing as ever!

Thanks LucD.

0 Kudos
Baoth
Enthusiast
Enthusiast
Jump to solution

Hi LucD

Sorry to drag this one up again. Is there an easy change to the script that will alter the subject of the e-mail if there are no violations when none are found, as opposed to the subject hard coded as 'Report' please?

Thanks

0 Kudos
LucD
Leadership
Leadership
Jump to solution

No problem.

You can use the same test we used for the Body.

The mail part could then be

if(-not $report){

    $body = ConvertTo-Html -Body 'no violations found' | Out-String

    $subject = 'No violations found'

}

else{

    $body = $report | ConvertTo-Html | Out-String

    $subject = 'Report'

}

$sMail = @{

    To         = 'you@domain'

    From       = 'me@domain'

    Subject    = $subject

    SmtpServer = 'mail.domain'

    BodyAsHtml = $true

    Body       = $body

}


Send-MailMessage @sMail


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference