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

One thought on “Build a Windows Server 2012 Hyper-V Cluster Using PowerShell”

  1. Hi,

    When you use workflows, it means that you run WMF (Windows Management Framework) 3.0. It also means that you don’t need to use the old V2 syntax to declare mandatory parameter: [parameter(Mandatory=$true)]
    In powershell V3.0 you can now simply do [parameter(mandatory)]

    Note also that when you declare [string[]], it means that it’s an array of strings.
    We usually expect a foreach loop to handle more than 1 string.
    So you should probably modify your workflow this way:
    [parameter(Mandatory)][String]$ClusterName

    I don’t have a cluster to test the above code, but it could be nice to handle errors using the
    try {
    my-cmdlet -ErrorAction Stop
    }catch{ }
    block.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.