TechEd 2012–Windows Server 2012 Hyper-V Storage Session/Scripts

I hope everyone that attended TechEd had a great time – this was far and away the best TechEd I have personally attended.  I had promised all the scripts from my session and I decided to wait until the recording/slides where available and just do one big post so here it is…

Session Recording




Keeping The PowerShell Window On Top

I already posted this earlier at Scripts From TechEd 2012… Part 1 (Keeping PowerShell Window On Top) but here it is again…
$signature = @’
public static extern bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
uint uFlags);
$type = Add-Type -MemberDefinition $signature -Name SetWindowPosition -Namespace SetWindowPos -Using System.Text -PassThru

$handle = (Get-Process -id $Global:PID).MainWindowHandle
$alwaysOnTop = New-Object -TypeName System.IntPtr -ArgumentList (-1)
$type::SetWindowPos($handle, $alwaysOnTop, 0, 0, 0, 0, 0x0003)


Configuring Virtual Fibre Channel

$vm = (Get-ClusterGroup -Name "FibreChannelDemo" -Cluster "hv-teched-c" | Get-VM)
$adapterA = Add-VMFibreChannelHba -VM $vm -GenerateWwn -SanName "Virtual SAN - A" -Passthru
$adapterB = Add-VMFibreChannelHba -VM $vm -GenerateWwn -SanName "Virtual SAN - B" -Passthru
Import-Module DataONTAP
Connect-NaController -Name " #Name/IP Of NetApp SAN"
$igroup = New-NaIgroup -Name "FibreChannelDemo" -Protocol fcp -Type hyper_v
Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterA.WorldWidePortNameSetA
Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterA.WorldWidePortNameSetB
Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterB.WorldWidePortNameSetA
Add-NaIgroupInitiator -Igroup $igroup.Name -Initiator $adapterB.WorldWidePortNameSetB
New-NaVol -Name "FibreChannelDemo" -Aggregate aggr1 -Size 100G -SpaceReserve "none"
New-NaLun -Path "/vol/FibreChannelDemo/FibreChannelDemo" -Size 100G -Type hyper_v -Unreserved
Add-NaLunMap -InitiatorGroup $igroup -Path "/vol/FibreChannelDemo/FibreChannelDemo"
Start-vm -VM $vm

Displaying SQL Transactions

#Insert the PowerShell Function to Keep the Window On Top
$sqlConn = new-object System.Data.SqlClient.SqlConnection -ArgumentList "Data Source=HV-TE-SQL-1\MSSQLSERVER2;Integrated Security=TRUE;Initial Catalog=Demo"
$sqlCommand = new-object System.Data.SqlClient.SqlCommand -ArgumentList @("EXEC [dbo].[AddData];", $sqlConn)

while ($true)
$startTime = [DateTime]::Now
for ($counter = 0; $startTime.AddSeconds(1) -gt [DateTime]::Now; $counter++)
"Executing $counter Transactions Per Second" | write-host -NoNewline

Displaying VHD/VHDx Size On Disk

#Insert the PowerShell Function to Keep the Window On Top
function Write-VHDSize {
$vhdSize = ((Get-ItemProperty -Path "m:\teched01_Trim_vhd\trim.vhd").Length/1GB)
$vhdxSize = ((Get-ItemProperty -Path "N:\teched01_Trim_vhdx\trim.vhdx").Length/1GB)
Write-Host "Current VHD and VHDx Size On Disk"
[String]::Format("VHD Size:`t{0:F2}GB`nVHDx Size:`t{1:F2}GB", $vhdSize, $vhdxSize) | Write-Host -NoNewline
Start-Sleep -Milliseconds 300

while ($true)

Displaying the VHDx and SAN Space Used

#Insert the PowerShell Function to Keep the Window On Top
function WriteVHDVolSize ()
    $vhdxSize = ((Get-Item -Path "O:\teched01-Trim-san\trim.vhdx").Length/1MB)
    $EqlVolumeSize = (Get-EqlVolume -VolumeName "teched01-Trim-san").AllocatedMB
    [String]::Format("VHDx Size:`t{0:F2}MB`nUsed SAN Space:`t{1:F2}MB", $vhdxSize, $EqlVolumeSize) | Write-Host -NoNewline
    Start-Sleep -Milliseconds 300

if (!(Get-Module EqlPSTools))
    Import-Module "c:\Program Files\EqualLogic\bin\EqlPSTools.dll"
$Creds = new-object -typename System.Management.Automation.PSCredential -argumentlist "demo", (ConvertTo-SecureString -AsPlainText " #Password" -Force)
Connect-EqlGroup -GroupAddress " #Name/IP Of EqualLogic SAN" -Credential $Creds

while ($true)

Initializing the Virtual Disk In The VM

Write-Host "Initializing VHDx Disk..."

$disk = Get-Disk | Where-Object {$_.OperationalStatus -eq "Offline"}
$disk | Set-Disk -IsOffline:$false
if ($disk -eq $null)
    $disk = Get-Disk | Where-Object {$_.PartitionStyle -eq "RAW"}
$disk | Initialize-Disk -PartitionStyle GPT

Write-Host "Creating X: Partition of 40GB on VHDx Disk..."
New-Partition -DiskId $disk.UniqueId -Size 40GB -DriveLetter ([Char]"X") | Format-Volume -FileSystem NTFS -Confirm:$false
Write-Host "Creating Y: Partition of 40GB on VHDx Disk..."
New-Partition -DiskId $disk.UniqueId -Size 40GB -DriveLetter ([Char]"Y") | Format-Volume -FileSystem NTFS -Confirm:$false

Start-Process E:

Optimizing The Volume

Optimize-Volume -DriveLetter X –ReTrim

Full Script For UnMap/Trim Demo Of VHDx On SAN

function Copy-File {
$sourceFile = [System.IO.File]::OpenRead($Source)
$destinationFile = [System.IO.File]::OpenWrite($Destination)
Write-Progress -ID 1 -Activity "Copying BigFile" -status "$Source -> $Destination" -PercentComplete 0
try {
[byte[]]$buffer = new-object byte[] 4096
[int]$total = [int]$counter = 0
do {
$counter = $sourceFile.Read($buffer, 0, $buffer.Length)
$destinationFile.Write($buffer, 0, $counter)
$total += $counter
if ($total % 1mb -eq 0) {
Write-Progress -ID 1 -Activity "Copying BigFile" -status "$Source -> $Destination" `
-PercentComplete ([int]($total/$sourceFile.Length* 100))
} while ($counter -gt 0)
finally {
Write-Progress -ID 1 -Activity "Copying BigFile" -Completed:$true

"Windows PowerShell" | Write-Host
"Copyright (C) 2012 Microsoft Corporation. All rights reserved.`n" | Write-Host

"PS C:\> Copy-File -From `"E:\MyBigFile.bin`" -To `"X:\MyBigFile.bin`"" | Write-Host -NoNewline
Read-Host |Out-Null
Copy-File -From "E:\MyBigFile.bin" -To "X:\MyBigFile.bin" | Write-Host -NoNewline
Write-Host "Flushing File System Cache...`n"
Set-Disk -Number 2 -IsOffline:$true
Set-Disk -Number 2 -IsOffline:$false

"PS C:\> Remove-Item `"X:\MyBigFile.bin`" -Force:`$true -Confirm:`$false" | Write-Host -NoNewline
Read-Host |Out-Null
Remove-Item "x:\MyBigFile.bin" -Force:$true -Confirm:$false

"PS C:\> Optimize-Volume -DriveLetter X -ReTrim" | Write-Host -NoNewline
Read-Host |Out-Null

Optimize-Volume -DriveLetter X –ReTrim