Skip to content

Instantly share code, notes, and snippets.

@basroovers
Last active June 18, 2019 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save basroovers/2c1cdf9298c2a26ad633e008d95abf46 to your computer and use it in GitHub Desktop.
Save basroovers/2c1cdf9298c2a26ad633e008d95abf46 to your computer and use it in GitHub Desktop.
function Start-VMStorageOptimization {
<#
.SYNOPSIS
Function to optimize storage usage on CSV volumes by using Hyper-V Live Storage Migration.
.DESCRIPTION
If you use dynamic virtual disks with VMs, you may need to monitor free space on your CSV volumes.
This script moves virtual machines into different CSV volumes by using Hyper-V Live Storage Migration.
Note: run this as Administrator
.PARAMETER WhatIf
Display what would happen if you would run the function with given parameters.
.PARAMETER Confirm
Prompts for confirmation for each operation. Allow user to specify Yes/No to all option to stop prompting.
.EXAMPLE
Start-VMStorageOptimization
.EXAMPLE
Start-VMStorageOptimization -AllowPT
.INPUTS
None
.OUTPUTS
None
.NOTES
Author: Yusuf Ozturk (Small updates by Bas Roovers)
Website: http://www.yusufozturk.info
Email: ysfozy@gmail.com
Date created: 08-June-2014
Last modified: 06-June-2019
Version: 1.5
.LINK
http://www.yusufozturk.info
http://twitter.com/yusufozturk
#>
[CmdletBinding(SupportsShouldProcess = $true)]
param (
# Allow Passthrough Disks
[Parameter(
Mandatory = $false,
HelpMessage = 'Allow Passthrough Disks')]
[switch]$AllowPT = $false,
# Debug Mode
[Parameter(
Mandatory = $false,
HelpMessage = 'Debug Mode')]
[switch]$DebugMode = $false
)
# Enable Debug Mode
if ($DebugMode)
{
$DebugPreference = "Continue"
}
else
{
$ErrorActionPreference = "silentlycontinue"
}
# Informational Output
Write-Host " "
Write-Host "------------------------------------------" -ForegroundColor Green
Write-Host " Hyper-V Storage Optimization Script v1.4 " -ForegroundColor Green
Write-Host "------------------------------------------" -ForegroundColor Green
Write-Host " "
# Set Storage Status
$StorageStatus = $True
while ($StorageStatus -eq $True)
{
# Get Worst CSV Volume
$WorstVolume = ((Get-ClusterSharedVolume | Select -ExpandProperty SharedVolumeInfo | Select @{label="Name";expression={(($_.FriendlyVolumeName).Split("\"))[-1]}},@{label="FreeSpace";expression={($_ | Select -Expand Partition).FreeSpace}} | Sort FreeSpace -Descending)[-1])
# Worst CSV Volume Information
$WorstVolumeName = $WorstVolume.Name
$WorstVolumeFreeSpace = $WorstVolume.FreeSpace
# Get Best CSV Volume
$BestVolume = ((Get-ClusterSharedVolume | Select -ExpandProperty SharedVolumeInfo | Select @{label="Name";expression={(($_.FriendlyVolumeName).Split("\"))[-1]}},@{label="FreeSpace";expression={($_ | Select -Expand Partition).FreeSpace}} | Sort FreeSpace -Descending)[0])
# Best CSV Volume Information
$BestVolumeName = $BestVolume.Name
$BestVolumeFreeSpace = $BestVolume.FreeSpace
# Calculate Space Gap
[int64]$SpaceGap = [math]::round((([int64]$BestVolumeFreeSpace - [int64]$WorstVolumeFreeSpace) / 1GB), 0)
if ($SpaceGap -lt "100")
{
# Informational Output
Write-Host "Storage is already optimized." -ForegroundColor Green
Write-Host " "
# Set Storage Status
$StorageStatus = $False
}
else
{
# VM Reports
$VMReports = $Null
# Get Cluster Nodes
$ClusterNodes = Get-Cluster | Get-ClusterNode
# Informational Output
Write-Host "Measuring VMs to find the most suitable virtual machine for the migration.. Please wait.." -ForegroundColor Cyan
Write-Host " "
if ($AllowPT)
{
# Enable Resource Metering
$EnableMetering = Get-VM -ComputerName $ClusterNodes | Where ConfigurationLocation -like "C:\ClusterStorage\$WorstVolumeName\*" | Enable-VMResourceMetering
# Get Resource Usage
$VMReports = Get-VM -ComputerName $ClusterNodes | Where ConfigurationLocation -like "C:\ClusterStorage\$WorstVolumeName\*" | Measure-VM
}
else
{
# Enable Resource Metering
$EnableMetering = Get-VM -ComputerName $ClusterNodes | Where ConfigurationLocation -like "C:\ClusterStorage\$WorstVolumeName\*" | Where {(($_ | Select -Expand HardDrives).Path -notlike "Disk*") -and (($_ | Select -expand FibreChannelHostBusAdapters) -eq $Null)} | Enable-VMResourceMetering
# Get Resource Usage
$VMReports = Get-VM -ComputerName $ClusterNodes | Where ConfigurationLocation -like "C:\ClusterStorage\$WorstVolumeName\*" | Where {(($_ | Select -Expand HardDrives).Path -notlike "Disk*") -and (($_ | Select -expand FibreChannelHostBusAdapters) -eq $Null)} | Measure-VM
}
# Calculate Space Gap Average
[int64]$SpaceGapAverage = [math]::round(([int64]$SpaceGap / 2), 0)
[int64]$SpaceGapAverageMb = [int64]$SpaceGapAverage * 1024
# Find Most Suitable VM
$BestVM = ($VMReports | Where TotalDisk -lt $SpaceGapAverageMb | Sort TotalDisk -Descending)[0]
if ($BestVM)
{
# Best VM Information
$BestVMName = $BestVM.VMName
$BestVMHost = $BestVM.ComputerName
# Informational Output
Write-Host "Moving $BestVMName from $WorstVolumeName to $BestVolumeName by using Hyper-V Storage Live Migration.." -ForegroundColor Yellow
# Move Virtual Machine
Move-VMStorage -ComputerName "$BestVMHost" -VMName "$BestVMName" -DestinationStoragePath "C:\ClusterStorage\$BestVolumeName\$BestVMName"
# Informational Output
Write-Host "Done." -ForegroundColor Green
Write-Host " "
}
else
{
# Informational Output
Write-Host "No suitable VM is found.. $WorstVolumeName contains VMs with large spaces." -ForegroundColor Red
Write-Host " "
# Set Storage Status
$StorageStatus = $False
}
}
}
}
@yusufozturk
Copy link

Thanks for the update @basroovers 👍 💯 🥇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment