Search code examples
powershellpowerclivcenter

How do I get events associated with Datastores and Datastore Clusters using PowerCLI?


This is a followup to this question I posted but running into an issue with enumerating events on some objects now. When I run the following code (or try any of the solutions in my prior question) to get the events from a datastore or datastore cluster for example:

Get-VMFolder FOLDER_NAME -Type Datastore | Get-DatastoreCluster | Get-VIEvent

I'm met with the following error for each event it tries to return:

Events can be retrieved only for inventory objects. The entity of type
'VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.VmfsDatastoreImpl' will be ignored.

This is particularly annoying since the cmdlet clearly enumerates the events as I get this error for every event it attempts to return.


When I use the Get-TaskPlus function mentioned in the accepted answer to my prior question returns a different type conversion error:

Cannot process argument transformation on parameter 'Entity'. Cannot convert the "DATASTORE_CLUSTER_NAME" value of type "VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreClusterImpl" to type "VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl".

If I remove the type constraint on the $Entity argument in the function definition, the error goes away but I also don't get any results.

I'm not really looking for recommendations or tools here, but if Get-VIEvent to look for events on non-inventory objects through PowerCLI, is there a workaround or more nuanced way to retrieve this information with PowerCLI?


Solution

  • After I posted this I did some more digging and found that Luc Dekens wrote another function called
    Get-VIEventPlus. This doesn't work out of the box because -Entity expects a type of VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[], but datastores and datastore clusters have a different type under the VMWare.VimAutomation.ViCore.Impl.V1.DatastoreManagement namespace.

    If we make one change to LucD's function to accept the base type VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[] instead of InventoryItemImpl[], Get-VIEventPlus should work other vCenter object types:

    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.VIObjectImpl[]]$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
      }
    }
    

    Update: The original answer changed the -Entity type to be an object[]. I have updated this function to make use of the VMware.VimAutomation.ViCore.Impl.V1.VIObjectImpl[] base type for -Entity instead.