VMware Cloud Community
gefleborg
Contributor
Contributor

Get-VIEvent showing completion time

I have snapshots created by TSM-VE backups that sometimes take very long time to remove.

I want to run a command that shows a list by running

Get-folder vmbackup | get-vm | Get-VIEvent -start (Get-Date).AddDays(-1) | where {$_.FullFormattedMessage -match "Remove snapshot"} | select CreatedTime, CompletedTime, Username, fullformattedMessage | sort CreatedTime | ft -auto

I can't find out how to get [Completed Time]. If I look in vCenter GUI I can see [Requested Start Time], [Start Time] and [Completed Time].

If I use select * on Get-VIEvent I get the following columns

Info                 :

Key                  :

ChainId              :

CreatedTime          :

UserName             :

Datacenter           :

ComputeResource      :

Host                 :

Vm                   :

Ds                   :

Net                  :

Dvs                  :

FullFormattedMessage :

ChangeTag            :

DynamicType          :

DynamicProperty      :

Is it possible to get what I'm after?

/Peter

Reply
0 Kudos
5 Replies
LucD
Leadership
Leadership

That information is not available in the TaskEvent but in the Task object.

You can do something like this (the Get-TaskPlus function is based on my Task Data Mining – An improved Get-Task post).

function Get-TaskPlus {

<# 

.SYNOPSIS  Returns vSphere Task information  

.DESCRIPTION The function will return vSphere task info. The

  available parameters allow server-side filtering of the

  results

.NOTES  Author:  Luc Dekens 

.PARAMETER Alarm

  When specified the function returns tasks triggered by

  specified alarm

.PARAMETER Entity

  When specified the function returns tasks for the

  specific vSphere entity

.PARAMETER Recurse

  Is used with the Entity. The function returns tasks

  for the Entity and all it's children

.PARAMETER State

  Specify the State of the tasks to be returned. Valid

  values are: error, queued, running and success

.PARAMETER Start

  The start date of the tasks to retrieve

.PARAMETER Finish

  The end date of the tasks to retrieve.

.PARAMETER UserName

  Only return tasks that were started by a specific user

.PARAMETER MaxSamples

  Specify the maximum number of tasks to return

.PARAMETER Reverse

  When true, the tasks are returned newest to oldest. The

  default is oldest to newest

.PARAMETER Server

  The vCenter instance(s) for which the tasks should

  be returned

.PARAMETER Realtime

  A switch, when true the most recent tasks are also returned.

.PARAMETER Details

  A switch, when true more task details are returned

.PARAMETER Keys

  A switch, when true all the keys are returned

.EXAMPLE

  PS> Get-TaskPlus -Start (Get-Date).AddDays(-1)

.EXAMPLE

  PS> Get-TaskPlus -Alarm $alarm -Details

#>

  

  param(

    [CmdletBinding()]

    [VMware.VimAutomation.ViCore.Impl.V1.Alarm.AlarmDefinitionImpl]$Alarm,

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

    [switch]$Recurse = $false,

    [VMware.Vim.TaskInfoState[]]$State,

    [DateTime]$Start,

    [DateTime]$Finish,

    [string]$UserName,

    [int]$MaxSamples = 100,

    [switch]$Reverse = $true,

    [VMware.VimAutomation.ViCore.Impl.V1.VIServerImpl[]]$Server = $global:DefaultVIServer,

    [switch]$Realtime,

    [switch]$Details,

    [switch]$Keys,

    [int]$WindowSize = 100

  )

  begin {

    function Get-TaskDetails {

      param(

        [VMware.Vim.TaskInfo[]]$Tasks

      )

      begin{

        $psV3 = $PSversionTable.PSVersion.Major -ge 3

      }

      process{

        $tasks | %{

          if($psV3){

            $object = [ordered]@{}

          }

          else {

            $object = @{}

          }

          $object.Add("Name",$_.Name)

          $object.Add("Description",$_.Description.Message)

          if($Details){$object.Add("DescriptionId",$_.DescriptionId)}

          if($Details){$object.Add("Task Created",$_.QueueTime)}

          $object.Add("Task Started",$_.StartTime)

          if($Details){$object.Add("Task Ended",$_.CompleteTime)}

          $object.Add("State",$_.State)

          $object.Add("Result",$_.Result)

          $object.Add("Entity",$_.EntityName)

          $object.Add("VIServer",$VIObject.Name)

          $object.Add("Error",$_.Error.ocalizedMessage)

          if($Details){

            $object.Add("Cancelled",(&{if($_.Cancelled){"Y"}else{"N"}}))

            $object.Add("Reason",$_.Reason.GetType().Name.Replace("TaskReason",""))

            $object.Add("AlarmName",$_.Reason.AlarmName)

            $object.Add("AlarmEntity",$_.Reason.EntityName)

            $object.Add("ScheduleName",$_.Reason.Name)

            $object.Add("User",$_.Reason.UserName)

          }

          if($keys){

            $object.Add("Key",$_.Key)

            $object.Add("ParentKey",$_.ParentTaskKey)

            $object.Add("RootKey",$_.RootTaskKey)

          }

          New-Object PSObject -Property $object

        }

      }

    }

    $filter = New-Object VMware.Vim.TaskFilterSpec

    if($Alarm){

      $filter.Alarm = $Alarm.ExtensionData.MoRef

    }

    if($Entity){

      $filter.Entity = New-Object VMware.Vim.TaskFilterSpecByEntity

      $filter.Entity.entity = $Entity.ExtensionData.MoRef

      if($Recurse){

        $filter.Entity.Recursion = [VMware.Vim.TaskFilterSpecRecursionOption]::all

      }

      else{

        $filter.Entity.Recursion = [VMware.Vim.TaskFilterSpecRecursionOption]::self

      }

    }

    if($State){

      $filter.State = $State

    }

    if($Start -or $Finish){

      $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime

      $filter.Time.beginTime = $Start

      if($Finish){

          $filter.Time.endTime = $Finish

      }

      else{

          $filter.Time.endTime = Get-Date

      }

      $filter.Time.timeType = [vmware.vim.taskfilterspectimeoption]::startedTime

    }

    if($UserName){

      $userNameFilterSpec = New-Object VMware.Vim.TaskFilterSpecByUserName

      $userNameFilterSpec.UserList = $UserName

      $filter.UserName = $userNameFilterSpec

    }

    $nrTasks = 0

  }

  process {

    foreach($viObject in $Server){

      $si = Get-View ServiceInstance -Server $viObject

      $tskMgr = Get-View $si.Content.TaskManager -Server $viObject

      if($Realtime -and $tskMgr.recentTask){

        $tasks = Get-View $tskMgr.recentTask

        $selectNr = [Math]::Min($tasks.Count,$MaxSamples-$nrTasks)

        Get-TaskDetails -Tasks[0..($selectNr-1)]

        $nrTasks += $selectNr

      }

      $tCollector = Get-View ($tskMgr.CreateCollectorForTasks($filter))

      if($Reverse){

        $tCollector.ResetCollector()

        $taskReadOp = $tCollector.ReadPreviousTasks

      }

      else{

        $tCollector.RewindCollector()

        $taskReadOp = $tCollector.ReadNextTasks

      }

      do{

        $tasks = $taskReadOp.Invoke($WindowSize)

   

        $selectNr = [Math]::Min($tasks.Count,$MaxSamples-$nrTasks)

        Get-TaskDetails -Tasks $tasks[0..($selectNr-1)]

        $nrTasks += $selectNr

      }while($tasks -and $nrTasks -lt $MaxSamples)

    }

    $tCollector.DestroyCollector()

  }

}

$start = (Get-Date).AddHours(-12)

Get-VM | %{

    Get-TaskPlus -Entity $__ -Start $start -Details -MaxSamples ([int]::MaxValue) |

    where{$_.Name -eq 'CreateSnapshot_Task'} |

    Select Entity,State,'Task Created','Task Started','Task Ended'

}


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

gefleborg
Contributor
Contributor

Hi LucD!

I loaded Get-TaskPlus and then executed this line

Get-TaskPlus -MaxSamples 99999 -Start (Get-Date).AddDays(-1) | where {$_.name -eq "RemoveSnapshot_Task"} | select Name, "Task Created", "Task Started", "Task Ended", Entity | sort entity | ft -AutoSize

The result is without Task Created and Task Ended. I get Task Started value (in UTC it seems).

What am I missing since I don't get the other date/time?

        

EDIT:

Now I found the details parameter. I get all dates in UTC so I'll fix that.

Since this gives me a list with VM as Entity, should it not be possible to add parameter -Entity "vmname"? I get an error that powershell cannot convert the "vmname". I had to list "vmname" in the where clause.

/Peter

Reply
0 Kudos
gefleborg
Contributor
Contributor

Hi again LucD!

I'm not a developer but I trySmiley Happy

I got the information that I'm after, so my question is solved, but my solution to fix UTC to local date/time gives me an error when there is no data in the date/time variable.

You cannot call a method on a null-valued expression.

At \\P100v071\pl14860$\WinData\Sync\utils\Get-TaskPlus.ps1:84 char:24

+           if($Details){$object.Add("Task Ended",$_.CompleteTime.ToLocalTime())}

+                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

Can you please tell me how solve it 8or update your function?

I added .ToLocalTime() in the function after the timevariables like this on row 82-84

if($Details){$object.Add("Task Created",$_.QueueTime)}

$object.Add("Task Started",$_.StartTime)

if($Details){$object.Add("Task Ended",$_.CompleteTime)}

if($Details){$object.Add("Task Created",$_.QueueTime.ToLocalTime())}

$object.Add("Task Started",$_.StartTime.ToLocalTime())

if($Details){$object.Add("Task Ended",$_.CompleteTime.ToLocalTime())}

/Peter

Reply
0 Kudos
LucD
Leadership
Leadership

We can use a script block for the 2nd parameter of the Add method.

In that script block we can test the content.

Something like this

$obj = @{}

$test = Get-Date '15/04/2015 09:00'

$obj.Add('Time1',{if($test){$test.ToLocalTime()}})

$test = ''

$obj.Add('Time2',{if($test){$test.ToLocalTime()}})


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

gefleborg
Contributor
Contributor

So, now I have it all as I want.

I could not use your code sample, only got errors. Probably because I don't know Powershell. I did it like this on row 84-86.

if($Details){if($_.QueueTime){$object.Add("Task Created",$_.QueueTime.ToLocalTime())}}

$object.Add("Task Started",$_.StartTime.ToLocalTime())

if($Details){if($_.CompleteTime){$object.Add("Task Ended",$_.CompleteTime.ToLocalTime())}}

Tx for all help.

/Peter

Reply
0 Kudos