Marco_2_G
Contributor
Contributor

Listing all snapshots per vm using get-view

Jump to solution

Hi everyone

I am in the process of developing a script to cleanup after our backup software.

One of the tasks will be to find snapshots of a certain name and remove them. This is pretty straight forward.

However, since we have several vCenters linked and since, when a backup job dies, there can be quite a number of of snapshots to work through AND people sometimes don't notice for a few days that something was amiss, I would like to optimise this in a few key aspects:

When a vm has nothing but backup snaps to be deleted, I would like to tell it to delete them all at once, which should be way easier than doing one at a time.

To do that, I need to check all snapshots per vm and group the vms and or their snapshots into either the "delete all" category or the "delete individually" category.

I would like to use views to drill down the data and only work with objects when it is clear what has to be done where. For this I need a way to find all snapshots of a certain vm. I have no trouble finding all vms with snapshots but I have so far only found a way to find the active snapshot and the root snapshot.

I can of course traverse the snapshot chains in code but I find this rather inelegant...

So in short: Is there a quick way in get-view to find all snapshots belonging to a vm? Or is there a much easier way to do what I want in the first place?

Regards,

Marco

Tags (2)
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

Ok, that requires a few more lines of code.

Try like this

function Get-SnapChild{

   param(

  [VMware.Vim.VirtualMachineSnapshotTree]$Snapshot

   )


   process{

   $snapshot.Name

   if($Snapshot.ChildSnapshotList.Count -gt 0){

   $Snapshot.ChildSnapshotList | %{

   Get-SnapChild -Snapshot $_

  }

  }

  }

}


foreach($vm in Get-View -ViewType VirtualMachine -Property Name,Snapshot -Filter @{'Snapshot' = ''}){

   $vm.Snapshot.RootSnapshotList | %{

   Get-SnapChild -Snapshot $_ | Select @{N='VM';E={$vm.name}},@{N='Snapshot';E={$_}}

  }

}


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

View solution in original post

15 Replies
LucD
Leadership
Leadership

The fastest way to find VMs with snapshot is something like this

Get-View -ViewType VirtualMachine -Property Name,Snapshot -Filter @{Snapshot = ''} |

select Name


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

Marco_2_G
Contributor
Contributor

Hi LucD

That gives me a list of all the vms that have snapshots.

I need to have a list of all the snapshots for each of the vms returned.

Regards,

Marco

0 Kudos
LucD
Leadership
Leadership

Ok, that requires a few more lines of code.

Try like this

function Get-SnapChild{

   param(

  [VMware.Vim.VirtualMachineSnapshotTree]$Snapshot

   )


   process{

   $snapshot.Name

   if($Snapshot.ChildSnapshotList.Count -gt 0){

   $Snapshot.ChildSnapshotList | %{

   Get-SnapChild -Snapshot $_

  }

  }

  }

}


foreach($vm in Get-View -ViewType VirtualMachine -Property Name,Snapshot -Filter @{'Snapshot' = ''}){

   $vm.Snapshot.RootSnapshotList | %{

   Get-SnapChild -Snapshot $_ | Select @{N='VM';E={$vm.name}},@{N='Snapshot';E={$_}}

  }

}


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

View solution in original post

Marco_2_G
Contributor
Contributor

Thank you, this works. I have no idea why it works but that's more due to my being a novice when it comes to coding and powershell in particular :smileygrin:.

I'll be staring at this code in total incomprehension some more now.

0 Kudos
LucD
Leadership
Leadership

Lol!


To minimise the staring, some annotations:

  • To filter the VMs that have a snapshot, the Get-View Filter parameter checks if the Snapshot property is $null or not. This translates to checking for an empty string, which is Get-View/RegEx speak for -not $null
  • On a VM there is the RootSnapShotList which points to the snapshot that make up the roots of all snapshot trees. For each root snapshot, we recursively traverse the snapshot tree via the Get-SnapChild function
  • In the Get-SnapChild function we avoid the issue with a Foreach loop that runs once, even with an empty array, by testing for the number of entries in the ChildSnapshotList array
  • when a child snapshot has children, the function calls itself again. This is the recursive part


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

0 Kudos
Marco_2_G
Contributor
Contributor

I may now understand your code. If you have the time I'd live for you to verify this:

Am I correct in assuming that the process block is more good coding style than strictly necessary?

Anyway as far as I can tell, you take the rootsnapshotlist which has an attribute childsnapshotlist (THIS is exactly the piece of linking information I was unable to find so far) and if it has more than 0 entries you traverse through those snapshots by calling your function inside itself.

The function then returns everything it has found through the first line after process{ and all you have to do is clean the output up a bit through the select statement.

Am I understanding this somewhat correctly? Smiley Happy

And thanks again for the help.

0 Kudos
Marco_2_G
Contributor
Contributor

Oh, you were faster than I was Smiley Happy

Thanks, I believe I've got it!

You're an invaluable source of info... but I'm sure I'm not telling you anything new.

0 Kudos
LucD
Leadership
Leadership

Correct, the function could be done without the Process block
Strictly speaking Begin-Process-End blocks are when objects are passed over the pipeline to the function.

The function just returns the names of all the snapshots it finds.

The Select is to combine that info with the VM name.


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

0 Kudos
Sudarshan_Bhart
Enthusiast
Enthusiast
Get-View -ViewType VirtualMachine -Filter @{"snapshot" = ""} -Property Name | % {Get-VM -id $_.MoRef | Get-Snapshot}
0 Kudos
ndnguyen
Contributor
Contributor
How would i add Date created, created by and description? 
0 Kudos
LucD
Leadership
Leadership

Like this.
For the user that created the snapshot, you will have to search the events.

See for example Re: snapshot who created it

function Get-SnapChild

{

   param(

   [VMware.Vim.VirtualMachineSnapshotTree]$Snapshot

   )


   process

   {

   $snapshot | Select Name, Description, CreateTime

   if ($Snapshot.ChildSnapshotList.Count -gt 0)

   {

   $Snapshot.ChildSnapshotList | % {

   Get-SnapChild -Snapshot $_

   }

   }

   }

}


foreach ($vm in Get-View -ViewType VirtualMachine -Property Name, Snapshot -Filter @{'Snapshot' = '' })

{

   $vm.Snapshot.RootSnapshotList | % {

   Get-SnapChild -Snapshot $_ |

  Select @{N = 'VM'; E = { $vm.name } },

   @{N = 'Snapshot'; E = { $_.Name } },

   @{N = 'Description'; E = { $_.Description } },

   @{N = 'CReated'; E = { $_.CreateTime } }

   }

}


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

ndnguyen
Contributor
Contributor
Thank you very much for the quick responce. Much appriciated. 
0 Kudos
RDGR
Contributor
Contributor
This function works perfectly.  On a related subject, we require all scripts to be signed.  It seems that a function is basically a script in disguise.  Is there a way to require functions to be signed or to restrict their use by the 400 users on our network?
0 Kudos
LucD
Leadership
Leadership

Yes, set the execution policy, by a command in for example a profile for All Usersa

Set-ExecutionPolicy -ExecutionPolicy AllSigned

Or do it in a GPO.


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

0 Kudos
David2021
Contributor
Contributor

Hello,

regarding this script, I have 4 points that I request a help:

1/ How can I catch the creator/author of the snapshot with this script?

I try this but without success:

@{N = 'Creator'; E= {

$event = Get-VIEvent | where {$_ -is [VMware.Vim.TaskEvent] -and $_.Info.descriptionId -eq "VirtualMachine.createSnapshot"} | Select Username

$event.Info.Reason.userName} }

2/ I have a difference with the time of 1 hour between the result of this part of the script  {N = 'Created'; E = { $_.CreateTime } }, it's 1 hour less if I compare with the time display in VMware web management. How can I display the correct time in the scipt result?

3/ How can I display the VMhost where the vm is located in the script result ?

4/ How can I output in CSV file?

 

regards

0 Kudos