Hyper-V: Create VM from PowerShell

I needed to create a cluster of (identical) VMs on an Hyper-V cluster.

To speed up things, I created a PowerShell script to automatically deploy VMs, cloning a template virtual harddisk.

# ------------------------------------------------------------
# Create Hyper-V virtual machine via PowerShell
# ------------------------------------------------------------

# Variables
$VM_NAME = "PS_TEST_VM"
$VM_MAC = "00:15:5d:11:22:01"

$VM_RAM = 256GB
$VM_CPUS = 16
$VM_DEST_PATH = "C:\ClusterStorage\Volume1\tests"
$VM_VLAN = 82
$VM_HOST = "HYPERV_NODE_25"
$NETWORK_SWITCH = "DefaultNetwork"
$ROOT_VHD_TPL = "C:\ClusterStorage\Volume1\tests\Template.vhdx"
$VM_ROOT_VHD = "${VM_DEST_PATH}/${VM_NAME}.vhdx"
$VM_DATA_VHD = "${VM_DEST_PATH}/${VM_NAME}-data.vhdx"
$VM_DATA_VHD_SIZE = 80GB
$VM_CLUSTER = "HV_CLUSTER_05"

# Create destination folder for VMs
MD $VM_DEST_PATH -ErrorAction SilentlyContinue

# Create Virtual Machine
# ------------------------------------------------------------

echo "Creating VM: $VM_NAME on ${VM_HOST}"
$VM = New-VM -Name $VM_NAME -Path $VM_DEST_PATH -MemoryStartupBytes $VM_RAM -ComputerName $VM_HOST
#echo "    VM Id: $( $VM.Id )"
#echo "    VM Name: $( $VM.Name )"
#echo "    Host: $( $VM.ComputerName )"

# Create & attach VHDs
# ------------------------------------------------------------
# Note: it is impossible to boot from SCSI controllers

echo "Getting first SCSI controller"

echo "Copying Root VHD to $VM_ROOT_VHD"
Convert-VHD -Path $ROOT_VHD_TPL -DestinationPath $VM_ROOT_VHD
Add-VMHardDiskDrive -VM $VM -ControllerType IDE -ControllerNumber 0 -ControllerLocation 0 -Path $VM_ROOT_VHD

echo "Creating new Data disk $VM_DATA_VHD_SIZE in $VM_DATA_VHD"
New-VHD -Path $VM_DATA_VHD -SizeBytes $VM_DATA_VHD_SIZE -Dynamic
Add-VMHardDiskDrive -VM $VM -ControllerType IDE -ControllerNumber 0 -ControllerLocation 1 -Path $VM_DATA_VHD

# Set CPU / memory
# ------------------------------------------------------------

echo "Setting CPU / Memory configuration"
Set-VMProcessor -VM $VM -Count $VM_CPUS
Set-VMMemory -VM $VM -DynamicMemoryEnabled $True -MaximumBytes 512GB -MinimumBytes 16GB -StartupBytes $VM_RAM

# Configure NIC
# ------------------------------------------------------------

echo "Configuring NIC (mac address: ${VM_MAC}, switch: ${NETWORK_SWITCH})"
Remove-VMNetworkAdapter -VM $VM
Add-VMNetworkAdapter -VM $VM -Name PublicNIC -StaticMacAddress $VM_MAC -SwitchName $NETWORK_SWITCH
$ADAPTER = Get-VMNetworkAdapter -VM $VM
Set-VMNetworkAdapterVlan -VMNetworkAdapter $ADAPTER -Access -VlanId $VM_VLAN
# Connect-VMNetworkAdapter -VMNetworkAdapter $ADAPTER -SwitchName $NETWORK_SWITCH

# Add VM to cluster
# ------------------------------------------------------------

echo "Adding VM to cluster"
Add-ClusterVirtualMachineRole -VMName $VM_NAME -Cluster $VM_CLUSTER

# Start VM
# ------------------------------------------------------------

#Start-VM $VM_NAME

Code is also available in a Gist: https://gist.github.com/rshk/a1fcde3b5c77bff3756b

Todo-List

  • Add more checks to make the script more robust, in case the default VM settings should change
  • Make this script accept arguments some way to directly create a batch of VMs without having to manually change configuration variables
  • Figure out some way to perform unattended finalization of VM installation
    • Change passwords
    • Setup SSH server
    • Install + register Saltstack + issue highstate
    • (This probably could be done via PXE boot – but we need a legacy NIC..)
comments powered by Disqus

Table Of Contents

Previous topic

GitLab: misc

Next topic

KVM: Convert disk images

This Page