Build a Windows Server 2012 Hyper-V Cluster Using PowerShell

I’ve previously posted a short and basic script that would build a Hyper-V Failover Cluster, but I’ve updated that script since for use in demos.  You can find my new script below.

What does it do?

  1. A new cluster is built with no attached storage.  My latest incarnation of my demos uses a Scale-Out File Server for the storage.
  2. It renames the cluster networks. Note that I’ve used converged fabrics via a virtual switch.
  3. Runs a function called Add-VMsToCluster which will scan all the cluster nodes for VMs to make them highly available
  4. Add-VMsToCluster will run a workflow which will in turn add VMs to the cluster in parallel (up to 5 at a time – a POSH subsystem restriction that Jeff Wouters helped me identify) rather than one at a time (which would be slower)

Things missing from the script:

  • There’s no error checking
  • Damned if I can find out how to set the Live Migration network for a cluster.  Don’t bother sending me your POSH cmdlets for configuring Live Migration networks for non-clustered hosts; that has no effect on clustered hosts.

Here’s the script:

####

# Written by Aidan Finn, @joe_elway, https://aidanfinn.com
# Author of Windows Server 2012 Hyper-V Installation And Configuration Guide
#
# Copyright
###########
# You may use and modify this script free of charge and without permission.
# You may not reproduce or share this script. Please forward people to this
# this page instead.
#
# Waiver
########
# You are solely responsible for testing and using this script and any
# results/problems. There is no support for this script.

Workflow Invoke-AddVMToCluster
{
Param (
[parameter(Mandatory=$true)][String[]] $VMList,
[parameter(Mandatory=$true)][String[]] $ClusterName
)

[string]$TheCluster = $ClusterName

ForEach -Parallel ($VM in $VMList)
    {
    Add-ClusterVirtualMachineRole -VMName $VM -Cluster $TheCluster
    }
# End of workflow
}

Function Add-VMsToCluster ($ClusterName)
{
$ClusterNodes = Get-ClusterNode -Cluster $ClusterName

ForEach ($AddNode in $ClusterNodes)
    {
    $VMList = Get-VM -Name * -ComputerName $AddNode
    If ($VMList -ne $null)
        {
        Invoke-AddVMToCluster -VMList $VMList.Name $ClusterName
        }
    }
# End of function
}

# The script starts here
CLS
Write-Host "Creating the cluster"
New-Cluster -Name demo-hvc1 -StaticAddress 192.168.1.61 -Node demo-host1, demo-host2 -NoStorage

Write-Host "Waiting 10 seconds for the cluster to initialise"
Start-Sleep -s 10

# This cluster is using storage provided by a Scale-Out File Server instead of traditional SAN
Write-Host "Configuring quorum to use file share witness"
Set-ClusterQuorum -NodeAndFileShareMajority \demo-sofs1HVC1-Witness

Write-Host "Renaming the cluster networks"
(Get-ClusterNetwork | where-object {$_.Address -eq "172.16.1.0"}).Name = "vEthernet (Host-Cluster)"
(Get-ClusterNetwork | where-object {$_.Address -eq "172.16.2.0"}).Name = "vEthernet (Host-LiveMigration)"
(Get-ClusterNetwork | where-object {$_.Address -eq "192.168.1.0"}).Name = "vEthernet (Host-Parent)"

Write-Host "Adding any existing VMs to the cluster"
Add-VMsToCluster "demo-hvc1"

####

This information has been brought to you by Windows Server 2012 Hyper-V Installation and Configuration Guide (available on pre-order on Amazon) where you’ll find lots of PowerShell like in this script:

image

Create Lots Of Hyper-V Virtual Machines From A CSV File Using PowerShell

A friend of mine works for a software company, looking after a test rig for one of their product families.  The test rig is based on Hyper-V, and they have to frequently provision lots of virtual machines to test new products.  We were chatting about how they do this a few weeks ago and I thought “I bet I could do that using PowerShell, and I bet I could create a very nice solution too”.  What I wanted: A PowerShell script that would make lots of Windows Server 2012 (WS2012) Hyper-V VMs from a comma separated values (CSV) file.  I also thought that this would be a great demonstration of PowerShell during WS2012 Hyper-V demos that I’m frequently doing.

So I put some work into it.  The concept is based on a previous script that I wrote, but I took it to the Nth degree.

Here’s how my script works:

  1. You create a CSV file that specifies the configuration of each VM (1 row per VM).
  2. You edit the script to read that file (easy change near the top)
  3. You run the script
  4. The results are recorded in a log file that you specify in the script (a second easy change near the top)

I’ve put instructions in the script.  I’ve also supplied a sample CSV file in the zip file to show three different types of VHDX creation.

The script allows you to specify the following in the CSV:

  • Storage location of the VM
  • Name of the VM
  • Processor count
  • Virtual memory, including Dynamic Memory if you want
  • VHDX type and configuration, including Fixed, Dynamic, and Differencing

So how could you use the script?

  • Maybe you want to create lots of pooled or personal VMs
  • Possibly you need to deploy a demo lab with lots of VMs
  • Maybe you are like my friend, working in a large software test environment, and you’d like to deploy lots of VMs, and you’d like to be able to vary the specification and build of those VMs

There’s nothing to stop you from editing the script and either adding/removing functionality.  If you find it useful, then go ahead and use it.  In fact, if you do use it, then tell me how because I’ll be interested.

This script is not supported by me.  Use and/or modify the script at your own risk.

Please note that this script is mine and you may not re-share it without my permission.  Please link to this blog post instead.

You can download the script and sample CSV file from here.

Possible improvements:

  • Add remote host functionality
  • Add cluster functionality
  • Start VMs

This information has been brought to you by Windows Server 2012 Hyper-V Installation and Configuration Guide (available on pre-order on Amazon) where you’ll find lots of PowerShell like in this script:

image

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.

PowerShell 3.0 For Windows 7 SP1, Windows Server 2008 R2 SP1 & Windows Server 2008 SP2

The Windows Management Framework 3.0, or PowerShell 3.0 for legacy operating systems including Windows 7 SP1, Windows Server 2008 R2 SP1 & Windows Server 2008 SP2, has been made available to download.

This package will update:

  • PowerShell
  • WMI
  • WinRM
  • Management OData IIS Extensions
  • Server Manager CIM Provider

The new features in Windows PowerShell 3.0 include:

  • Workflow: Windows PowerShell Workflow lets IT Pros and developers apply the benefits of workflows to the automation capabilities of Windows PowerShell. Workflows allow administrators to run long-running tasks (which can be made repeatable, frequent, parallelizable, interruptible, or restart-able) that can affect multiple managed computers or devices at the same time.
  • Disconnected Sessions: PowerShell sessions can be disconnected from the remote computer and reconnected later from the same computer or a different computer without losing state or causing running commands to fail.
  • Robust Session Connectivity: Remote sessions are resilient to network failures and will attempt to reconnect for several minutes. If connectivity cannot be reestablished, the session will automatically disconnect itself so that it can be reconnected when network connectivity is restored.
  • Scheduled Jobs: Scheduled jobs that run regularly or in response to an event.
  • Delegated Administration: Commands that can be executed with a delegated set of credentials so users with limited permissions can run critical jobs
  • Simplified Language Syntax: Simplified language syntax that make commands and scripts look a lot less like code and a lot more like natural language.
  • Cmdlet Discovery: Improved cmdlet discovery and automatic module loading that make it easier to find and run any of the cmdlets installed on your computer.
  • Show-Command: Show-Command, a cmdlet and ISE Add-On that helps users find the right cmdlet, view its parameters in a dialog box, and run it.
Technorati Tags:

Renaming Cluster Networks In Windows Server 2012

When I’m building a Hyper-V cluster, I like to rename the networks so I know what is what when tuning them.  I’ve previously given you a script to configure a converged fabric host and the code to build a cluster.  Instead of manually renaming the networks, you can do this:

(Get-ClusterNetwork | where-object {$_.Address -eq "172.16.2.0"}).Name = "vEthernet (Host-LiveMigration)"

This cmdlet will find the network you want to rename by querying for it’s IP address.  In this case, find the network 172.16.2.0.  I know this will be my migration network.  Using the object oriented nature of PowerShell (everything is either an object or a method, and objects have attributes), I grab the Name of the resulting network and set it to "vEthernet (Host-LiveMigration)".

The cluster network is then renamed from the anonymous Cluster Network X to a more useful and human friendly name, which is also the name I’m using on my converged fabric virtual NICs.

image

Just repeat this for each network in your script and you’ll have automated yet another step in the cluster creation process.

Updated: PowerShell Script To Create A Converged Fabric For Clustered Windows Server 2012 Hyper-V Host

Last week I published a script to create a converged fabric clustered host.  I wrote that script using the beta of Windows Server 2012 (“8”).  But since then, the release candidate has come out.  And wouldn’t you know it, some of the PowerShell cmdlets in the RC have changed.

Here’s a summary of the changes:

  • When you create a NIC team in the GUI, the device name now matches the NIC team local area connection name.  That’s a good change.  I hated that the local area connection name was tucked away in the advanced settings and threw in a “default” into the name.
  • The cmdlet to set the IP address of the NIC is different.  We used to say –IPv4Address to specify the address.  Now we use –IPAddress.
  • By default, the new virtual NIC took on a meaningless “Wired Ethernet Connection” label for the Local Area Connection name.  I had to rename it to something meaningful, like “Host-Parent”.  Now, the new virtual NIC takes on a meaningful name, such as “vEthernet (Host-Parent)”, so I can delete the cmdlet to delete it.  At first I didn’t like this, but after talking to Hans Vredevoort last night, he changed my mind.
  • I have found that a new management OS virtual NIC can take over 20 seconds to initialise.  That means that any attempt to configure the IP address straight away will fail.  Therefore I’ve moved all the IP config cmdlets to the end of the script, and they only run after a 30 second sleep.

I have updated the original script to reflect these changes.

EDIT #1:

After some testing I found that I had to add a sleep cmdlet before configuring the IP addresses of the virtual NICs.

PowerShell Script To Create A Converged Fabric For Clustered Windows Server 2012 Hyper-V Host

Note: This post was originally written using the Windows Server “8” (aka 2012) Beta.  The PowerShell cmdlets have changed in the Release Candidate and this code has been corrected to suit it.

After the posts of the last few weeks, I thought I’d share a script that I am using to build a converged fabric hosts in the lab.  Some notes:

  1. You have installed Windows Server 2012 on the machine.
  2. You are either on the console or using something like iLO/DRAC to get KVM access.
  3. All NICs on the host will be used for the converged fabric.  You can tweak this.
  4. This will not create a virtual NIC in the management OS (parent partition or host OS).
  5. You will make a different copy of the script for each host in the cluster to change the IPs.
  6. You could strip out all but the Host-Parent NIC to create converged fabric for standalone host with 2 or 4 * 1 GbE NICs

And finally …. MSFT has not published best practices yet.  This is still a beta release.  Please verify that you are following best practices before you use this script.

OK…. here we go.  Watch out for the line breaks if you copy & paste:

write-host “Creating virtual switch with QoS enabled”
New-VMSwitch “ConvergedNetSwitch” -MinimumBandwidthMode weight -NetAdapterName “ConvergedNetTeam” -AllowManagementOS 0

write-host “Setting default QoS policy”
Set-VMSwitch “ConvergedNetSwitch” -DefaultFlowMinimumBandwidthWeight 10

write-host “Creating virtual NICs for the management OS”
Add-VMNetworkAdapter -ManagementOS -Name “Host-Parent” -SwitchName “ConvergedNetSwitch”
Set-VMNetworkAdapter -ManagementOS -Name “Host-Parent” -MinimumBandwidthWeight 10

Add-VMNetworkAdapter -ManagementOS -Name “Host-Cluster” -SwitchName “ConvergedNetSwitch”
Set-VMNetworkAdapter -ManagementOS -Name “Host-Cluster” -MinimumBandwidthWeight 10

Add-VMNetworkAdapter -ManagementOS -Name “Host-LiveMigration” -SwitchName “ConvergedNetSwitch”
Set-VMNetworkAdapter -ManagementOS -Name “Host-LiveMigration” -MinimumBandwidthWeight 10

Add-VMNetworkAdapter -ManagementOS -Name “Host-iSCSI1” -SwitchName “ConvergedNetSwitch”
Set-VMNetworkAdapter -ManagementOS -Name “Host-iSCSI1” -MinimumBandwidthWeight 10

#Add-VMNetworkAdapter -ManagementOS -Name “Host-iSCSI2” -SwitchName “ConvergedNetSwitch”
#Set-VMNetworkAdapter -ManagementOS -Name “Host-iSCSI2” -MinimumBandwidthWeight 15

write-host “Waiting 30 seconds for virtual devices to initialise”
Start-Sleep -s 30

write-host “Configuring IPv4 addresses for the management OS virtual NICs”
New-NetIPAddress -InterfaceAlias “vEthernet (Host-Parent)” -IPAddress 192.168.1.51 -PrefixLength 24 -DefaultGateway 192.168.1.1
Set-DnsClientServerAddress -InterfaceAlias “vEthernet (Host-Parent)” -ServerAddresses “192.168.1.40”

New-NetIPAddress -InterfaceAlias “vEthernet (Host-Cluster)” -IPAddress 172.16.1.1 -PrefixLength “24”

New-NetIPAddress -InterfaceAlias “vEthernet (Host-LiveMigration)” -IPAddress 172.16.2.1 -PrefixLength “24”

New-NetIPAddress -InterfaceAlias “vEthernet (Host-iSCSI1)” -IPAddress 10.0.1.55 -PrefixLength “24”

#New-NetIPAddress -InterfaceAlias “vEthernet (Host-iSCSI2)” -IPAddress 10.0.1.56 -PrefixLength “24”

That will set up the following architecture:

image

QoS is set up as follows:

  • The default (unspecified links) is 10% minimum
  • Parent: 10%
  • Cluster: 10%
  • Live Migration: 20%

My lab has a single VLAN network.  In production, you should have VLANs and trunk the physical switch ports.  Then (I believe), you’ll need to add a line for each virtual NIC in the management OS (host) to specify the right VLAN (I’ve not tested this line yet on the RC release of WS2012 – watch out for teh VMNetowrkAdaptername parameter):

Set-VMNetworkAdapterVLAN –ManagementOS –VMNetworkAdapterName “vEthernet (Host-Parent)” –Trunk –AllowedVLANList 101

Now you have all the cluster connections you need, with NIC teaming, using maybe 2 * 10 GbE, 4 * 1 GbE, or maybe even 4 * 10 GbE if you’re lucky.

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 192.168.1.61 –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 192.168.1.61 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.