Creating & Adding Lots Of Shared VHDX Files To VMs Using PowerShell

As previously mentioned, I want to run a virtual SOFS in my lab using Storage Spaces.  This is completely unsupported, but it’s fine for my lab.  In the real world, the SOFS with Storage Spaces features physical servers with a JBOD.

I’m lazy, and I don’t want to be creating VHDX files, adding disks by hand, configuring sharing, and repeating for each and every VHDX on each and every VM.

First up: creating the VHDX files.  This snippet will create a 1 GB witness and 8 * 100 GB data disks:

$Folder = “E:Shared VHDXDemo-FSC1”

New-VHD -Path “$FolderDemo-FSC1 Witness Disk.vhdx” -Dynamic -SizeBytes 1GB

for ($DiskNumber = 2; $DiskNumber -lt 9; $DiskNumber++)
New-VHD -Path “$FolderDemo-FSC1 Data Disk$DiskNumber.vhdx” -Dynamic -SizeBytes 100GB

The next snippet will (a) attach the VHDX files to the default SCSI controller of the VMs, and (b) enable Shared VHDX (Persistent Reservations):

$VMName = “Demo-FS1.demo-internal”

Add-VMHardDiskDrive $VMName -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0 -Path “E:Shared VHDXDemo-FSC1Demo-FSC1 Witness Disk.vhdx” -SupportPersistentReservations

for ($DiskNumber = 1; $DiskNumber -lt 9; $DiskNumber++)
Add-VMHardDiskDrive $VMName -ControllerType SCSI -ControllerNumber 0 -ControllerLocation $DiskNumber -Path “E:Shared VHDXDemo-FSC1Demo-FSC1 Data Disk$DiskNumber.vhdx” -SupportPersistentReservations

And there’s the power of PowerShell.  In just a few minutes, I figured this out, and saved myself some boredom, and then sped up my job. With a bit more crafting, I could script a hell of a lot more in this:

  • Creation of VMs
  • Copying and attaching OS disks
  • The above
  • Booting the VMs
  • Use functions to group code and an array of user entered VM names

Note: You might want to consider adding more SCSI controllers to the VMs, especially if you have plenty of vCPUs to spare.  And yes, I did use Dynamic VHDX because this is a lab.

Configuring WS2012 R2 Hyper-V Live Migration Performance Options Using PowerShell

Didier Van Hoye (VM MVP like me) beat me to blogging about configuring the new options for Live Migration in Windows Server 2012 R2 Hyper-V.  He’s doing that a lot lately Smile  There Didier shows you how to configure the performance options for Live Migration in the GUI.  Here’s how you can do it using PowerShell:

Set-VMHost –VirtualMachineMigrationPerformanceOption <Option>

Where <Option> can be:

  • Compression: This is the default option in WS2012 R2 and uses idle CPU capacity (only) to reduce the time to live migrate VMs.
  • SMB: Using SMB 3.0 Direct (if RDMA is available) and Multichannel (if multiple NICs are available)
  • TCPIP: The legacy non-optimized Live Migration option


Set-VMHost –VirtualMachineMigrationPerformanceOption SMB

And that’s how Ben Armstrong probably scripted his host changes in his TechEd 2013 Live Migration demo (obviously with a lot more logic wrapped around it).

Configuring Jumbo Frames Using PowerShell

Another new version of Windows Server, more features, and another set of PowerShell scripts to write Smile  My host design will be taking advantage of the fact that I have 4 * 10 GbE NICs in each host to play with, and I’ll be implementing my recent converged networks design for SMB 3.0 storage (use the search tool on the top right).

A key in the design is to use the full bandwidth of the NICs.  That means configuring the packet or payload size of each NIC, aka configuring Jumbo Frames.  You can do this by hand, but that’s going to:

  • Get pretty boring after a couple of NICs.
  • Be mistake prone: please send €10 to me every time you get this setting wrong if you disagree with me and continue to do it by hand.


You can configure this setting using PowerShell.  It’s not immediately discoverable, but here’s how I discovered it for my NICs.

I ran Get-NetAdapterAdvancedProperty, targeting a 10 GbE NIC.  That returned the advanced settings and their values of the NIC.  These aren’t the traditional attributes.  Each setting has two values:

  • DisplayName: The NIC setting name
  • DisplayValue: The NIC setting value

I knew from the GUI that the DisplayName was Packet Size and that the desired DisplayValue would be 9014.  Now I could configure the setting:

Set-NetAdapterAdvancedProperty <NIC Name> –DisplayName “Packet Size” –DisplayValue “9014”

I could run that command over and over for each NIC.  Consistent Device Naming (CDN) would make this easier, if my servers were new enough to have CDN Smile  I want to configure all my 10 GbE NICs and not configure my still-enabled 1 GbE NIC (used for remote management).  Here’s how I can target the NICs with the setting:

Get-NetAdapter * | Where-Object { $_.TransmitLinkSpeed –EQ “10000000000” } | Set-NetAdapterAdvancedProperty –DisplayName “Packet Size” –DisplayValue “9014”

The first half of that line finds the 10 GbE NICs, thus filtering out the 1 GbE NICs.  Now I can use that line as part of a greater script to configure my hosts.

Carsten Rachfahl (Hyper-V MVP) Interviews Mark Minasi About PowerShell

Carsten Rachfahl (@hypervserver) is at it again; he’s just published a video interview with Mark Minasi (@mminasi), the famed journalist, author, speaker, trainer, consultant and Directory Services MVP.  This time, the topic is the importance of PowerShell to the admin and why they should learn this scripting language.

Videointerview mit Mark Minasi über PowerShell-thumb1

Don’t worry; the page with the video link is auf Deutch but the video is in English.

Hyper-V PowerShell Script Cookbook on TechNet Wiki

If you’ve heard me speak on Windows Server 2012 or Hyper-V recently, then you know that:

  • I did not really do any PowerShell before March of 2012
  • I started then to solve small problems
  • I’m a total convert to the ways of PowerShell because it speeds up work, gives me predictable results (minus my typos), and saves me from those repetitive tasks

Not only will you find PowerShell all over Windows Server 2012 Hyper-V Installation And Configuration Guide, but you’ll find that a new valuable resource has appeared on the TechNet Wiki.  There you will find the “Hyper-V PowerShell Script Cookbook”.

The goal of this site is to shared PowerShell snippets and scripts.  Right now, the categories include:

  • Virtual Machine
  • Virtual Hard Disk
  • Network Virtualization
  • Virtual Switch
  • Additional scripts

As all good scripters know, you first start by searching, then copying/pasting, and then modifying to get the results you want.  Why not start here … and then contribute any new stuff you create!?!?!

How To Check That A Hyper-V VM Is Active Using PowerShell

I wanted to write a little bit of code to see if a virtual machine was active or not.  Here is a crude bit of code that you could turn into a function:

$VM = Get-VMIntegrationService -VMName VM04 -Name Heartbeat
while ($VM.PrimaryStatusDescription -ne "OK")
    $VM = Get-VMIntegrationService -VMName VM04 -Name Heartbeat
    write-host "The VM is not on"
    sleep 5

    write-host "The VM is on"

The code checks to see if the integration component for the VM heartbeat is active.  This assumes you have either the Windows Integration Components or the Linux Integration Services installed (I wrote this code testing with a Ubuntu 12.04 VM with the built-in services) and that you have not disabled the Integration Services in the VM properties.

The code simply queries the heartbeat status to see if it is “OK” or not.  It will loop until the status is “OK”.  You could use it to see when a VM is active … it is actually testing to see when the Integration Components/Services are active and responsive.

The code could be more elegant, and could be turned into a function for reuse.  This is just a crude example to get you started.

Create A Windows Server 2012 Hyper-V Cluster Using PowerShell

I’ve since posted a more complete script for a Hyper-V cluster that’s using SMB 3.0 storage.

I am creating and destroying Hyper-V clusters like crazy in the lab at the moment.  And that means I need to script; I don’t want to waste time repeating the same thing over and over in the GUI, wasting valuable time.  Assuming your networking is completed (more to come on scripting that!) and your disk is provisioned/formatted, then the following script will build a cluster for you:

New-Cluster –Name demo-hvc1 –StaticAddress –Node demo-host1, demo-host2

Get-ClusterResource | Where-Object {$_.OwnerGroup –eq “Available Storage”}  | Add-ClusterSharedVolume

(Get-Cluster).SharedVolumeBlockCacheSizeInMB = 512

Get-ClusterSharedVolume *  |  Set-ClusterParameter CSVEnabledBlockCache 1

Get-ClusterSharedVolume  | Stop-ClusterResource

Get-ClusterSharedVolume | Start-ClusterResource

What does the script do?

  1. It creates a new cluster called demo-hvc1 with an IP address of using demo-host1 and demo-host2 as the nodes.
  2. It finds all available disk and converts it to CSV volumes.
  3. Then it configures CSV cache to use 512 MB RAM
  4. Every CSV is configured to use CSV cache
  5. The CSVs are stopped
  6. The CSVs are restarted so they can avail of CSV cache

The script doesn’t do a validation.  My setup is pretty static so no validation is required.  BTW, for the VMLimited fanboys out there who moan about time to deploy Hyper-V, my process (networking included) builds the cluster in probably around 30-40 seconds.

Change Windows Server 8 Hyper-V VM Virtual Switch Connection Using PowerShell

I’m building a demo lab on my “beast” laptop and want to make it as mobile as possible, independent of IP addresses, while retaining Internet access.  I do that by placing the VMs on an internal virtual switch and running a proxy on the parent partition or in a VM (dual homed on external virtual switch).  I accidentally built my VMs on an external virtual switch and wanted to switch them to an internal virtual switch called Internal 1.  I could spend a couple of minutes going through every VM and making the change.  Or I could just run this in an elevated PowerShell window, as I just did on my Windows 8 (client OS) machine:

Connect-VMNetworkAdapter –VMName * –SwitchName Internal1

Every VM on my PC was connected to the Internal1 virtual switch.

Use PowerShell To Reconfigure Dynamic Memory in All Hyper-V VMs

I wanted to get more VMs onto my Windows Server 8 Hyper-V lab, so I wanted to change my Dynamic Memory settings in my virtual machines.  I don’t have the patience to edit every VM.  PowerShell to the rescue:

Get-VM * | Set-VMMemory -DynamicMemoryEnabled $True -MaximumBytes 8GB -MinimumBytes 256MB -StartupBytes 512MB

This script gets every VM on this host, passes through the VM via the pipe into the Set-VMMeory cmdlet, and then reconfigures the Dynamic Memory settings that I care about.  Time required by editing & running this in ISE: 1 minute.

PowerShell Script to Create Lots of Windows Server 2012 Hyper-V Virtual Machines at Once

If you like this solution then you might like a newer script that creates lots of VMs based on specs that are stored in a CSV file.

Here you will find a PowerShell script I just wrote to deploy a lot of Windows Server 8 Hyper-V VMs with the minimum of effort.  I created it because I wanted more load to stress my 20 GbE Live Migration network and creating the VMs by hand was too slow.  Yes, it took me time to figure out and write the script in ISE, but I have it for the future and can lash out a lab in no time now.

Note that this script is using the new cmdlets for Hyper-V (and one cmdlet for clustering) that are in Windows Server 8, and not the VMM cmdlets.

What the script will do:

  1. Create a new folder for each VM on an SMB 2.2 file server shared folder
  2. Create a differencing disk pointing to a parent VHD.  This is for lab purposes only.  You’d do something different like create a new VHDX or copy an existing sysprepped VHDX in production.
  3. Create a new VM (e.g. VM1) using the VHDX
  4. Configure Dynamic Memory
  5. Start the VM
  6. Add the VM to a cluster
  7. It’ll do this 20 times (configurable in the foreach loop).


  • Windows Server 8 SMB file share that is correctly configured
  • A Windows Server 8 Hyper-V cluster
  • A parent VHDX that has been sysprepped.  That will automate the configuration of the VM when it powers up for the first time.

Here’s the script.  My old programmer instinct (which refuses to go away) tells me that it could be a lot cleaner, but this rough and ready script works.  There is also zero error checking which the old programmer instinct hates but this is just for deploying a lab workload.

$parentpath = “\fileserverVirtual Machine 1WinSvr8Beta.vhdx”

$path = “\fileserverVirtual Machine 1”

foreach ($i in 1..20)


#Create the necessary folders

$vmpath = “$pathVM$i”

New-Item -Path $vmpath -ItemType “Directory”

New-Item -Path “$vmpathVirtual Hard Disks” -ItemType “Directory”

#create a VHDX – differencing format

$vhdpath = “$vmpathVitual Hard DisksDisk0.vhdx”

New-VHD -ParentPath $parentpath -Differencing -Path $vhdpath

#Create the VM

New-VM -VHDPath “$vhdpath” -Name “VM$i” -Path “$vmpathVirtual Machine” -SwitchName “External1”

#Configure Dynamic Memory

Set-VMMemory -VMName “VM$i” -DynamicMemoryEnabled $True -MaximumBytes 8GB -MinimumBytes 512MB -StartupBytes 1GB

#Start the VM

Start-VM “VM$i”

#Add the VM to the cluster

Add-ClusterVirtualMachineRole -Cluster “hvc1” -VMName “VM$i”