If you have to create several identical VMs that deviate significantly from the wizard's defaults in the Hyper-V Manager, it results in a lot of manual work. Alternatively, PowerShell offers cmdlets for this purpose that can add and configure virtual hardware, such as network adapters or VHDs.
Avatar

The requirement to create several identical VMs arises, for example, when you want to combine virtual instances of Windows Server to form a cluster. A typical application for this is setting up a lab environment. The following instructions show the procedure using the example of Azure Stack HCI to evaluate it on a single machine.

In principle, you could simply configure a VM manually in such a case and then clone it. The Hyper-V Manager does not have an explicit function for this task, but for some time now, the Windows Admin Center has been able to do this. New VMs, automatically created by PowerShell, are probably the cleaner solution, though.

Creating and customizing a VM

The first step is to create the virtual machine. The command depends on whether the VHD for it already exists. If it does, then you tell New-VM the path to the virtual drive using the VHDPath parameter.

We are assuming that no VHD exists yet and that we will only install it afterwards:

New-VM -Name ASHCI03 -NoVHD -Path "F:\\Hyper-V\\" -Generation 2

After the VM ASHCI03 has been created, you can configure it using Set-VM. The following command sets the number of vCPUs and the available vRAM. It also disables snapshots, including the automatic checkpoints common in Windows 10. Since Azure Stack HCI uses nested virtualization, we don't activate Dynamic Memory.

Set-VM -Name ASHCI03 -ProcessorCount 4 -StaticMemory \`
-MemoryStartupBytes 8GB -CheckpointType Disabled

Now it is time to configure the vNICs. When the VM is created, it automatically receives a network adapter. Its name can be saved in the variable $NicName, using

$NicName = (Get-VMNetworkAdapter -VMName ASHCI03).Name

We need the adapter's default name because we want to name all NICs according to a consistent convention. This command gives it the new name vNIC01:

Rename-VMNetworkAdapter -Name $NicName -VMName ASHCI03 -NewName vNIC01

Creating and connecting network adapters

Microsoft's recommendation for Azure Stack HCI includes four vNICs for the virtual machine. The missing three can be created as follows:

2 .. 4 | foreach {Add-VMNetworkAdapter -VMName ASHCI03 -Name vNIC0$\_}

These should be bound to an external-type vSwitch.

All steps start from creating and customizing the VM to adding the NICs and creating the VHDs

All steps start from creating and customizing the VM to adding the NICs and creating the VHDs

The following command connects all four vNICs to a virtual switch, which in our example is called External:

1 .. 4 | foreach {Connect-VMNetworkAdapter -Name vNIC0$\_ \`
-SwitchName "Extern" -VMName ASHCI03}

Since we need to enable the hypervisor in Azure Stack HCI, you need to allow spoofing of Mac addresses for nested virtualization:

1 .. 4 | foreach {Set-VMNetworkAdapter -VMName ASHCI03 -Name vNIC0$\_ \`
-MacAddressSpoofing On}

At this point, you can create another necessary prerequisite, namely, to make the virtualization extensions of the CPU visible in the VM:

Set-VMProcessor -VMName ASHCI03 -ExposeVirtualizationExtensions $true

Creating and attaching drives

In addition to the system volume, Azure Stack HCI requires at least two more drives for Storage Spaces Direct. They are created with the New-VHD cmdlet, named ASHCI03-0[1,2,3].vhdx:

1 .. 3 | foreach {New-VHD -Path "F:\\Hyper-V\\ASHCI03\\Virtual Hard Disks\\ASHCI03-0$\_.vhdx" \`
-Dynamic -SizeBytes 20GB}

You then link the three VHDX to the virtual machine with this command:

1 .. 3 | foreach {Add-VMHardDiskDrive -Path "F:\\Hyper-V\\ASHCI03\\Virtual Hard Disks\\ASHCI03-0$\_.vhdx" -VMName "ASHCI03"}
Assigning new VHDs to the virtual machine inserting ISO into the virtual DVD drive and enabling nested virtualization

Assigning new VHDs to the virtual machine inserting ISO into the virtual DVD drive and enabling nested virtualization

Finally, assign the installation media to the VM using a virtual DVD drive:

Add-VMDvdDrive -VMName ASHCI03 -Path F:\\AzureStackHCI\_17784.1408\_EN-US.iso
The inside view in the Azure Stack HCI VM on the virtual network adapters and drives

The inside view in the Azure Stack HCI VM on the virtual network adapters and drives

For the VM to boot from the DVD drive, the boot order must be changed accordingly:

$dvd = Get-VMDvdDrive -VMName ASHCI03
Set-VMFirmware ASHCI03 -FirstBootDevice $dvd

The new VM is now ready for the installation of the operating system. If Hyper-V cannot be enabled in Azure Stack HCI, you can enable the feature offline in VHDX.

Consolidating all commands in a function

For more efficient use, you can combine the above instructions into one function, specifying the name of the new VM as a parameter.

Using the generateVM function to create a new virtual machine

Using the generateVM function to create a new virtual machine

If necessary, you can also set a variable for the paths used. Specify the paths as additional parameters when you execute the function.

Subscribe to 4sysops newsletter!

function generateVM{
Param(
	[parameter(Mandatory=$true)]
	[String] $vmname
)
#create new VM

New-VM -Name $vmname -NoVHD -Path "F:\Hyper-V\" -Generation 2

#configure vCPUs, vRAM, Checkpoints
Set-VM -Name $vmname -ProcessorCount 4 -StaticMemory `
-MemoryStartupBytes 8GB -CheckpointType Disabled

#query default vNIC name
$NicName = (Get-VMNetworkAdapter -VMName $vmname).Name

#rename network adapter
Rename-VMNetworkAdapter -Name $NicName -VMName $vmname -NewName vNIC01

#add 3 additional vNICs to VM
2 .. 4 | foreach {Add-VMNetworkAdapter -VMName $vmname -Name vNIC0$_}

#activate MAC address spoofing
1 .. 4 | foreach {Set-VMNetworkAdapter -VMName $vmname -Name vNIC0$_ `
-MacAddressSpoofing On}

#bind adapters to vSwitch
1 .. 4 | foreach {Connect-VMNetworkAdapter -Name vNIC0$_ `
-SwitchName "Extern" -VMName $vmname}

#enable nested virtualization
Set-VMProcessor -VMName $vmname -ExposeVirtualizationExtensions $true

#create dynamic VHDs
1 .. 3 | foreach {New-VHD -Path "F:\Hyper-V\$vmname\Virtual Hard Disks\$vmname-0$_.vhdx" `
-Dynamic -SizeBytes 20GB}

#add VHDs to VM
1 .. 3 | foreach {Add-VMHardDiskDrive -Path "F:\Hyper-V\$vmname\Virtual Hard Disks\$vmname-0$_.vhdx" `
-VMName $vmname}

#add ISO as new DVD drive to VM
Add-VMDvdDrive -VMName $vmname -Path C:\Users\wolf.WINDOWSPRO\Downloads\AzureStackHCI_17784.1408_EN-US.iso

#rearrange boot order
$dvd = Get-VMDvdDrive -VMName $vmname
Set-VMFirmware $vmname -FirstBootDevice $dvd
}
avatar
0 Comments

Leave a reply

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

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account