VMware Cloud Community
monderick
Enthusiast
Enthusiast
Jump to solution

snapshot script help

Most of the below script for listing snapshots was passed to me ( i made some small modifications) and it works great except that it will not list the original creator of the snapshot but rather the creator of the latest snapshot even if it doesn't exist, vDP snapshots for example.  I believe it's how the Get-VIEvents is being called instead of getting the snapshot creator from the get-snapshot command.

Anyone able to point me in the right direction or use another method of finding snapshot creator?

thanks.

$myVMs = Get-VM

$VMsWithSnaps = @()

foreach ($vm in $myVMs) {

    $vmView = $vm | Get-View

    if ($vmView.snapshot -ne $null) {

$snapsize = get-vm $vm | get-snapshot | select @{N="SizeMB";E={[Math]::Round($_.SizeMb)}}

        $SnapshotEvents = Get-VIEvent -Entity $vm -type info -MaxSamples 1000 | Where {

            $_.FullFormattedMessage.contains("Create virtual machine snapshot")}

        try {

        $user = $SnapshotEvents[0].UserName

        $time = $SnapshotEvents[0].CreatedTime

        } catch [System.Exception] {

$user = $SnapshotEvents.UserName

$time = $SnapshotEvents.CreatedTime

        }

        $VMInfo = “” | Select "VM","CreationDate","User","SizeMb"

$VMInfo."VM" = $vm.Name

$VMInfo."CreationDate" = $time

$VMInfo."User" = $user

$VMInfo."SizeMb" = $snapsize.SizeMb

$VMsWithSnaps += $VMInfo

    }

}

$VMsWithSnaps | Sort CreationDate | ft -auto

after searching around on google, original script looks to have come from:

Find virtual machine snapshots with PowerCLI | Notes from a Sysadmin

Reply
0 Kudos
1 Solution

Accepted Solutions
davotronic5000
Contributor
Contributor
Jump to solution

I have written a script before, which I will post a section of below, which does what you need,  TO get the name of the snapshot creator it involves using the API to get the task logged when the snapshot was created, (by getting the create snapshot task for the relevant VM within 5 seconds of the snapshot complete time).  The whole script to see this section in context is here http://davotronic5000.co.uk/blog/updated-script-to-monitor-snapshots-in-vsphere/.  The part which gets the snapshot creators name is:

Write-Verbose "Getting list of Old Snapshots"

    $OldSnapshotList = $SnapshotList | Where {$_.Created -LE (Get-Date).AddDays(-$AlertOlderThan)}

    IF ($OldSnapshotList -ne $null)

        {

        Write-Verbose "Getting Additional Snapshot Details"

        #Open report array

        $Report = @()

        $SnapUser = ""

        FOREACH ($Snapshot in $OldSnapshotList)

            {

            #Use Task log SDK to get the user who created the Snapshot

            $TaskMgr = Get-View TaskManager

            $TaskNumber = 100

            #Create task filter for search

            $Filter = New-Object VMware.Vim.TaskFilterSpec

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

            $Filter.Time.beginTime = ((($Snapshot.Created).AddSeconds(-5)).ToUniversalTime())

            $Filter.Time.timeType = "startedTime"

            $Filter.Time.EndTime = ((($Snapshot.Created).AddSeconds(5)).ToUniversalTime())

            $Filter.State = "success"

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

            $Filter.Entity.recursion = "self"

            $Filter.Entity.entity = (Get-Vm -Name $Snapshot.VM.Name).Extensiondata.MoRef

            $TaskCollector = Get-View ($TaskMgr.CreateCollectorForTasks($Filter))

            $TaskCollector.RewindCollector | Out-Null

            $Tasks = $TaskCollector.ReadNextTasks($TaskNumber)

                #Get only the task for the snapshot in question and out put the username of the snapshot creator

                FOREACH ($Task in $Tasks)

                    {

                    $GuestName = $Snapshot.VM

                    $Task = $Task | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $GuestName}                         

                    IF ($Task -ne $null)

                        {

                        $SnapUser = $Task

                        }

                    $TaskCollector.ReadNextTasks($TaskNumber)

                    }

                #Create a custom object for reporting

                $objReport = New-Object System.Object

                $objReport | Add-Member -Type NoteProperty -Name "Name" -Value $Snapshot.Name

                $objReport | Add-Member -Type NoteProperty -Name "Description" -Value $Snapshot.Description                

                $objReport | Add-Member -Type NoteProperty -Name "Created By" -Value $SnapUser.Reason.Username

                $objReport | Add-Member -Type NoteProperty -Name "Attached To" -Value $Snapshot.VM

                $objReport | Add-Member -Type NoteProperty -Name "Created On" -Value $Snapshot.Created

                $Report += $objReport

            #There is a default limit of 32 collector objects, destroying collector after use

            $TaskCollector.DestroyCollector()

            }

View solution in original post

Reply
0 Kudos
7 Replies
davotronic5000
Contributor
Contributor
Jump to solution

I have written a script before, which I will post a section of below, which does what you need,  TO get the name of the snapshot creator it involves using the API to get the task logged when the snapshot was created, (by getting the create snapshot task for the relevant VM within 5 seconds of the snapshot complete time).  The whole script to see this section in context is here http://davotronic5000.co.uk/blog/updated-script-to-monitor-snapshots-in-vsphere/.  The part which gets the snapshot creators name is:

Write-Verbose "Getting list of Old Snapshots"

    $OldSnapshotList = $SnapshotList | Where {$_.Created -LE (Get-Date).AddDays(-$AlertOlderThan)}

    IF ($OldSnapshotList -ne $null)

        {

        Write-Verbose "Getting Additional Snapshot Details"

        #Open report array

        $Report = @()

        $SnapUser = ""

        FOREACH ($Snapshot in $OldSnapshotList)

            {

            #Use Task log SDK to get the user who created the Snapshot

            $TaskMgr = Get-View TaskManager

            $TaskNumber = 100

            #Create task filter for search

            $Filter = New-Object VMware.Vim.TaskFilterSpec

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

            $Filter.Time.beginTime = ((($Snapshot.Created).AddSeconds(-5)).ToUniversalTime())

            $Filter.Time.timeType = "startedTime"

            $Filter.Time.EndTime = ((($Snapshot.Created).AddSeconds(5)).ToUniversalTime())

            $Filter.State = "success"

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

            $Filter.Entity.recursion = "self"

            $Filter.Entity.entity = (Get-Vm -Name $Snapshot.VM.Name).Extensiondata.MoRef

            $TaskCollector = Get-View ($TaskMgr.CreateCollectorForTasks($Filter))

            $TaskCollector.RewindCollector | Out-Null

            $Tasks = $TaskCollector.ReadNextTasks($TaskNumber)

                #Get only the task for the snapshot in question and out put the username of the snapshot creator

                FOREACH ($Task in $Tasks)

                    {

                    $GuestName = $Snapshot.VM

                    $Task = $Task | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $GuestName}                         

                    IF ($Task -ne $null)

                        {

                        $SnapUser = $Task

                        }

                    $TaskCollector.ReadNextTasks($TaskNumber)

                    }

                #Create a custom object for reporting

                $objReport = New-Object System.Object

                $objReport | Add-Member -Type NoteProperty -Name "Name" -Value $Snapshot.Name

                $objReport | Add-Member -Type NoteProperty -Name "Description" -Value $Snapshot.Description                

                $objReport | Add-Member -Type NoteProperty -Name "Created By" -Value $SnapUser.Reason.Username

                $objReport | Add-Member -Type NoteProperty -Name "Attached To" -Value $Snapshot.VM

                $objReport | Add-Member -Type NoteProperty -Name "Created On" -Value $Snapshot.Created

                $Report += $objReport

            #There is a default limit of 32 collector objects, destroying collector after use

            $TaskCollector.DestroyCollector()

            }

Reply
0 Kudos
monderick
Enthusiast
Enthusiast
Jump to solution

Thanks, I modified the portion of script you posted (below) to help me learn how it works and ran it to verify the results.

All the fields (Description, Created On, etc) looks ok except for "Created By" which is either blank or the wrong user listed multiple times.  I'm dealing with snapshots that are only a day or two old.

Write-Verbose "Getting list of Old Snapshots"

    $OldSnapshotList = Get-VM | get-snapshot

    IF ($OldSnapshotList -ne $null)

        {

        Write-Verbose "Getting Additional Snapshot Details"

        #Open report array

        $Report = @()

        $SnapUser = ""

        FOREACH ($Snapshot in $OldSnapshotList)

            {

            #Use Task log SDK to get the user who created the Snapshot

            $TaskMgr = Get-View TaskManager

            $TaskNumber = 100

            #Create task filter for search

            $Filter = New-Object VMware.Vim.TaskFilterSpec

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

            $Filter.Time.beginTime = ((($Snapshot.Created).AddSeconds(-5)).ToUniversalTime())

            $Filter.Time.timeType = "startedTime"

            $Filter.Time.EndTime = ((($Snapshot.Created).AddSeconds(5)).ToUniversalTime())

            $Filter.State = "success"

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

            $Filter.Entity.recursion = "self"

            $Filter.Entity.entity = (Get-Vm -Name $Snapshot.VM.Name).Extensiondata.MoRef

            $TaskCollector = Get-View ($TaskMgr.CreateCollectorForTasks($Filter))

            $TaskCollector.RewindCollector | Out-Null

            $Tasks = $TaskCollector.ReadNextTasks($TaskNumber)

                #Get only the task for the snapshot in question and out put the username of the snapshot creator

                FOREACH ($Task in $Tasks)

                    {

                    $GuestName = $Snapshot.VM

                    $Task = $Task | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $GuestName}                        

                    IF ($Task -ne $null)

                        {

                        $SnapUser = $Task

                        }

                    $TaskCollector.ReadNextTasks($TaskNumber)

                    }

                #Create a custom object for reporting

                $objReport = New-Object System.Object

  $objReport | Add-Member -Type NoteProperty -Name "Snapshot Name" -Value $Snapshot.Name

                $objReport | Add-Member -Type NoteProperty -Name "Description" -Value $Snapshot.Description               

                $objReport | Add-Member -Type NoteProperty -Name "Created By" -Value $SnapUser.Reason.Username

                $objReport | Add-Member -Type NoteProperty -Name "Attached To" -Value $Snapshot.VM

                $objReport | Add-Member -Type NoteProperty -Name "Created On" -Value $Snapshot.Created

                $Report += $objReport

            #There is a default limit of 32 collector objects, destroying collector after use

            $TaskCollector.DestroyCollector()

            }

  }

  $report

Reply
0 Kudos
monderick
Enthusiast
Enthusiast
Jump to solution

I take that back, changed the filter time to 60 seconds from 5 as this may not be enough and the script is now reporting creator properly.

thanks, davotronic5000!


Reply
0 Kudos
monderick
Enthusiast
Enthusiast
Jump to solution

The snapshot report script has been working great, until i noticed it does not handle VMs that have multiple snapshots very well and the "Days Old" result displays a "System.Object []" error.  I tried to rewrite it a bit so the logic outputs the correct number of days for VMs with multiple snapshots but at my wits end.  Any advice?

thanks

example of error:

Snapshot Name

Description

Created By

Virtual Machine

Created On

SizeMB

Days Old

20130621_upgrade

upgrade

User1

Test1

6/21/2013 3:55:03 PM

5440

7

20130624_patch

patch

User1

Test2

6/24/2013 11:43:40 AM

120

  1. System.Object[]

Pre-Project

testing

User2

Test2

6/25/2013 12:15:25 PM

5152

  1. System.Object[]

current script that works great otherwise (edited out the sensitive bits):

Add-PSSnapin VMware.VimAutomation.Core

  Connect-VIServer #,#

  $OldSnapshotList = Get-VM | where {$_.name -notlike "*wvm*"} | get-snapshot

    IF ($OldSnapshotList -ne $null)

        {

        $Report = @()

        $SnapUser = ""

        FOREACH ($Snapshot in $OldSnapshotList)

            {

            $TaskMgr = Get-View TaskManager

            $TaskNumber = 100

            $Filter = New-Object VMware.Vim.TaskFilterSpec

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

            $Filter.Time.beginTime = ((($Snapshot.Created).AddSeconds(-60)).ToUniversalTime())

            $Filter.Time.timeType = "startedTime"

            $Filter.Time.EndTime = ((($Snapshot.Created).AddSeconds(60)).ToUniversalTime())

            $Filter.State = "success"

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

            $Filter.Entity.recursion = "self"

            $Filter.Entity.entity = (Get-Vm -Name $Snapshot.VM.Name).Extensiondata.MoRef

            $TaskCollector = Get-View ($TaskMgr.CreateCollectorForTasks($Filter))

            $TaskCollector.RewindCollector | Out-Null

            $Tasks = $TaskCollector.ReadNextTasks($TaskNumber)

                FOREACH ($Task in $Tasks)

                    {

  $GuestName = $Snapshot.VM

  $Daysold = Get-VM  $GuestName | Get-Snapshot | Select @{N="DaysOld"; e={((Get-Date) - $_.Created).Days}}

                    $Task = $Task | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $GuestName}                     

                    IF ($Task -ne $null)

                        {

                        $SnapUser = $Task

                        }

                    $TaskCollector.ReadNextTasks($TaskNumber)

                    }

  $SplitSnapUser = $SnapUser.Reason.Username -split('\\') | select -last 1

                #Create a custom object for reporting

  $objReport = New-Object System.Object

  $objReport | Add-Member -Type NoteProperty -Name "Snapshot Name" -Value $Snapshot.Name

                $objReport | Add-Member -Type NoteProperty -Name "Description" -Value $Snapshot.Description            

                $objReport | Add-Member -Type NoteProperty -Name "Created By" -Value $SplitSnapUser

                $objReport | Add-Member -Type NoteProperty -Name "Virtual Machine" -Value $Snapshot.VM

                $objReport | Add-Member -Type NoteProperty -Name "Created On" -Value $Snapshot.Created

  $objReport | Add-Member -Type NoteProperty -Name "SizeMB" -Value ([System.Math]::Round($Snapshot.SizeMB))

  $objReport | Add-Member -Type NoteProperty -Name "Days Old" -Value $DaysOld.DaysOld

                $Report += $objReport

            $TaskCollector.DestroyCollector()

            }

  }

$head = "<style>

                 TABLE{border-width:1px; border-color: black;font-size:12px; font-family:courier; border-style: solid; border-collapse: collapse;}

                 TH{border-width:1px; border-style: solid; padding: 0px; border-color: black; background-color: #006699; color: white;}

                 TD{border-width:1px; border-style: solid; padding: 7px; border-color: black; background-color:#424242; color: white;}

                        </style>"    

$mailreport = $report | sort "Created On"  | ConvertTo-Html -Head $head | Out-String

Send-MailMessage -to #,#,# -from # -subject "vCenter Snapshot Report" -body $mailreport -BodyAsHtml -smtpServer #

Disconnect-VIServer # -Confirm:$false

Disconnect-VIServer # -Confirm:$false

Reply
0 Kudos
davotronic5000
Contributor
Contributor
Jump to solution

Hi Monderick

I think I can see where the problem is, where the line   $Daysold = Get-VM  $GuestName | Get-Snapshot | Select @{N="DaysOld"; e={((Get-Date) - $_.Created).Days}}   has been added if the VM has multiple snapshots then $Daysold will be an array, which when it is then being added to the object the array is not being enumerated causing the error you are getting.

I am not in a position to be able to test this at the moment but if where you are adding the days old propertie to the object you use just $DaysOld instead of $daysOld.DaysOld it should work,  If not I can take a bit more of a look at this later on.

davotronic5000
Contributor
Contributor
Jump to solution


I have take a bit more of a look at this, so ignore my previous post.  The best way to acheive what you need is to remove the line:

$Daysold = Get-VM  $GuestName | Get-Snapshot | Select @{N="DaysOld"; e={((Get-Date) - $_.Created).Days}} 

Then because we are already retireving the created date for each snapshot to get the count of days since it was created as a propertie of the object all you need to to is change the line creating that property to:

  $objReport | Add-Member -Type NoteProperty -Name "Days Old" -Value $((Get-Date) - $Snapshot.Created).Day

This should then create this property uniquely for each snapshot reported avaoiding the problem you are getting.

FYI, I am not near an environment I can test this on, so the syntax may be slightly off, but should point you in the right direction.

monderick
Enthusiast
Enthusiast
Jump to solution

brilliant, davotronic5000!  of course, i was over-complicating things.

added once tiny modification to the new line 44 and works perfectly now.

$objReport | Add-Member -Type NoteProperty -Name "Days Old" -Value $((Get-Date) - $Snapshot.Created).Days


thanks for the assist, this community is amazing.

Reply
0 Kudos