Recently we encountered an issue where a team member mistakenly did not delete a snapshot following some maintenance on a VM. Long story short, the snapshot ballooned into more than 2TB and took many hours to consolidate. Aside from the obvious of "don't forget to delete snapshots", we're looking for ideas on ways to prevent this from happening.
One idea that our manager wanted us to pursue was to have a script which would routinely scan for VMs showing the "Disk Consolidation Needed" warning. It would then alert us, and start the consolidation process. This wasn't complicated to write, but I'm having trouble getting a VM into the "Disk Consolidation Needed" state to test it.
Also, any other ideas on better ways to handle this are certainly welcome.
Script code:
# Notes: Since we don't specify a credential pair to connect with, it will attempt to connect as the current script environment's user.
# Load PowerCLI Module
Import-Module -Name VMware.VimAutomation.Core
##### Variables #####
$vCenters = @('XXXX', 'YYYY')
$logpath = "$env:SystemDrive\Windows\Temp\VM_Consolidation.log"
############
<#
.SYNOPSIS
Logs messages to a file
.DESCRIPTION
Receives messages and logs them to an output file.
.PARAMETER msg
The message to be written
.EXAMPLE
Write-Log 'Write this to the logfile'
.NOTES
Requires $logfile to be configured as the path to the output log file
#>
function Write-Log {
param($msg)
"$(Get-Date -Format G) : $msg" | Out-File -FilePath $logpath -Append -Force
}
foreach ($vCenter in $vCenters) {
try {
Connect-VIServer $vCenter -ErrorAction Stop
} catch {
Write-Log 'Cannot connect to $vCenter'
}
}
if ($Global:DefaultVIServers.Count -gt 0) {
$VMsNeedingConsolidation = Get-VM | Where-Object {$_.ExtensionData.Runtime.consolidationNeeded}
if ($VMsNeedingConsolidation -gt 0){
Write-Log "VMs needing consolidation: $VMsNeedingConsolidation"
$VMsNeedingConsolidation | ForEach-Object {
Write-Log "Needs consolidation $_ "
$_.ExtensionData.ConsolidateVMDisks_Task()
}
}
}
If you running this against a big environment, I would go for a Get-View approach.
Something like this
try {
Connect-VIServer $vCenter -ErrorAction Stop
}
catch {
Write-Log 'Cannot connect to $vCenter'
}
}
if ($Global:DefaultVIServers) {
Get-View -ViewType VirtualMachine -Property Name, Runtime.ConsolidationNeeded -Filter @{'Runtime.ConsolidationNeeded' = 'True' } |
ForEach-Object -Process {
Write-Log "Needs consolidation $_ "
$_.ConsolidateVMDisks_Task()
}
}
Unfortunately I don't know if it is even possible to force a VM in "Disk Consolidation Needed" situation.
But for testing, you reverse the filter, and you always run the consolidation task against any VM, even if consolidation is not needed.
The following, reverses the filter, selects the first 5 VMs and runs the consolidation task.
try {
Connect-VIServer $vCenter -ErrorAction Stop
}
catch {
Write-Log 'Cannot connect to $vCenter'
}
}
if ($Global:DefaultVIServers) {
Get-View -ViewType VirtualMachine -Property Name, Runtime.ConsolidationNeeded -Filter @{'Runtime.ConsolidationNeeded' = 'False' } |
Select-Object -First 5 |
ForEach-Object -Process {
Write-Log "Needs consolidation $_ "
$_.ConsolidateVMDisks_Task()
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
If you running this against a big environment, I would go for a Get-View approach.
Something like this
try {
Connect-VIServer $vCenter -ErrorAction Stop
}
catch {
Write-Log 'Cannot connect to $vCenter'
}
}
if ($Global:DefaultVIServers) {
Get-View -ViewType VirtualMachine -Property Name, Runtime.ConsolidationNeeded -Filter @{'Runtime.ConsolidationNeeded' = 'True' } |
ForEach-Object -Process {
Write-Log "Needs consolidation $_ "
$_.ConsolidateVMDisks_Task()
}
}
Unfortunately I don't know if it is even possible to force a VM in "Disk Consolidation Needed" situation.
But for testing, you reverse the filter, and you always run the consolidation task against any VM, even if consolidation is not needed.
The following, reverses the filter, selects the first 5 VMs and runs the consolidation task.
try {
Connect-VIServer $vCenter -ErrorAction Stop
}
catch {
Write-Log 'Cannot connect to $vCenter'
}
}
if ($Global:DefaultVIServers) {
Get-View -ViewType VirtualMachine -Property Name, Runtime.ConsolidationNeeded -Filter @{'Runtime.ConsolidationNeeded' = 'False' } |
Select-Object -First 5 |
ForEach-Object -Process {
Write-Log "Needs consolidation $_ "
$_.ConsolidateVMDisks_Task()
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD,
Thanks for the quick reply! Good suggestion regarding Get-View. Works great!
A minor issue is I can't figure out how to get the name to print properly to the log file.
4/1/2019 2:27:22 PM : Needs consolidation VMware.Vim.VirtualMachine.VMName
My bad, try replacing that line with
Write-Log "Needs consolidation $($_.Name)"
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
prashantpote,
To log in to a single ESXi host, you can simply replace the contents of the $vCenters variable with the hostname/IP address of the host.
You'll probably also need to specify a username/password to the Connect-VIServer command. See here for more details https://code.vmware.com/doc/Connect-VIServer.html
LucD,
Which line, i need to replace in the above script. Please help. I'm trying to test the script.
Thanks
vmk
I'm seeing error.
PS D:\vmk> .\consolidate-Disk.ps1
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Type Value
---- -----
Task task-7846099
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846100
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846101
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846102
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846104
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846105
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846106
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846107
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846108
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846109
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846110
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846111
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846112
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846114
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846115
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846116
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846117
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846118
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846119
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846120
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846121
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846122
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846123
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:22 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846124
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:55 char:4
+ Write-Log "Needs consolidation $($_.Name)"
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Task task-7846126
The original script in this thread contains a function definition for Write-Log, you need to include that part in your script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ok, i tried but it throws an error.
Write-Log : The term 'Write-Log' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:26 char:4
+ Write-Log "Needs consolidation $_ "
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Log:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
thanks
vmk
Did you include the following lines at the beginning of your script?
param($msg)
"$(Get-Date -Format G) : $msg" | Out-File -FilePath $logpath -Append -Force
}
Otherwise attach the script you are using, so I can have a look.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
I have attached the script, which i'm trying to run, but i'm getting error after adding the write-log function.
PS D:\vmk> .\consolidate-Disk.ps1
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At D:\nvmk\consolidate-Disk.ps1:8 char:57
+ ... "$(Get-Date -Format G) : $msg" | Out-File -FilePath $logpath -Append ...
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileComm
and
Type Value
---- -----
Task task-7850873
Thanks
vmk
You have to set the variable $logpath to a valid file before calling Write-Log.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You meant to say something like that
$logPaths = D:\disk
function Write-Log {
param($msg)
"$(Get-Date -Format G) : $msg" | Out-File -FilePath $logpath -Append -Force
}
Yes, and it should point to valid filename
$logPaths = 'D:\disk\report.txt'
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
PS D:\vmk> .\consolidate-Disk.ps1
D:\vmk\report.txt : The term 'D:\vmk\report.txt' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:1 char:13
+ $logPaths = D:\vmk\report.txt
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (D:\vmk\report.txt:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At D:\vmk\consolidate-Disk.ps1:10 char:57
+ ... "$(Get-Date -Format G) : $msg" | Out-File -FilePath $logpath -Append ...
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileCommand
Thanks
vmk
My bad, there should be quotes around the filename
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You mean it should be D:\vmk\"report.txt" ?
Also, report it will be output file ?
Thanks
vmk
LucD,
Tried with quote, but still shows an error.
D:\vmk\report.txt : The term 'D:\vmk\report.txt' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At D:\vmk\consolidate-Disk.ps1:1 char:13
+ $logPaths = D:\vmk\'report.txt'
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (D:\vmk\report.txt:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At D:\vmk\consolidate-Disk.ps1:10 char:57
+ ... "$(Get-Date -Format G) : $msg" | Out-File -FilePath $logpath -Append ...
+
Thanks
vmk
No, quotes around the complete string.
See my updated answer earlier.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference