VMware Cloud Community
JLogan2016
Enthusiast
Enthusiast
Jump to solution

Deleting snapshots with wait

I have a script that deletes snapshots throughout several vCenter environments. The number of snapshots has grown to ~500 every week due to the size of the overall environment. I am beginning by gathering a list of any snapshots older than x days, excluding some that have special wording in the description. This gives me a csv that has the VM name, the vCenter, the snapshot name, creation date, description, server owner (VM tag), and SizeMB. I then sort by date so in the case of a VM with multiple snapshots (rare) I am deleting newest first, and then doing something like this:

Get-VM -Name $VM.Name |

    Get-Snapshot -Name $VM.Snap |

        Remove-Snapshot -Confirm: $false

The script works, but I find that there is no method for waiting until one is done before moving on to the next. So what happens, if I have 500 servers that have snapshots, is they all attempt to kick off one after another. I could do a simple sleep, but with the differing size of snapshots that is a crap shoot. I have also tried something like this:

$t = Get-VM -Name $VM.Name | Get-Snapshot -Name $VM.Snap | Remove-Snapshot -Confirm: $false

While('Running','Queued' -contains $t.State) {

    Start-Sleep 5

    $t = Get-Task -Id $t.Id

}

But it doesn't seem to work, it still runs them one after another. The net result is I usually have to make a second pass to clean up any snapshots I missed. I am just curious if there is a better way.

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

You can run the removal of the snapshots in the background with the RunAsync switch.
Then with Get-Task check how many there are running.

If that number is higher than your set maximum, just wait till one or more of the background jobs finishes.

$maxJobs = 5

Get-VM | Get-Snapshot |

   ForEach-Object -Process {

   Remove-Snapshot -Snapshot $_ -Confirm:$false -RunAsync

   $current = Get-Task | where {$_.Name -eq 'RemoveSnapshot_Task' -and 'Running','Queued' -contains $_.State}

   while ($current.count -gt $maxJobs) {

      sleep 5

      $current = Get-Task | where {$_.Name -eq 'RemoveSnapshot_Task' -and 'Running','Queued' -contains $_.State}

   }

}


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

View solution in original post

12 Replies
a_p_
Leadership
Leadership
Jump to solution

Please see whether Wait-Task cmdlet is what you are looking for.

André

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can run the removal of the snapshots in the background with the RunAsync switch.
Then with Get-Task check how many there are running.

If that number is higher than your set maximum, just wait till one or more of the background jobs finishes.

$maxJobs = 5

Get-VM | Get-Snapshot |

   ForEach-Object -Process {

   Remove-Snapshot -Snapshot $_ -Confirm:$false -RunAsync

   $current = Get-Task | where {$_.Name -eq 'RemoveSnapshot_Task' -and 'Running','Queued' -contains $_.State}

   while ($current.count -gt $maxJobs) {

      sleep 5

      $current = Get-Task | where {$_.Name -eq 'RemoveSnapshot_Task' -and 'Running','Queued' -contains $_.State}

   }

}


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

JLogan2016
Enthusiast
Enthusiast
Jump to solution

This worked perfectly, thanks.

Reply
0 Kudos
scorpion20
Contributor
Contributor
Jump to solution

Hi LucD,

Thanks for the resolution to the query. I have a bit different query though. I want to delete all snapshot's 7 days older from a particular VC (to which I am connected to) but want to leave snapshot of one or few VM untouched as those are still required. How can we achieve this?

As of now I am using the below command to delete all the snapshot from the VC.

Get-VM | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-7)} | Remove-Snapshot -RunAsync -confirm:$false | Export-Csv C:\tesmp\snapshot.log

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

How do you select the VMs for which the snapshots do not need to be deleted?

Is that based on the name or something else?


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

Reply
0 Kudos
scorpion20
Contributor
Contributor
Jump to solution

Hi LucD,

Yes, need to select the VM with it's name that needs to be excluded from the snapshot deletion.

If we select it with the description of the Snapshot in case it's mentioned there "Do not delete the snapshot" that could help us giving the name of the VM for exclusion and will exclude all VM's where the description says "Do not delete the snapshot".

Would be good to have command for both the possibilities though :-). Thank you.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can include multiple Where-clauses in the pipeline.

Get-VM | where{$_.Name -notlike "Exclude*" } |

Get-Snapshot | where {$_.Description -notlike "*Do not delete*"} |

ForEach-Object -Process {

   Remove-Snapshot -Snapshot $_ -Confirm:$false -RunAsync

   $current = Get-Task | where {$_.Name -eq 'RemoveSnapshot_Task' -and 'Running','Queued' -contains $_.State}

   while ($current.count -gt $maxJobs) {

      sleep 5

      $current = Get-Task | where {$_.Name -eq 'RemoveSnapshot_Task' -and 'Running','Queued' -contains $_.State}

   }

}


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

scorpion20
Contributor
Contributor
Jump to solution

Thank you very much LucD. I will try to run this command and see the result.

Last query - Should there be a file from which this command can pick the name of the VM from that needs to be excluded from snapshot removal process?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The script above doesn't use an external file, but you can use for example an Import-Csv to pick up the names of the VMs to look at.


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

vcertify
Contributor
Contributor
Jump to solution

Hi LucD,

The above script works very well but when I given the VM list from the file, the get-task is getting all the tasks other than we have initiated for remove. And I need to get more details to be capture as when the remove snapshot task started time for a VM and the completion time with who initiated the task.

Please help the above.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Do you mean you are not only getting the Remove-Snapshot tasks, but also other tasks that are running or queued in the vCenter?

If yes, you can use the Id parameter on the Get-Task cmdlet to specifically specify which tasks you want to retrieve.


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

Reply
0 Kudos
vcertify
Contributor
Contributor
Jump to solution

Yes. I tried to use the id parameter. Facing an issue with retrieving output. Could you please share a small example with id and display output as vmname, start time, finish time and initiated by details from the task once the state is succes.

Reply
0 Kudos