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()
}
}
}
HI Lucd,
I did run the script after removing the quotes around the string but still same error. Script attached for you ref.
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
Type Value
is it possible to modify attached script.
Thanks
vmk
There should be quotes around the full filename, as I mentioned in Re: Disk consolidation script -- Need help testing
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD,
I tried the script suggested but it keeps showing in log.
11/8/2019 12:55:32 PM : Cannot connect to $vCenter
11/8/2019 12:55:36 PM : Cannot connect to $vCenter
11/8/2019 12:58:09 PM : Cannot connect to $vCenter
11/8/2019 12:58:13 PM : Cannot connect to $vCenter
11/8/2019 1:05:20 PM : Cannot connect to $vCenter
11/8/2019 1:05:24 PM : Cannot connect to $vCenter
11/8/2019 1:06:58 PM : Cannot connect to $vCente
i got prompted for vcenter credential and i entred the credential
Thanks
vmk
Did you initialise the $vcenters variable somewhere in your script?
It should contain the names of the vCenters for which you want to consolidate the VM disks.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, like this
$vCenters = @('XXXX', 'YYYY')
replaced - $vCenters = @('my vc', )
Do you really have that comma after the 1st VC name?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LuCd,
No comma after VC. Right now only one VC, i'm trying to connect.
Thanks
vmk
LucD,
In log still shows cannot connect vcenter but in console output
Cannot compare "VM00M967" because it is not IComparable.
At D:\vmk\consolidate-Disk2.ps1:78 char:7
+ if ($VMsNeedingConsolidation -gt 0){
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NotIcomparable
Thanks
vmk
I don't see that line in the last script you attached.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I have vcenter ip address, might that is causing issue but np difference. Attaching entire script
$vCenters = $vCenters = @('10.x.x.78')
$logpath = "$env:D\vmk\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"
You need to use the Count property of you want to test like that
$logpath = "$env:D\vmk\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.Count -gt 0){
Write-Log "VMs needing consolidation: $VMsNeedingConsolidation"
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thank you, LucD. It worked this time, but it only generated output saying that the VM's consolidation needed in VM_consolidation.log file. I'm looking to automate the VM consolidation and i also observed while using the first script that the disk consolidation fails due to lock on file. Can it be mitigated ?
Thanks
vmk
Hi LucD,
Can the VM disk consolidation be initiated from this script ? Right now, it only recommend the VM disk consolidation.
Thanks
vmk
Sure, call the ConsolidateVMDisks method on the VirtualMachine.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference