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
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
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
Hi again LucD!
I'm not a developer but I try![]()
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
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
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
