VMware Cloud Community
AlbertWT
Virtuoso
Virtuoso
Jump to solution

Using PowerCLI to show Error and Warning VI Events in the vCenter in the past 1 hour?

Hi Folks,

I need some help in creating the cmdlet or script to show Error and Warning VI Events in the vCenter in the past 1 hour? 

I have stumbled upon this article: Get the vMotion/svMotion history - LucD notes

But not sure how to build the cmd line so this can be scripted every 1 hour using scheduled task.

Thank you in advance.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Yes, it can.
The EventFilterSpec contains a property named Category.
In there, you can enter one or more of the EventCategory values (Error,Info,User,Warning).

This updated version makes that option available.

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.   
	.PARAMETER Category
	Limits the set of collected events to those associated with the specified category 
	.EXAMPLE
	PS> Get-VIEventPlus -Entity $vm
	.EXAMPLE
	PS> Get-VIEventPlus -Entity $cluster -Recurse:$true
	.EXAMPLE
	PS> Get-VIEventPlus -Entity $cluster -Category 'error','warning'
	#>
	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,
		[string[]]$Category
	)
	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
		$eventFilter.Category = $Category
		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
	}
}


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

View solution in original post

12 Replies
LucD
Leadership
Leadership
Jump to solution

I'm not sure what exactly you want to retrieve.
All events for the past hour, or specific events for the past hour?

To prepare, copy the Get-VIEventPlus function to a .ps1 file (for example GetVIEventPlus.ps1).
Then dot-source that .ps1 file (note the space betwene the 2 dots at the start of the line), this makes sure that your PS sessions "knows" the function.

. .\GetVIEventPlus.ps1


Now you can "call" the function.

If you just want to retrieve all events created against the root of the vCenter for the last hour, you can do

 

Get-VIEventPlus -Start (Get-Date).AddHours(-1)

 

 If you want all events in the vCenter for the last hour, you can do

Get-VIEventPlus -Start (Get-Date).AddHours(-1) -Recurse

If you want specific events, you could do

Get-VIEventPlus -Start (Get-Date).AAddHours(-1) -EventType 'DrsVmMigratedEvent','VmMigratedEvent'


If you have more specific requirements, let me know.

 


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

AlbertWT
Virtuoso
Virtuoso
Jump to solution

Hi @LucD ,

Thank you for the reply.

May I know if the script can be used or customized to show the result for any Error, Critical or Failed events in the past 1 hour?

 

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, it can.
The EventFilterSpec contains a property named Category.
In there, you can enter one or more of the EventCategory values (Error,Info,User,Warning).

This updated version makes that option available.

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.   
	.PARAMETER Category
	Limits the set of collected events to those associated with the specified category 
	.EXAMPLE
	PS> Get-VIEventPlus -Entity $vm
	.EXAMPLE
	PS> Get-VIEventPlus -Entity $cluster -Recurse:$true
	.EXAMPLE
	PS> Get-VIEventPlus -Entity $cluster -Category 'error','warning'
	#>
	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,
		[string[]]$Category
	)
	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
		$eventFilter.Category = $Category
		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
	}
}


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

AlbertWT
Virtuoso
Virtuoso
Jump to solution

Wow, thank you @LucD for the assistance in this thread.

I wonder what am I missing in the below code to iterate through all of my vCenters:

 

 

$connectVIServer = @'
"Server",     "User", "Password"
"10.10.10.10", "DOMAIN\VI-Admin1", "Pass1"
"20.20.20.20", "DOMAIN\VI-Admin2", "Pass2"
"99.99.99.99", "DOMAIN\VI-AdminX", "PassX"
'@ | ConvertFrom-Csv

ForEach ($row in $connectVIServer)
{
Write-Host "Connecting to '$($row.Server)'".

$paramConnectVIServer = @{
Server   = $row.Server
User = $row.User
Password = $row.Password
}

Connect-VIServer @paramConnectVIServer

$paramGetVIEventPlus = @{
Recurse  = $true
Entity   = $_
Category = 'error', 'warning', 'user', 'info'
}

$AllEvents += Get-Cluster | Get-VIEventPlus @paramGetVIEventPlus

$paramDisconnectVIServer = @{
Server = $paramConnectVIServer.Server
Force  = $true
}

Disconnect-VIServer @paramDisconnectVIServer
}

$AllEvents | Out-GridView

 

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this

$connectVIServer = @'
"Server",     "User", "Password"
"10.10.10.10", "DOMAIN\VI-Admin1", "Pass1"
"20.20.20.20", "DOMAIN\VI-Admin2", "Pass2"
"99.99.99.99", "DOMAIN\VI-AdminX", "PassX"
'@ 
$connectVIServer | ConvertFrom-Csv -PipelineVariable row |
ForEach-Object -Process {
	Write-Host "Connecting to '$($row.Server)'".

	$paramConnectVIServer = @{
		Server   = $row.Server
		User = $row.User
		Password = $row.Password
	}

	Connect-VIServer @paramConnectVIServer

	$paramGetVIEventPlus = @{
		Recurse  = $true
		Entity   = $_
		Category = 'error', 'warning', 'user', 'info'
	}

	$AllEvents += Get-Cluster | Get-VIEventPlus @paramGetVIEventPlus

	$paramDisconnectVIServer = @{
		Server = $paramConnectVIServer.Server
		Force  = $true
	}

	Disconnect-VIServer @paramDisconnectVIServer
}

$AllEvents | Out-GridView

 


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

AlbertWT
Virtuoso
Virtuoso
Jump to solution

Hi, @LucD many thanks for the update.

For the calculated property below, I wonder why it does not translate into meaningful text or strings although I have expanded it.

AlbertWT_0-1686275133591.png

This is the snippet I am using:

$paramGetVIEventPlus = @{    Recurse  = $true    Entity   = $_    Category = 'error', 'warning', 'user', 'info'    FullMessage = $true    Start    = (Get-Date).AddDays(-1)    Finish   = (Get-Date)
}

Get-Cluster |
Get-VIEventPlus @paramGetVIEventPlus |
Select-Object IPAddress,
              CreatedTime,
              Username,
              @{ N = "DataCenter"; E = { $_.Datacenter } },
              @{ N = "ComputeResource"; E = { $_.ComputeResource } },
              @{ N = "Host"; E = { $_.Host } },
              @{ N = "VM"; E = { $_.VM } },
              FullFormattedMesage |
Out-GridView
 
/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

PowerCLI doesn't know how to show these objects, hence it shows the type of the object.
You want the Name property in those objects.

$paramGetVIEventPlus = @{    Recurse  = $true    Entity   = $_    Category = 'error', 'warning', 'user', 'info'    FullMessage = $true    Start    = (Get-Date).AddDays(-1)    Finish   = (Get-Date)
}

Get-Cluster |
Get-VIEventPlus @paramGetVIEventPlus |
Select-Object IPAddress,
              CreatedTime,
              Username,
              @{ N = "DataCenter"; E = { $_.Datacenter.Name } },
              @{ N = "ComputeResource"; E = { $_.ComputeResource.Name } },
              @{ N = "Host"; E = { $_.Host.Name } },
              @{ N = "VM"; E = { $_.VM.Name } },
              FullFormattedMesage |
Out-GridView


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

AlbertWT
Virtuoso
Virtuoso
Jump to solution

Yes, that works well.

One last thing, with the FullFormattedMesage property.

It does not show the value when I executed the above or the last code snippets like:

Get-Cluster | 
Get-VIEventPlus @paramGetVIEventPlus | 
Select-Object IPAddress,
			  CreatedTime,
			  Username,
			  @{ N = "DataCenter"; E = { $_.Datacenter.Name } },
			  @{ N = "ComputeResource"; E = { $_.ComputeResource.Name } },
			  @{ N = "Host"; E = { $_.Host.Name } },
			  @{ N = "VM"; E = { $_.VM.Name } },
			  @{ N = "FullFormattedMesage"; E = { $_.FullFormattedMesage.Name } } | 
Out-GridView

 

but it shows fine when it is selected as *

 

Get-Cluster | 
Get-VIEventPlus @paramGetVIEventPlus | 
Select-Object IPAddress,
			  CreatedTime,
			  Username,
			  @{ N = "DataCenter"; E = { $_.Datacenter.Name } },
			  @{ N = "ComputeResource"; E = { $_.ComputeResource.Name } },
			  @{ N = "Host"; E = { $_.Host.Name } },
			  @{ N = "VM"; E = { $_.VM.Name } },
			  @{ N = "FullFormattedMesage"; E = { $_.FullFormattedMesage.Name } }, * | 
Out-GridView

 

how to show the complete values for the FullFormattedMesage property?

Thank you.
/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

For the message there is no Name property, just $_.FullFormattedMessage should be sufficient.


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

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso
Jump to solution

Hi @LucD ,
Yes, I did that already, but somehow the FullFormattedMesage result is still not shown.

AlbertWT_0-1686305383842.png

 

While select-object * shows everything including the FullFormattedMesage value.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Just noticed, there is a type in the property name.
It should be (double 's')

@{ N = "FullFormattedMesage"; E = { $_.FullFormattedMessage } }

  


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

AlbertWT
Virtuoso
Virtuoso
Jump to solution

Yes, that works great,

Many thanks, @LucD for your great support as always.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos