hguthrie
Contributor
Contributor

Disk consolidation script -- Need help testing

Jump to solution

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:

# Overview: Check vCenter(s) for any VMs with disks needing consolidation. If it finds any, attempt to consolidate them.

# 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()

  }

  }

}

Tags (2)
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

If you running this against a big environment, I would go for a Get-View approach.

Something like this

foreach ($vCenter in $vCenters) {

   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.

foreach ($vCenter in $vCenters) {

   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

View solution in original post

33 Replies
LucD
Leadership
Leadership

If you running this against a big environment, I would go for a Get-View approach.

Something like this

foreach ($vCenter in $vCenters) {

   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.

foreach ($vCenter in $vCenters) {

   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

View solution in original post

hguthrie
Contributor
Contributor

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

0 Kudos
LucD
Leadership
Leadership

My bad, try replacing that line with

Write-Log "Needs consolidation $($_.Name)"


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

prashantpote
Contributor
Contributor
Please share above disk consolidation script for single standalone host.
0 Kudos
hguthrie
Contributor
Contributor

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

0 Kudos
vmk2014
Expert
Expert

LucD,

Which line, i need to replace in the above script. Please help. I'm trying to test the script.

Thanks

vmk

0 Kudos
vmk2014
Expert
Expert

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

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
vmk2014
Expert
Expert

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

0 Kudos
LucD
Leadership
Leadership

Did you include the following lines at the beginning of your script?

function Write-Log {

    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

0 Kudos
vmk2014
Expert
Expert

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

0 Kudos
LucD
Leadership
Leadership

You have to set the variable $logpath to a valid file before calling Write-Log.


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

0 Kudos
vmk2014
Expert
Expert

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

  }

0 Kudos
LucD
Leadership
Leadership

Yes, and it should point to valid filename

$logPaths = 'D:\disk\report.txt'


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

0 Kudos
vmk2014
Expert
Expert

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

0 Kudos
LucD
Leadership
Leadership

My bad, there should be quotes around the filename


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

0 Kudos
vmk2014
Expert
Expert

You mean it should be D:\vmk\"report.txt"  ?

Also, report it will be output file ?

Thanks

vmk

0 Kudos
vmk2014
Expert
Expert

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

0 Kudos
LucD
Leadership
Leadership

No, quotes around the complete string.
See my updated answer earlier.


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

0 Kudos