VMware Cloud Community
PederVMikkelsen
Contributor
Contributor
Jump to solution

Script to delete vms that are x days old on a test server

Hi

I am new to PowerCLI and are trying to create a script to delete VMs older than a day (to cleanup on a testserver).

My plan was to find some code that did something similar and see if I could redo it to fit my purpose.

I have been trying to merge these 2 scripts and have been failing for a couple of days:

Create a list of candidates for deletion: Get Snapshots older than X Days – PowerCLI | VMMaster

Delete the VMs: Script for reporting and removing VMs older than 2 weeks.

Connect-viserver -Server viserver

function Get-VMCreationTimes {

   $vms = get-vm -Datastore datastore-9

   $vmevts = @()

   $vmevt = new-object PSObject

   foreach ($vm in $vms) {

#

#Progress bar:

#

      $foundString = "Found: "+$vmevt.name+"   "+$vmevt.createdTime

      $searchString = "Searching: "+$vm.name

      $percentComplete = $vmevts.count / $vms.count * 100

      write-progress -activity $foundString -status $searchString -percentcomplete $percentComplete

      $evt = get-vievent $vm | sort createdTime | select -first 1

      $vmevt = new-object PSObject

      $vmevt | add-member -type NoteProperty -Name createdTime -Value $evt.createdTime

      $vmevt | add-member -type NoteProperty -Name name -Value $vm.name

        

      $vmevts += $vmevt   

   }

   $vmevts | sort createdTime

}

$deletioncandidates = Get-VMCreationTimes | Where {$evt.CreatedTime -lt (Get-Date).AddDays(-1)} | Select-Object Name

Stop-VM -VM $deletioncandidates -Confirm:$false -whatif

But this gives me this message:

Stop-VM : Cannot bind parameter 'VM'. Cannot convert the "" value of type "System.Management.Automation.PSCustomObject" to type "VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine".

At line:29 char:13

+ Stop-VM -VM $deletioncandidates -Confirm:$false -whatif

+             ~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Stop-VM], ParameterBindingException

    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomation.ViCore.Cmdlets.Commands.StopVM

start-sleep 30

$vms = @{}

Get-VM | where {$_.PowerState -eq "PoweredOff"} | % {$vms.Add($_.Name, $_)}

Get-VIEvent -Start (Get-Date).AddDays(-1) -Entity $vms.Values -MaxSamples ([int]::MaxValue) | where {$_ -is [VMware.Vim.VmPoweredOffEvent]} |

  Sort-Object -Property CreatedTime -Unique | % {

  $vms.Remove($_.VM.Name)

}

Remove-VM -VM $vms.Values -DeletePermanently -Confirm:$false -WhatIf

But this gives me this message

Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: 'Windows2012'  Key being added: 'Windows2012'"

At line:3 char:54

+ Get-VM | where {$_.PowerState -eq "PoweredOff"} | % {$vms.Add($_.Name, $_)}

+                                                      ~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : ArgumentException

Can anybody figure out what i am doing wrong?

(or point me in the direction of a script that works)

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

I think there is an easier way (although part of it is similar to what you have been doing).

  • get all the VMCreatedEvent from the last 8 days
  • store the names of those VMs in an array
  • remove duplicates in the array with the Sort-Object -Unique
  • get all VMs and let only the ones that are not in the array get through
  • remove the VMs that came through the Where-clause

$vmNew = @()

$vm = Get-VM

Get-VIEvent -Start (Get-Date).AddDays(-8) -Entity $vm -MaxSamples ([int]::MaxValue) |

   where {$_ -is [VMware.Vim.VmCreatedEvent]} |

   ForEach-Object -Process {

   $vmNew += $_.VM.Name

}

$vmNew = $vmNew | Sort-Object -Unique


$vm | where {$vmNew -notcontains $_.Name} |

   Remove-VM -DeletePermanently -Confirm:$false


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

View solution in original post

0 Kudos
5 Replies
LucD
Leadership
Leadership
Jump to solution

I think there is an easier way (although part of it is similar to what you have been doing).

  • get all the VMCreatedEvent from the last 8 days
  • store the names of those VMs in an array
  • remove duplicates in the array with the Sort-Object -Unique
  • get all VMs and let only the ones that are not in the array get through
  • remove the VMs that came through the Where-clause

$vmNew = @()

$vm = Get-VM

Get-VIEvent -Start (Get-Date).AddDays(-8) -Entity $vm -MaxSamples ([int]::MaxValue) |

   where {$_ -is [VMware.Vim.VmCreatedEvent]} |

   ForEach-Object -Process {

   $vmNew += $_.VM.Name

}

$vmNew = $vmNew | Sort-Object -Unique


$vm | where {$vmNew -notcontains $_.Name} |

   Remove-VM -DeletePermanently -Confirm:$false


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

0 Kudos
PederVMikkelsen
Contributor
Contributor
Jump to solution

Thank you LucD.

Your script catch all the machines on the host.

At the moment the server only have VMs created today and yesterday, and todays machines also got included when i ran the script with -whatif.

When i ran the script i modified this part:

Get-VIEvent -Start (Get-Date).AddDays(-1)

and this part:

Get-VM -Datastore datastore-9

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You are capturing the events I assume?

You are connected to a vCenter, and not an ESXi node.

Check if the following lists anything at all.

$vm = Get-VM

Get-VIEvent -Start (Get-Date).AddDays(-1) -Entity $vm -MaxSamples ([int]::MaxValue) |

   where {$_ -is [VMware.Vim.VmCreatedEvent]}


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

0 Kudos
PederVMikkelsen
Contributor
Contributor
Jump to solution

You are right, the events are missing.

I never thought the machine would be setup this way.

Thank you for your help.

0 Kudos
PederVMikkelsen
Contributor
Contributor
Jump to solution

I ended up with another kind of solution, from this thread:

Need a script to reboot VM if uptime is more than 1 days

Where time since boot were used:

Connect-viserver -Server viserver

Get-VM -Datastore datastore | Where-Object {($_.ExtensionData.RunTime.BootTime -lt (get-date).AddDays(-1)) -and ($_.PowerState -eq "PoweredOn")} | `

Remove-VM -Confirm:$False -DeletePermanently

Thank you for your help LucD.

0 Kudos