1 2 3 Previous Next 76 Replies Latest reply on Jun 13, 2018 12:52 AM by afhamsani

    Who created the Snapshot

    alanrenouf Master
    VMware Employees

       

      Any idea how I can relatemy Get-Snapshot information to the Get-VIEvent information to work out who created a snapshot ?

       

       

       

       

       

      Thanks

       

       

       

       

       

      Alan

       

       

        • 1. Re: Who created the Snapshot
          LucD Guru
          vExpertUser ModeratorsCommunity Warriors

          Short question but a long answer. In the end I got there.

          There were a few quirks in writing this script.

           

          1) The Created timestamp in the Event object is not always exactly the same as the time stamp in the VirtualMachine Snapshot property.

          The solution is to use the Task Entity property to get the time stamp of the snapshot.

          2) The Get-ViEvent cmdlet returns a VimApi.ManagedObjectReference instead of a VMware.Vim.ManagedObjectReference.

          As such this is not a big problem since I can easily convert the one MoRef to the other (unfortunately not via casting).

          3) The speed of the Get-ViEvent cmdlet is not ideal compered to the Task Collector form the APIs

          From 2) and 3) I decided to go for the Task Collector methods.

             

           

          The flow of the script is quite simple.

          First create a hash table from all tasks that created snapshots on the specific guest.

          The key into the hash table is the name of the guest concatenated with the snapshot creation timestamp.

           

          Then the script use the Get-Snapshot cmdlet to retrieve the snapshots for the guest.

          From this output a key is constructed and then the key is used to look up the user in the hash table.

          The User property is added to the SnapshotImpl object.

           

          function Get-SnapshotTree{
               param($tree, $target)
               
               $found = $null
               foreach($elem in $tree){
                    if($elem.Snapshot.Value -eq $target.Value){
                         $found = $elem
                         continue
                    }
               }
               if($found -eq $null -and $elem.ChildSnapshotList -ne $null){
                    $found = Get-SnapshotTree $elem.ChildSnapshotList $target
               }
               
               return $found
          }
          
          $daysBack = 3                            # How many days back from now
          $guestName = <VM-name>                          # The name of the guest
          
          $tasknumber = 999                       # Windowsize of the Task collector
          
          #$serviceInstance = get-view ServiceInstance
          $taskMgr = Get-View TaskManager
          
          # Create hash table. Each entry is a create snapshot task
          $report = @{}
          
          $filter = New-Object VMware.Vim.TaskFilterSpec
          $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
          $filter.Time.beginTime = (Get-Date).AddDays(-$daysBack)
          $filter.Time.timeType = "startedTime"
          
          $collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter))
          
          $dummy = $collectionImpl.RewindCollector
          $collection = $collectionImpl.ReadNextTasks($tasknumber)
          while($collection -ne $null){
               $collection | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $guestName} | %{
                    $row = New-Object PsObject
                    $row | Add-Member -MemberType NoteProperty -Name User -Value $_.Reason.UserName
                    $vm = Get-View $_.Entity
                  $snapshot = Get-SnapshotTree $vm.Snapshot.RootSnapshotList $_.Result
                    $key = $_.EntityName + "&" + ($snapshot.CreateTime.ToString())
                    $report[$key] = $row
               }
               $collection = $collectionImpl.ReadNextTasks($tasknumber)
          }
          $collectionImpl.DestroyCollector()
          
          # Get the guest's snapshots and add the user
          $snapshotsExtra = Get-VM $guestName | Get-Snapshot | % {
               $key = $_.vm.Name + "&" + ($_.Created.ToString())
               if($report.ContainsKey($key)){
                    $_ | Add-Member -MemberType NoteProperty -Name User -Value $report[$key].User
               }
               $_
          }
          
          $snapshotsExtra | Export-Csv "C:\SnapshotsExtra.csv" -NoTypeInformation -UseCulture
          

          Note1: the -UseCulture parameter on the Export-Csv cmdlet is PS v2 CTP3

          Note2: it shouldn't be too difficult to convert the script to handle all guests instead of just one. The name of the guest is already in the key in the hash table.

          • 2. Re: Who created the Snapshot
            alanrenouf Master
            VMware Employees

            Luc, is there nothing you can not do ?!

             

            Thanks very much, I managed to adapt your code to allow me to create a function for this info.

             

            
            function Get-SnapshotTree{
                 param($tree, $target)
                 
                 $found = $null
                 foreach($elem in $tree){
                      if($elem.Snapshot.Value -eq $target.Value){
                           $found = $elem
                           continue
                      }
                 }
                 if($found -eq $null -and $elem.ChildSnapshotList -ne $null){
                      $found = Get-SnapshotTree $elem.ChildSnapshotList $target
                 }
                 
                 return $found
            }
            
            function Get-SnapshotExtra ($snap){
                 #$daysBack = 5               # How many days back from now
                 $guestName = $snap.VM     # The name of the guest
                 
            
                 $tasknumber = 999          # Windowsize of the Task collector
                 
                 #$serviceInstance = get-view ServiceInstance
                 $taskMgr = Get-View TaskManager
                 
                 # Create hash table. Each entry is a create snapshot task
                 $report = @{}
                 
                 $filter = New-Object VMware.Vim.TaskFilterSpec
                 $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
                 $filter.Time.beginTime = (($snap.Created).AddSeconds(-5))
                 $filter.Time.timeType = "startedTime"
                 
                 $collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter))
                 
                 $dummy = $collectionImpl.RewindCollector
                 $collection = $collectionImpl.ReadNextTasks($tasknumber)
                 while($collection -ne $null){
                      $collection | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $guestName} | %{
                           $row = New-Object PsObject
                           $row | Add-Member -MemberType NoteProperty -Name User -Value $_.Reason.UserName
                           $vm = Get-View $_.Entity
                           $snapshot = Get-SnapshotTree $vm.Snapshot.RootSnapshotList $_.Result
                           $key = $_.EntityName + "&" + ($snapshot.CreateTime.ToString())
                           $report[$key] = $row
                      }
                      $collection = $collectionImpl.ReadNextTasks($tasknumber)
                 }
                 $collectionImpl.DestroyCollector()
                 
                 # Get the guest's snapshots and add the user
                 $snapshotsExtra = $snap | % {
                      $key = $_.vm.Name + "&" + ($_.Created.ToString())
                      if($report.ContainsKey($key)){
                           $_ | Add-Member -MemberType NoteProperty -Name Creator -Value $report[$key].User
                      }
                      $_
                 }
                 $snapshotsExtra
            }
            
            $Snapshots = Get-VM | Get-Snapshot | Where {$_.Created -lt ((Get-Date).AddDays(-14))} 
            
            $mySnaps = @()
            foreach ($snap in $Snapshots){
                 $SnapshotInfo = Get-SnapshotExtra $snap
                 $mySnaps += $SnapshotInfo
            }
            
            $mySnaps | Select VM, Name, Creator, Description
            
            
            

             

             

             

            If you found this information useful, please consider awarding points for Correct or Helpful.

             

            Alan Renouf

            http://virtu-al.net

            • 3. Re: Who created the Snapshot
              LucD Guru
              Community WarriorsvExpertUser Moderators

              It's the combined strength of PowerShell, PowerCLI and the SDK that allows me to do this kind of stuff.

              They are the instruments, I'm just the conductor

               

              Nice adaption to a general function btw.

              • 4. Re: Who created the Snapshot
                cchipman Novice

                Ok, so I have a question.  I know that this is a bit of an old topic, but why create a filter for the TaskCollector, and then not specify all the relevant filters.  I.e. you specify start time, but then don't filter on state, entity, or end time.  The only reason I bring it up is that I was running this in the snapreminder.ps1 script, and a couple of very old snapshots brought huge performance problems by bringing up hundreds of records since then. 

                • 5. Re: Who created the Snapshot
                  LucD Guru
                  vExpertUser ModeratorsCommunity Warriors

                  Basically I did that for performance reasons, the more complex the filter, the longer it will take.

                  But you are of course right.

                  • We should have used the TaskState -eq "success". No point in retrieving failed snapshot tasks
                  • Entity is handy when you want to limit the filter to a specific branch (datacenter, folder, cluster, host...) in your vSphere environment. With the RecursionOption you can easily state for which entities you want to retrieve the tasks

                   

                  In the mean time the performance of the Get-VIEvent cmdlet has improved. So you could even consider using the cmdlet instead of the collector. Just filter on TaskEvent.

                  • 6. Re: Who created the Snapshot
                    avlieshout Expert
                    VMware Employees

                    You can always specify more filter properties to narrow down your search.

                    If it fits you, use it as it will return lesser objects to filter out afterwards and improve performance.

                     

                    Don't know why there weren't any additional properties in the code though.

                    • 7. Re: Who created the Snapshot
                      cchipman Novice

                      Thanks for the suggestion, I'll try reworking it with the Get-Event.  However, I'd like to finish out the thought exercise.  I was trying to do this:

                       

                          $filter = New-Object VMware.Vim.TaskFilterSpec

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

                          $filter.Time.beginTime = (($snap.Created).AddSeconds(-5))

                          $filter.Time.timeType = "startedTime"

                          $filter.State = "success"

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

                          $filter.Entity.recursion = "self"

                          $filter.Entity.entity = Get-Vm -Name $snap.VM.Name | Get-View | Get-VIObjectByVIView

                       

                      but get the following error

                       

                       

                      Get-VIObjectByVIView : 2/2/2011 1:53:20 PM    Get-VIObjectByVIView        Object reference not set to an instance of an object.   
                      At C:\scripts\snapreminder.ps1:59 char:89
                      +     $filter.Entity.entity = Get-Vm -Name $snap.VM.Name | Get-View | Get-VIObjectByVIView <<<<
                          + CategoryInfo          : NotSpecified: (:) [Get-VIObjectByVIView], VimException
                          + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIObjectByVIViewCommand

                       

                      Any ideas on what I am doing wrong?

                      • 8. Re: Who created the Snapshot
                        LucD Guru
                        User ModeratorsvExpertCommunity Warriors

                        The property Entity needs a MoRef.

                        Try replacing this line

                        $filter.Entity.entity = Get-Vm -Name $snap.VM.Name | Get-View |  Get-VIObjectByVIView

                        by this

                        $filter.Entity.entity = (Get-Vm -Name $snap.VM.Name).Extensiondata.MoRef
                        • 9. Re: Who created the Snapshot
                          cchipman Novice

                          That worked great.  But it looks like I've run into some time based problems....

                           

                          when I get to the end of the Get-SnapshotExtra, where it's trying to see if the find the VM+Snapshot creation time in the map,

                           

                           

                             # Get the guest's snapshots and add the user

                              $snapshotsExtra = $snap | % {

                                  $key = $_.vm.Name + "&" + ($_.Created.ToString())

                                  if($report.ContainsKey($key)){

                                      $_ | Add-Member -MemberType NoteProperty -Name Creator -Value $report[$key].User

                                  }

                                  $_

                           

                          if I output the value of $key and $report it shows:

                           

                          [DBG]: PS C:\Users\admin.ccc>>> $key
                          FSBUS&1/8/2011 5:00:44 PM
                          ____________________________________________________________________________________________________________________________________________________________________________________________________________________
                          [DBG]: PS C:\Users\admin.ccc>>> $report
                          Name                           Value                                                                                                                                                                                  
                          ----                           -----                                                                                                                                                                                  
                          FSBUS&1/8/2011 11:00:44 PM     @{User=ICXT\svc.scripts}

                           

                          Now, since we are in Central time zone, the 6 hour difference *kind* of makes sense, but is there away to determine what TZ the data was in, and adjust it before we convert it to the string to put in the tables?

                           

                          Thanks for all the help, you've been extremely considerate.

                          • 10. Re: Who created the Snapshot
                            LucD Guru
                            vExpertUser ModeratorsCommunity Warriors

                            Those timestamp are kept in UTC.

                            You can easily convert to your localtime like this

                            $_.Created.ToLocalTime()
                            • 11. Re: Who created the Snapshot
                              Zsoldier Expert
                              vExpert

                              Awesome.  I had been messing w/ this for awhile trying to figure out best method.  Thanks as always.

                              • 12. Re: Who created the Snapshot
                                cchipman Novice

                                Ok, I took all the changes, added in some of the parts from list_snapshots_v6.ps1, and have the one below.

                                 

                                Creates a list of snapshots, identifies who created them, and emails the owners about them, as well as emailing you a summary.

                                 

                                Next step is to add a custom field to VMs allowing them to be excluded from this reporting.

                                • 13. Re: Who created the Snapshot
                                  ron9999 Enthusiast

                                  Hi.

                                   

                                  This script is very helpful for me but i have a little problem with the creator information. We have VMs who have 2 days old snapshots and the script shows under "Created by" Unknown Creator. Has someone an idea why this information isn't shown there?

                                   

                                  Thanks for help

                                   

                                  ron999

                                  • 14. Re: Who created the Snapshot
                                    BKeadle Novice

                                    Very cool.  I've spent most of the day searching/trying scripts to do this, and yours is the best, and *almost* perfect for what I'm looking for:

                                     

                                    - would it be easy enough to add the snapshot size to the email and summary?

                                    - if the snapshot owner is not determined (returns "unknown owner"), do I understand correctly that you attempt to find that  information in the VC task list?

                                    - if the owner is determined, how is the email address determined from DOMAIN\Owner?  Would it be possible to extract Owner and append the email domain name, e.g.  from DOMAIN\Owner  => Owner@mydomain.com?

                                     

                                     

                                    Did you ever complete the "next step" you mention for exclude VMs from the report?

                                    1 2 3 Previous Next