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)
I think there is an easier way (although part of it is similar to what you have been doing).
$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
I think there is an easier way (although part of it is similar to what you have been doing).
$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
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
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.
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
You are right, the events are missing.
I never thought the machine would be setup this way.
Thank you for your help.
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.