-
-
Save hansdg1/ea4f1e9248f5dfdbcc5cbb0ecd9ebb4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 5.0 -Modules VMware.VimAutomation.Core | |
<# | |
.SYNOPSIS | |
Check vCenter(s) for any VMs with disks needing consolidation, attempting to consolidate any it finds. | |
.DESCRIPTION | |
Kicks off ConsolidateVMDisks_Tasks for any VirtualMachine objects it finds needing consolidation. Emails a report detailing any it successfully consolidates, has errors with, or excluded due. | |
.NOTES | |
Since we don't specify a credential pair to connect with, it will attempt to connect as the current script environment's user. | |
Due to the current architecture of the code, if the -WhatIf switch is used, the Disconnect-VIServer command will not execute. To workaround this, I added "-WhatIf:$false" to that line. | |
#> | |
[CmdletBinding(SupportsShouldProcess = $true)] | |
Param( | |
# List of VMs to exclude from disk consolidation | |
[string[]] | |
$ExcludedVMs, | |
# Email address the report will be sent to. | |
[ValidateNotNullOrEmpty()] | |
[string[]] | |
$ToAddress, | |
# Email address the report will show as from. | |
[string] | |
$FromAddress | |
) | |
function Write-Log { | |
<# | |
.SYNOPSIS | |
Logs messages to a file | |
.DESCRIPTION | |
Receives messages and logs them to an output file. | |
.EXAMPLE | |
Write-Log -Message "Write this to the log" -Path "C:\Temp\LogFile.log" | |
.NOTES | |
Uses the variable $LogPath as the default value for Path | |
#> | |
[CmdletBinding()] | |
param ( | |
# The message to be written | |
[Parameter(Mandatory = $true)] | |
[string] | |
$Message, | |
# File path of the log file. Default value is $LogPath, if set. | |
[ValidateNotNullOrEmpty()] | |
[string] | |
$Path = $LogPath | |
) | |
begin { | |
$ConfirmPreference = 'None' | |
} | |
process { | |
Write-Verbose $Message | |
Add-Content -Path $Path -Value "[$(Get-Date -Format 'yy:MM:dd-hh:mm:ss')] $Message" | |
} | |
} | |
function Add-EmailBodyContent { | |
<# | |
.SYNOPSIS | |
Generates a formatted text block using a heading and list of child items. | |
.DESCRIPTION | |
The Add-EmailBodyContent cmdlet accepts a SectionHeader and array of ChildItems and uses them to generate a formatted block of text. | |
The SectionHeader is listed on the first line, with each of the ChildItems indented on subsequent lines. | |
.EXAMPLE | |
PS> Add-EmailBodyContent -SectionHeader 'Cars' -ChildItems $('car1','car2','car3') | |
Cars: | |
car1 | |
car2 | |
car3 | |
#> | |
[CmdletBinding()] | |
param ( | |
# The header for the text block. | |
[Parameter(Mandatory)] | |
[string] | |
$SectionHeader, | |
# List of items to appear indented under the SectionHeader | |
[Parameter(Mandatory)] | |
[string[]] | |
$ChildItems | |
) | |
process { | |
Write-Output "$($SectionHeader):`n" | |
foreach ($item in $ChildItems) { | |
Write-Output "`t$($item)`n" | |
} | |
Write-Output "`n" | |
} | |
} | |
function Invoke-DiskConsolidation { | |
<# | |
.SYNOPSIS | |
Start disk consolidation tasks for each VirtualMachine in View | |
.DESCRIPTION | |
Start disk consolidation tasks for each of the VirtualMachine managed objects in View. These tasks are non-blocking and will execute in parallel. | |
.EXAMPLE | |
PS> $TaskList = Invoke-DiskConsolidation -View $view -ExcludedVMs $ExcludedVMs | |
Returns a Hashtable ($TaskList) containing the task objects and VM names | |
.NOTES | |
The tasks created by the ConsolidateVMDisks_Task method are non-blocking, meaning it will not wait for completion before continuing. | |
There is another VirtualMachine method, ConsolidateVMDisks, which waits for the consolidation to complete before continuing. | |
.OUTPUTS | |
[System.Collections.Hashtable] Containing tasks and the VM names | |
#> | |
[CmdletBinding(SupportsShouldProcess = $true)] | |
param ( | |
# List of vSphere View VirtualMachine objects representing the VMs that will have their disks consolidated. | |
[VMware.Vim.ViewBase[]] | |
$View, | |
# List of VMs to exclude from consolidation | |
[string[]] | |
$ExcludedVMs | |
) | |
begin { | |
$View = $View | Where-Object {$_.Name -notin $ExcludedVMs} | |
$TaskList = @{} | |
} | |
process { | |
foreach ($VirtualMachineObj in $View) { | |
Write-Log "Kicking off consolidation for $($VirtualMachineObj.Name)" | |
if ($PSCmdlet.ShouldProcess($VirtualMachineObj.Name)) { | |
$TaskList[(Get-Task -Id $VirtualMachineObj.ConsolidateVMDisks_Task()).Id] = $VirtualMachineObj.Name | |
} | |
} | |
} | |
end { | |
Write-Output $TaskList | |
} | |
} | |
##### Variables ##### | |
$vCentersList = @('vcenter1.example.com', 'vcenter2.example.com') | |
$LogPath = "$env:SystemDrive\Windows\Temp\Disk_Consolidation.log" | |
$ExcludedVMs = @('exclude-this-vm') | |
# Used when determining if consolidation succeeded/failed | |
$TaskList = @{} | |
$SuccessfulVMs = @() | |
$ErrorVMs = @() | |
# Used in report generation | |
$EmailBody = '' | |
##################### | |
foreach ($vCenter in $vCentersList) { | |
try { | |
Connect-VIServer $vCenter -ErrorAction Stop | Out-Null | |
Write-Log "Connected to $($vCenter)" | |
} catch { | |
Write-Log "Error connecting to $($vCenter)" | |
} | |
} | |
if ($Global:DefaultVIServers.Count -gt 0) { | |
$VirtualMachineView = Get-View -ViewType VirtualMachine -Property Name, Runtime.ConsolidationNeeded -Filter @{'Runtime.ConsolidationNeeded' = 'True' } | |
$TaskList = Invoke-DiskConsolidation -View $VirtualMachineView -ExcludedVMs $ExcludedVMs | |
do { | |
foreach ($Task in @($TaskList.Keys)) { | |
switch (Get-Task -Id $Task) { | |
{$_.State -eq 'Success'} { | |
Write-Log "Successfully consolidated $($TaskList.$Task)." | |
$SuccessfulVMs += $TaskList.$Task | |
$TaskList.Remove($Task) | |
} | |
{$_.State -eq 'Error'} { | |
Write-Log "Error consolidating $($TaskList.$Task)." | |
$ErrorVMs += $TaskList.$Task | |
$TaskList.Remove($Task) | |
} | |
{$_.State -eq 'Running'} { | |
Write-Log "Waiting for $($Task) ($($TaskList.$Task)) to complete." | |
Start-Sleep -Seconds 5 | |
} | |
Default { Start-Sleep -Seconds 5 } | |
} | |
} | |
} while ($TaskList.Count -gt 0) | |
if ($SuccessfulVMs -gt 0) { | |
$EmailBody += Add-EmailBodyContent -SectionHeader "Successfully Consolidated" -ChildItems $SuccessfulVMs | |
} | |
if ($ErrorVMs -gt 0) { | |
$EmailBody += Add-EmailBodyContent -SectionHeader "Error Consolidating" -ChildItems $ErrorVMs | |
} | |
if ($ExcludedVMs -gt 0) { | |
$EmailBody += Add-EmailBodyContent -SectionHeader "Excluded From Consolidation" -ChildItems $ExcludedVMs | |
} | |
# If $EmailBody is still empty, include a warning | |
if ($EmailBody -eq '') { | |
$EmailBody += Add-EmailBodyContent -SectionHeader "Warning, no VMs processed. Check the logs." -ChildItems "$($LogPath)" | |
} | |
Write-Log -Message "Sending email report. From:$($FromAddress) To:$($ToAddress)" | |
Send-MailMessage -From $FromAddress -To $ToAddress -SmtpServer 'mailserver.example.com' -Subject 'Automated Disk Consolidation Results' -Body $EmailBody | |
Disconnect-VIServer * -Confirm:$false -WhatIf:$false | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment