I have asked a few similar questions but my report that contains snapshots is in sore need of expanding in order to call out some culprits and to ensure that our backup software is not abandoning snaps in the environment. So far I have the following snippet from my report as a lead in example:
Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn'} |
Select -First 50 Name,
@{N='SnapShot';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList | %{
Get-Snap -Snap $_
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='SnapShot Created';E={($script:snaps | sort-Object -property Name).CreateTime -join ','}},
@{N="Days Old";E={(New-TimeSpan -End (Get-Date) -Start $script:snaps.CreateTime).Days}},
@{N='Created By';E={$snapevent = Get-VIEvent -Entity $_ -Types Info -Finish $_.created -MaxSamples 1 | Where-Object {$_.FullFormattedMessage -imatch 'Task: Create virtual machine snapshot'}
$snapevent.UserName}}
Everything works except the Created By
If I run this on a single server I get all Created by results from the Event Log including ones that have been deleted.
$snapevent = Get-VIEvent -Entity ServerA -Types Info -Finish ServerA.Created -MaxSamples 1 | Where-Object {$_.FullFormattedMessage -imatch 'Task: Create virtual machine snapshot'}
$snapevent.UserName
Any help is greatly appreciated.
There are a couple of flaws in there.
Try the following
Select -First 50 Name,
@{N='SnapShot';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList | %{
Get-Snap -Snap $_
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='SnapShot Created';E={($script:snaps | sort-Object -property Name).CreateTime -join '|'}},
@{N="Days Old";E={
$now = Get-Date
($script:snaps | %{(New-TimeSpan -End $now -Start $_.CreateTime).Days}) -join '|'}},
@{N='Created By';E={
$start = $script:snaps.CreateTime | Sort-Object | Select -First 1
(Get-VIEvent -Entity $_.Name -Start $start -MaxSamples ([int]::MaxValue) |
Where-Object {$_ -is [VMware.Vim.TaskEvent] -and $_.Info.DescriptionId -eq 'VirtualMachine.createSnapshot'} |
Select -ExpandProperty UserName) -join '|'}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks LucD for the quick response. I also want to thank you for the education. Unfortunately the script modifications return the created by results of every created by event in the event logs not just for snapshots that currently exist. Any ideas?
I was originally trying to model it after the following
#
foreach ($snap in Get-VM | Get-Snapshot)
{$snapevent = Get-VIEvent -Entity $snap.VM -Types Info -Finish $snap.Created -MaxSamples 1 | Where-Object {$_.FullFormattedMessage -imatch 'Task: Create virtual machine snapshot'}
if ($snapevent -ne $null){Write-Host ( "VM: "+ $snap.VM + ". Snapshot '" + $snap + "' created on " + $snap.Created.DateTime + " by " + $snapevent.UserName +".")}
else {Write-Host ("VM: "+ $snap.VM + ". Snapshot '" + $snap + "' created on " + $snap.Created.DateTime + ". This event is not in vCenter events database")}}
#
You could try to verify the event's CreateTime against the Created times of the snapshots.
Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn'}} |
Select -First 50 Name,
@{N='SnapShot';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList | %{
Get-Snap -Snap $_
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='SnapShot Created';E={($script:snaps | sort-Object -property Name).CreateTime -join '|'}},
@{N="Days Old";E={
$now = Get-Date
($script:snaps | %{(New-TimeSpan -End $now -Start $_.CreateTime).Days}) -join '|'}},
@{N='Created By';E={
$startEvents = $script:snaps.CreateTime
$start = $startEvents | Sort-Object | Select -First 1
(Get-VIEvent -Entity $_.Name -Start $start -MaxSamples ([int]::MaxValue) |
Where-Object {$_ -is [VMware.Vim.TaskEvent] -and
$_.Info.DescriptionId -eq 'VirtualMachine.createSnapshot' -and
$startEvents -contains $_.CreateTime} |
Select -ExpandProperty UserName) -join '|'}}
But there might be slight differences in these timestamp.
I normally add a margin of 5 seconds plus and minus, but the margin depends on the load in your environment.
Let's first check if a straight timestamp comparison works.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
This is an example where I accept 1 2 second difference between the time in the Event and the time on the Snapshot.
Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn'}} |
Select -First 50 Name,
@{N='SnapShot';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList | %{
Get-Snap -Snap $_
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='SnapShot Created';E={($script:snaps | sort-Object -property Name).CreateTime -join '|'}},
@{N="Days Old";E={
$now = Get-Date
($script:snaps | %{(New-TimeSpan -End $now -Start $_.CreateTime).Days}) -join '|'}},
@{N='Created By';E={
$startEvents = $script:snaps.CreateTime
$start = $startEvents | Sort-Object | Select -First 1
(Get-VIEvent -Entity $_.Name -Start $start -MaxSamples ([int]::MaxValue) |
Where-Object {$_ -is [VMware.Vim.TaskEvent] -and $_.Info.DescriptionId -eq 'VirtualMachine.createSnapshot'} |
ForEach-Object -Process {
$event = $_
$startEvents | ForEach-Object -Process {
if([math]::Abs((New-TimeSpan -Start $event.CreateTime -End $_).TotalSeconds) -lt $timeDiff){
$event
}
}
} | Select-Object -ExpandProperty UserName) -join '|'}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD,
I have tried both and even ran it against the entire environment and had no results returned. I have verified that I am storing tasks for 120 days before cleanup is run.
Just remembered that datetime values in events are always reported in UTC, while the snapshot timestamp are in local time.
Try this version, it converts the event timestamp to local time.
You alse might want to expriment with the value in $timeDiff.
It is currently set to 2 seconds.
Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn'}} |
Select -First 50 Name,
@{N='SnapShot';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList | %{
Get-Snap -Snap $_
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='SnapShot Created';E={($script:snaps | sort-Object -property Name).CreateTime -join '|'}},
@{N="Days Old";E={
$now = Get-Date
($script:snaps | %{(New-TimeSpan -End $now -Start $_.CreateTime).Days}) -join '|'}},
@{N='Created By';E={
$startEvents = $script:snaps.CreateTime
$start = $startEvents | Sort-Object | Select -First 1
(Get-VIEvent -Entity $_.Name -Start $start -MaxSamples ([int]::MaxValue) |
Where-Object {$_ -is [VMware.Vim.TaskEvent] -and $_.Info.DescriptionId -eq 'VirtualMachine.createSnapshot'} |
ForEach-Object -Process {
$event = $_
$startEvents | ForEach-Object -Process {
if([math]::Abs((New-TimeSpan -Start $event.CreateTime.ToLocalTime() -End $_).TotalSeconds) -lt $timeDiff){
$event
}
}
} | Select-Object -ExpandProperty UserName) -join '|'}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
So I ran the update and I have picked a recent snapshot and the creator data is still not showing in the report. Below is a screenshot.
Here are the results of the $report
Here is what is listed under tasks for the snapshot that was taken by the administrator
I hope this information helps in some way, you have been a great help so far.
I'm a bit confused, the report seems to say the snapshot was created on 10/10/2019 at 04:33, while the event seems to say 09/10/2019 at 11:33.
From that I would conclude that you are in a timezone UTC-5.
Is that correct?
If yes, the ToLocalTime function should have converted the event's CreateTime to 10/10/2019 04:33.
This could mean that the difference between the timestamps might be more than 2 seconds.
Did you try it with a higher $timeDiff, let's say 60 seconds?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Modified to time offset to be 60 and still no results.
ran Get-VIEvent -Entity servername -Types Info
Yes, that is approximately the same time of the Task event you showed earlier.
But are you in UTC-5?
Can you run this for that VM and the snapshot event?
Select CreatedTime,@{N='Local time';E={$_.CreatedTime.ToLocal()}},FullFormattedMessage
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
10/9/2019 11:33:03 PM | Task: Create virtual machine snapshot |
PS C:\Scripts> Get-TimeZone
Id : Central Standard Time
DisplayName : (UTC-06:00) Central Time (US & Canada)
StandardName : Central Standard Time
DaylightName : Central Daylight Time
BaseUtcOffset : -06:00:00
SupportsDaylightSavingTime : True
Ok, that 1 hour difference is probably due to DST.
Did you run the snippet from my previous reply?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, it was the top line
10/9/2019 11:33:03 PM | Task: Create virtual machine snapshot |
Ok, that seems to be very close to the Created timestamp on the snapshot.
Can you run the following short experiment against that test VM.
It will create a snapshot, and display the timestamps from the event and the snapshot.
$vmName = 'ServerName'
$now = Get-Date
$vm = Get-VM -Name $vmName
$task = New-Snapshot -VM $vm -Name Test -RunAsync
while($task.ExtensionData.Info.State -ne 'success'){
sleep 2
$task.ExtensionData.UpdateViewData('Info.State')
}
$task.ExtensionData.UpdateViewData('Info')
Get-VIEvent -Entity $vm -Start $now | where{$task.Id -eq $_.Info.Task} |
Select @{N='Task StartTime';E={$task.ExtensionData.Info.StartTime.ToLocalTime().ToString('dd-MM-yyyy HH:mm:ss.fff')}},
@{N='Task FinishTime';E={$task.ExtensionData.Info.CompleteTime.ToLocalTime().ToString('dd-MM-yyyy HH:mm:ss.fff')}},
@{N='Event Created';E={$_.CreatedTime.ToString('dd-MM-yyyy HH:mm:ss.fff')}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Task StartTime Task FinishTime Event Created
15-10-2019 13:37:14.056 15-10-2019 13:37:15.268 15-10-2019 13:37:14.053
Perfect.
It looks like I swapped to conversion to local time.
Try this version
Get-View -ViewType VirtualMachine -Filter @{'Runtime.PowerState'='poweredOn'} |
Select -First 50 Name,
@{N='SnapShot';E={
function Get-Snap{
param([PSObject]$snap)
$snap
if($snap.ChildSnapshotList){
$snap.ChildSnapshotList | %{
Get-Snap -Snap $_
}
}
}
$script:snaps = $_.Snapshot.RootSnapshotList | %{
Get-Snap -Snap $_
}
($script:snaps | sort-Object -property Name).Name -join '|'}},
@{N='SnapShot Created';E={($script:snaps | sort-Object -property Name).CreateTime -join '|'}},
@{N="Days Old";E={
$now = Get-Date
($script:snaps | %{(New-TimeSpan -End $now -Start $_.CreateTime).Days}) -join '|'}},
@{N='Created By';E={
$startEvents = $script:snaps.CreateTime
$start = $startEvents | Sort-Object | Select -First 1
(Get-VIEvent -Entity $_.Name -Start $start.AddSeconds(- $timeDiff) -MaxSamples ([int]::MaxValue) |
Where-Object {$_ -is [VMware.Vim.TaskEvent] -and $_.Info.DescriptionId -eq 'VirtualMachine.createSnapshot'} |
ForEach-Object -Process {
$event = $_
$startEvents | ForEach-Object -Process {
if([math]::Abs((New-TimeSpan -Start $event.CreatedTime -End $_.ToLocalTime()).TotalSeconds) -lt $timeDiff){
$event
}
}
} | Select-Object -ExpandProperty UserName) -join '|'}}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
PURE GENIUS!!!
Sorry, it took me a while to realise the root of the problem where the timestamps and the timezone.
All's well...
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I followed this thread with great interest. However, it is not working for me with vCenter 6.7U3. Latest version of PowerCLI. First I have to remove a "}" before it will run. Then the output I receive is like this:
Name : server1
SnapShot :
SnapShot Created :
Days Old :
Created By :
Name : server2
SnapShot :
SnapShot Created :
Days Old :
Created By :
Name : server3
SnapShot :
SnapShot Created :
Days Old :
Created By :
It is listing snapshots that do not currently exist (maybe they did in the past?) without any other information. I tried different versions of the script presented here and that is the best I get. I am at UTC -5. Any further advice or suggestions would be appreciated. Amazing how involved it is to acquire this simple bit of data.