OS virtualization is a process whereby you run an operating system instance inside another. Your host computer and its operating system can run multiple virtual machines, each with a different operating system and virtual hardware. Virtualization as a concept is not new. IBM used virtualization with its Time Sharing System OS (TSS) in the late 1960s, for example.
Microsoft's virtualization efforts began with the purchase of Connectix and the launch of two products: Microsoft Virtual PC and Microsoft Virtual Server. Both products enabled you to create and use virtual machines. Microsoft Virtual PC, version 2004, ran on Windows XP Professional and Windows 2000 Professional. Virtual Server was an enhanced product primarily for use on servers.
Hyper‐V replaced these products, although initially, it was a server‐only product. Microsoft shipped Hyper‐V as a feature inside Windows Server 2008. Subsequently, Microsoft incorporated a client version of Hyper‐V into Windows 8. Today, Microsoft supports Hyper‐V in versions of Windows Server, Windows 8.1, and Windows 10 (Enterprise, Professional, and Education editions of Windows 10 only).
Microsoft also provides a free version of Hyper‐V, the Microsoft Hyper‐V Server. This product is a bare‐metal hypervisor that only runs virtual machines and has no management GUI, very much like Windows Server installed without the Desktop Experience (aka Server Core). After installing the Hyper‐V server, you perform some initial configuration using
sconfig.exe
and can then manage the server remotely using PowerShell or the Hyper‐V management console
virgmgmt.msc
.
With Windows Server 2019 and Windows 10, Microsoft incorporated nested virtualization. This feature allows you to build a VM that can itself host VMs. Nested virtualization can be useful in cases such as training—you could provide each student a single VM on a large server dedicated to the class in which you create VMs as needed for lab work. Nested virtualization also provides an additional layer of security that might be useful when deploying VMs in multitenant scenarios. And for the geeks, it is pretty cool.
This chapter looks at Hyper‐V running on Windows Server. If you are managing Hyper‐V in Windows 10 or using Hyper‐V Server, you can use the same tools discussed here. Some features, such as VM migration, are not available in Windows 10. You can use nested virtualization and create virtual machines running Windows Server 2019 and then use VM migration as shown in this chapter.
In this chapter, you examine the following topics:
HVDirect
VM and then adding the Hyper‐V role to the VM.This chapter uses three hosts:
Reskit.Org
domain, which you created in Chapter 3, “Managing Active Directory.”Reskit.Org
domain. In this chapter, you use these hosts to install and manage Hyper‐V virtualization.Figure 8.1 shows the systems in use in this chapter.
Figure 8.1: Systems used in this chapter
If you create
HV1
and
HV2
using the build scripts at github.com/doctordns/ReskitBuildScripts, make sure you adjust the amount of virtual RAM to allocate to both
HV1
and
HV2
. Having 4GB on each of these VMs is recommended, and more is preferable.
Note that all systems used in this chapter need PowerShell 7 (and VS Code) loaded before starting. You can do that manually using the scripts from Chapter 1, “Establishing a PowerShell 7 Administrative Environment.”
Optionally, you can configure VS Code as shown in Chapter 1.
Hyper‐V is a Windows Server feature that you can install on Windows Server 2019 and Windows Server 2016. On supported editions of Windows 10, the Hyper‐V client is an optional feature, and you install it differently.
You can install the Hyper‐V management tools independently; doing so provides the ability for local and remote administration. And with the management tools, you have the choice of using the GUI or using PowerShell 7. If you choose to use Hyper‐V with Windows 10, see docs.microsoft.com
/virtualization/hyper‐v‐on‐windows/quick‐start/enable‐hyper‐v
for more information on installing Hyper‐V.
In this section, you install the Hyper‐V feature on the
HV1
server.
HV1
is a Windows Server 2019 Datacenter host installed with the Desktop Experience. You should add PowerShell 7 and, optionally, VS Code to this host before proceeding.
Assuming you are using Hyper‐V to host the
HV1
VM, after you create
DC1
as a basic, domain‐joined host, you should then add PowerShell 7 and the Hyper‐V feature. You can configure the
HV1
VM as follows:
# 0. Configure HV1 VM
# Run on the Hyper-V Host running HV1
Stop-VM -VMName HV1
# Enable nested virtualization and set processor count for HV1
$VMHT = @{
VMName = 'HV1'
ExposeVirtualizationExtensions = $true
Count = 4
}
Set-VMProcessor @VMHT
# Set VM Memory for HV1
$VMHT = [ordered] @{
VMName = 'HV1'
DynamicMemoryEnabled = $true
MinimumBytes = 4GB
StartupBytes = 4GB
MaximumBytes = 6GB
}
Set-VMMemory @VMHT
Start-VM -VMName HV1
The first step in configuring a Windows Server 2019 host to support Hyper‐V is to use
Install‐WindowsFeature
to install both Hyper‐V and the necessary management tools.
# 1. Install the Hyper-V feature on HV1
Import-Module -Name ServerManager -WarningAction SilentlyContinue
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools
You can view the output of this code in Figure 8.2.
Figure 8.2: Installing Hyper‐V on
HV1
In most cases, you want to install both the feature and the tools on each Hyper‐V host. You can also install the management tools separately where you need them by installing the Hyper‐V RSAT tools.
As you can see in the output in Figure 8.2, you need to reboot
HV1
to complete the installation of Hyper‐V.
# 2. Reboot HV1 to complete the installation
Restart-Computer
Hyper‐V provides control over where to store VM configuration details and VM hard disks. To see this for yourself, create some new folders using
New‐Item
.
# 3. Create new folders to hold VM details and disks
$VMS = 'C:\VM\VMS'
$VHDS = 'C:\VM\VHDS\'
New-Item -Path $VMS -ItemType Directory -Force | Out-Null
New-Item -Path $VHDS -ItemType Directory -force | Out-Null
If you use the
‐Force
parameter when creating a new folder, PowerShell automatically creates any intermediate folders in the path. In this case, you are creating
C:\VM\VMS
, and using
‐Force
creates both the
C:\VM
and
C:\VM\VMS
folders.
You can set a number of separate configuration items on your Hyper‐V host. You use
Set‐VMHost
to apply these settings and begin by creating a splatting hash table with some of the configuration options given nondefault values. Then you pass the hash table to
Set‐VMHost
to configure the options specified there. The complete snippet looks like this:
# 4. Build Hash Table to configure the VM Host
$VMCHT = @{
# Where to store VM configuration files
VirtualMachinePath = $VMS
# Where to store VHDx files
VirtualHardDiskPath = $VHDS
# Enable NUMA spanning
NumaSpanningEnabled = $true
# Enable Enhanced Session Mode
EnableEnhancedSessionMode = $true
# Specify Resource metering save interval
ResourceMeteringSaveInterval = (New-TimeSpan -Hours 2 )
}
Set-VMHost @VMCHT
There are 15 configuration settings you can update using the
Set‐VMHost
command. For more details on the command and the options you can set, see docs.microsoft.com
/powershell/module/hyper‐v/set‐vmhost
. For Microsoft's explanation of splatting in PowerShell 7, see docs.microsoft.com
/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell‐7
.
You can review some of the VM host settings using the GUI, or you can review or you can review them all using all using
Get‐VMHost
. To see the updated settings for your host, you can use this syntax:
# 5. Review key VMHost settings
Get-VMHost |
Format-Table -Property 'Name', 'V*Path','Numasp*', 'Ena*','RES*'
This code produces the output you can see in Figure 8.3.
Figure 8.3: Reviewing VM host settings
With some objects, selecting properties can be challenging, especially when you have long property names. As shown in the output, you can “cheat” a bit when specifying the property names with wildcards. As an alternative, you could create a string array holding the full names of all the properties to display and pass that to
Format‐Table
. For production scripts, you may want to spell out explicitly the name of the properties to view.
Once you have a VM host up and running, you can create a VM inside the host. To create a Hyper‐V VM and install an operating system as part of the process, you need a bootable OS installation ISO file. You can download an ISO image for Window Server 2019 from the Microsoft Evaluation Center web site at microsoft.com/evalcenter/evaluate-windows-server-2019.
This section uses a Windows Server ISO image. As an alternative, Microsoft's Evaluation Center also provides a virtual disk file you can use to build a preconfigured VM.
This section uses the
HV1
host, which you configured in “Installing and Configuring Hyper‐V.” It also uses an ISO image of Windows Server, a 180‐day evaluation edition downloaded from the Microsoft Evaluation Center.
The filename of the ISO can (and often does) vary depending on your particular image source and when you download it. You can use the same ISO image in this section that you used to create the other VMs used throughout this book. For the purposes of this chapter, a specific filename for the ISO image is used. After downloading the ISO image, you store the image as
C:\ISO
\
WinSrv2019.ISO.
You start this section by setting values for key variables to be used later in this section, as follows:
# 1. Set up the VM name and paths
$VMname = 'HVDirect'
$VMLocation = 'C:\VM\VMs'
$VHDlocation = 'C:\VM\Vhds'
$VHDPath = "$VHDlocation\HVDirect.Vhdx"
$ISOPath = 'C:\ISO\WinSrv2019.ISO'
These variables are used in creating a VM.
$ISOPath
is the path name for the Windows Server 2019. This section assumes a specific filename, although the actual name of the file you download may vary depending on your source and when you do the download. You can either change the file name of the ISO image or change the value you assigned to
$ISOPath
to match your actual filename.
To verify that the ISO image is available, you can use
Test‐Path
.
# 2. Verify drive contents
If (-Not (Test-Path -Path $ISOPath)) {
Throw "ISO Image [$ISOPath] NOT found"
}
The
Test‐Path
cmdlet returns a value of
True
(if the file exists) or
False
. If for some reason the ISO file is not there, the code throws an exception. If the file is there, this code produces no output, and you move on to the next step.
Microsoft's Windows Deployment Image Servicing and Management (DISM) module is a set of tools that help you to manage Windows images as part of deployment. In this section, you use DISM to obtain the versions of Windows that can be installed from your ISO image. A typical ISO image contains Windows Server Standard and Windows Server Datacenter, with and without the Desktop Experience. This book uses Windows Server Datacenter with Desktop Experience.
The DISM module is one of the older Windows PowerShell modules that is not natively supported within PowerShell 7. Nevertheless, you can use the module based on the Windows PowerShell compatibility feature described in Chapter 2. The
Import‐Module
statement looks like this:
# 3. Import the DISM Module
Import-Module -Name DISM -WarningAction SilentlyContinue
Running this command normally produces a warning message that the module has been loaded using a compatibility remoting session (as described in Chapter 2, “PowerShell 7 Compatibility with Windows PowerShell”). To avoid this warning, you can use the
‐WarningAction
parameter to tell PowerShell not to display it.
An ISO image represents a bootable DVD containing the Windows Installation media. You could burn the image to a physical CD or put the image on a USB stick for use in installing Windows on physical hardware. You can also mount the ISO image within Windows as if it were an actual DVD. You use the
Mount‐DiskImage
command to mount the ISO image on
HV1
as follows:
# 4. Mount ISO Image
Mount-DiskImage -ImagePath $ISOPath
This command mounts the ISO image onto your host computer and produces the output you can see in Figure 8.4.
Figure 8.4: Mounting the ISO disk image
When you mount the ISO image, Windows gives it a drive letter and enables read‐only access to all the files/folders within the image. With Windows Server 2019, the Windows installation ISO contains a file called
<dvddrive>:\sources\install.wim
. This file contains one or more specific images that you can install using this image. To see what version of Windows Server you can install, you use the
Get‐WindowsImage
cmdlet, as shown here:
# 5. Get details and Display ISO image contents and Dismount the ISO
$ISOImage = Get-DiskImage -ImagePath $ISOPath | Get-Volume
$ISODrive = [string] $ISOImage.DriveLetter + ":"
Get-WindowsImage -ImagePath $ISODrive\sources\install.wim |
Format-Table -Property ImageIndex, Imagename, Imagedescription -Wrap
Dismount-DiskImage -ImagePath $ISOPath | Out-Null
These commands provide you with details of the versions of Windows Server you can install from the ISO image, after which you dismount the image.
Depending on the source of your ISO image, the output from this step looks like Figure 8.5.
Figure 8.5: Viewing the contents of
install.wim
Before proceeding, you should ensure that the ISO contains an image for Windows Server 2019 Datacenter with Desktop Experience.
To create a VM, you use the
New‐VM
command, as shown here:
# 6. Create a new VM
New-VM -Name $VMname -Path $VMLocation -MemoryStartupBytes 1GB
This creates a new Hyper‐V VM, although at this point it is not usable yet. You can see the output from this command in Figure 8.6.
Figure 8.6: Creating a new VM
Every VM needs at least one virtual disk on which you install the OS. You use the
New‐VHD
command to create this file for the new VM, as follows:
# 7. Create a virtual disk file for the VM
New-VHD -Path $VhdPath -SizeBytes 128GB -Dynamic | Out-Null
You use the
Add‐VMHardDiskDrive
command to add a disk to a VM:
# 8. Add the virtual hard drive to the VM
Add-VMHardDiskDrive -VMName $VMname -Path $VhdPath
By default, a Hyper‐V VM has two IDE controllers that both have two locations that can contain virtual disks or virtual CDs. This command adds the newly created (and empty) disk in the first location on the first controller, which Windows creates as the C: drive.
You next use the
Set‐VMDvdDrive
command to set the ISO image in the VM's virtual DVD drive.
# 9. Set ISO image in the VM's DVD drive
$IHT = @{
VMName = $VMName
ControllerNumber = 1
Path = $ISOPath
}
Set-VMDvdDrive @IHT
This inserts the ISO image into the virtual DVD drive. The
$ISOPath
variable holds the full path for the ISO image file.
With the disk drive and DVD added to the VM, you can now start the VM. By default, Hyper‐V boots from the DVD image to begin the process of installing Windows Server 2019. You use the
Start‐VM
command to start the VM as follows:
# 10. Start the VM
Start-VM -VMName $VMName
Now that you have started the VM, you should use the Hyper‐V Virtual Machine Connection tool (
vmconnect.exe
) to connect to it. You can run this tool directly from the command line or via the Hyper‐V Manager MMC (
wbadmin.msc
). After connecting to the newly created VM, you can complete the manual installation of Windows Server. This includes creating the Administrator user and specifying the password. For the examples in this chapter, be sure to use the book's general‐use password (
Pa$$w0rd
). Alternatively, use a different password (and remember to use that password in later sections of this chapter).
Once you complete the installation process, you can view the VM details using
Get‐VM
, as follows:
# 12. View the results
Get-VM -VMName $VMName
You can see the output from this command in Figure 8.7.
Figure 8.7: Viewing newly created VM details
PowerShell Direct is a Hyper‐V feature that allows you to use a VM that does not have a working network stack. Without a working network stack, you cannot, for example, use the Remote Desktop application to connect to the VM. Instead, you can use PowerShell and just specify the VM name. Using the feature means you do need to have the credentials for the VM. PS Direct enables you to use the VM, often to configure networking within the VM.
You run the code in this section on
HV1
, which you set up in “Installing and Configuring Hyper‐V,” and after you have created the
HVDirect
VM in “Creating a Hyper‐V VM.”
To begin this section, you create a number of variables, as follows:
# 1. Create a credential object for local Administrator
$LHAN = 'Localhost\Administrator'
$PS = 'Pa$$w0rd'
$LHP = ConvertTo-SecureString -String $PS -AsPlainText -Force
$CREDHT = @{
TypeName = 'System.Management.Automation.PSCredential'
Argumentlist = $LHAN, $LHP
}
$LHCred = New-Object @CREDHT
$VMNAME = 'HVDirect'
This code first creates a new credential object for the
HVDirect
VM. Note that you use the hostname
Localhost
. Then you set the variable
$VMNAME
to the VM name. By default, the VM's hostname was assigned by the Windows Server setup process and so is different from the VM name.
Before using the
HVDirect
VM, check to ensure the VM is up and running, using
Get‐VM
as follows:
# 2. Display the details of the HVDirect VM
Get-VM -Name $VMNAME
This command produces the output shown in Figure 8.8.
Figure 8.8: Displaying VM details
To demonstrate using PS Direct, you can use
Invoke‐Command
to run a command inside the VM, as follows:
# 3. Invoke a command on the VM, specifying VM name
$SBHT = @{
VMName = $VMNAME
Credential = $LHCred
ScriptBlock = {hostname}
}
Invoke-Command @SBHT
The
Invoke‐Command
cmdlet runs the script block inside the
HVDirect
VM and produces the output you can see in Figure 8.9.
Figure 8.9: Getting the VM host name
The output confirms the host name as, in this case,
WIN‐DIDLT555LM3
. This host name was assigned by the Windows Setup process automatically when you created the VM. This is probably not a host name you want to retain and is easy to change.
In the previous step, you ran a command on a VM based on the Hyper‐V VM name. Another way to identify the VM is based on the internal Hyper‐V VM ID. This is a GUID created by Hyper‐V when you create the VM and, unlike the VM name itself, never changes. You can use the VM ID in conjunction with
Invoke‐Command
as follows:
# 4. Invoke a command based on VMID
$VMID = (Get-VM -VMName $VMNAME).VMId.Guid
Invoke-Command -VMid $VMID -Credential $LHCred -ScriptBlock {ipconfig}
You can see the output from this command in Figure 8.10.
Figure 8.10: Displaying VM details using VM ID
As you can see in Figure 8.10, the network inside
HVDirect
is not connected to a working network. This is expected, given that you created this VM as shown in “Creating a Hyper‐V VM,” and it is easy to resolve as you see in “Configuring VM Networking.”
With Hyper‐V, you can configure a VM to have one or more virtual NICs associated with different virtual switches. To enable VMs to communicate with each other, with the VM host, and with the wider Internet, you also need to implement one or more VM switches. Once you create a virtual switch, you assign a VM's virtual NIC to the switch to enable communication with other systems using the same switch. For more details on planning Hyper‐V networking, see docs.microsoft.com/en-gb/windows-server/virtualization/hyper-v/plan/plan-hyper-v-networking-in-windows-server.
In this section, you configure networking for the VM you created in “Creating a Hyper‐V VM.” This VM,
HVDirect
, runs on the
HV1
host, which you set up in “Installing and Configuring Hyper‐V.”
In “Creating a Hyper‐V VM,” you created a VM with a host name of
HVDirect
. In this section, you create a new external switch on
HV1
and configure the
HVDirect
VM to be connected to that switch.
Once you have networking for this VM configured fully, you can join the VM to the Reskit domain and change the host name in the process. In this section you assign a new host name,
Tiger
, to this VM.
You start this section by getting details of the virtual NIC inside the
HVDirect
VM.
# 1. Get NIC details and any IP Address from the HVDirect VM
$VMNAME = 'HVDirect'
Get-VMNetworkAdapter -VMName $VMNAME
Figure 8.11 shows the output from this command.
Figure 8.11: Viewing NIC details
You need to create a credential object for this VM, which you can do using
New‐Object
as follows:
# 2. Create a credential
$LHAN = 'Localhost\Administrator'
$PS = 'Pa$$w0rd'
$LHP = ConvertTo-SecureString -String $PS -AsPlainText -Force
$T = 'System.Management.Automation.PSCredential'
$LHCred = New-Object -TypeName $T -ArgumentList $LHAN, $LHP
This credential object is for the VM host's administrator account.
This snippet shows one of the many methods you can use to create a PowerShell account credentials object.
You use the
Get‐NetIPConfiguration
command run inside the VM to get the IP address configuration, as follows:
# 3. Get NIC Details from inside the VM
$VMHT = @{
VMName = $VMName
ScriptBlock = {Get-NetIPConfiguration |
Format-List }
Credential = $LHCred
}
Invoke-Command @VMHT
When you use
Invoke‐Command
in this way, PowerShell runs the script block within the VM. This produces the output you see in Figure 8.12.
Figure 8.12: Viewing the NIC configuration
In the output, you can see that the network adapter is shown as being disconnected. Given the way you created the VM (by using the code in “Creating a Hyper‐V VM”), this is to be expected.
By default, when you install Hyper‐V, the installation process does not create any virtual switches. You can create a simple external switch using
New‐VMSwitch
, as follows:
# 4. Create a virtual switch on HV1
$VSHT = @{
Name = 'External'
NetAdapterName = 'Ethernet'
Notes = 'Created on HV1'
}
New-VMSwitch @VSHT
Figure 8.13 shows the output.
Figure 8.13: Creating a virtual switch
Now that you have an external virtual switch defined, you can connect the NIC inside the
HVDirect
VM to the switch, using the
Connect‐VMNetworkAdapter
command.
# 5. Connect HVDirect to the switch
Connect-VMNetworkAdapter -VMName $VMNAME -SwitchName External
This command connects the virtual NIC to the external switch, which enables networking.
The examples in this chapter make use of the nested virtualization feature you examine later, in “Implementing Nested Virtualization.” If you are using Hyper‐V and have implemented
HV1
as a VM, you need to update
HV1
's NIC configuration to enable MAC address spoofing, using the
Set‐VMNetworkAdapter
command, as follows:
# 6. Enable spoofing From VM Host
# Run this command on the VM Host that hosts HV1
Get-VMNetworkAdapter -VMName HV1 |
Set-VMNetworkAdapter -MacAddressSpoofing On
With this command, the virtual NIC inside the VM now appears to be on the local network. Since the VM was created, by default, with a single NIC that is set to get its address by DHCP, if you have a DHCP server on the network, DHCP allocates IP address details to the VM.
Now that you have set up networking for the
HVDirect
VM, you can view the results by using
Get‐VMNetworkAdapter
from your VM host.
# 7. Get VM networking information
Get-VMNetworkAdapter -VMName $VMName
You can see the output from this command in Figure 8.14.
Figure 8.14: Viewing the virtual NIC configuration
In Chapter 4, “Managing Networking,” you installed a DHCP server (“Installing the DHCP Service”) and created a DHCP scope (in “Configuring DHCP Scopes”) on
DC1
. If you have the DHCP service running on
DC1
, then after you connect the virtual NIC to the network, Windows assigns a new DHCP‐supplied IP address to the NIC. You can view this IP address by running
Get‐NetIPConfiguration
as follows:
# 8. With HVDirect now in the network, observe the IP address in the VM
$NCHT = @{
VMName = $VMName
ScriptBlock = {Get-NetIPConfiguration | Format-List}
Credential = $LHCred
}
Invoke-Command @NCHT
You can see the output from this command in Figure 8.15.
Figure 8.15: Viewing the NIC IP address
In this command, you retrieved the IP address information for the NIC inside the VM using PowerShell remoting. Since there is a DHCP server (on
DC1
) in your network, the VM obtains IP configuration from the DHCP server.
By default, the objects that PowerShell creates within a remoting session are serialized when returned. In this case, PowerShell does not have access to the display XML that was in the remote session, which results in output that is much harder to read. A way around this is to pipe the network details to
Format‐List
inside the remote session, which produces easier‐to‐use output.
If, for any reason, there is no DHCP server in the network, you need to configure
HVDirect
to have a working IP address so that it can connect to the domain controller (to join the domain).
In the steps in this section so far, you have configured the
HVDirect
VM to obtain a working IP address configuration. You can now join this host to the Reskit domain by using the
Add‐Computer
command, as shown here:
# 9. Join the Reskit Domain
# Update the script block
$NCHT.ScriptBlock = {
$RKAdmin = 'Reskit\Administrator'
$PS = 'Pa$$w0rd'
$RKPW = ConvertTo-SecureString -String $PS -AsPlainText -Force
$T = 'System.Management.Automation.PSCredential'
$DomCred = New-Object -TypeName $T -ArgumentList $RKAdmin, $RKPW
$JCHT = @{
Domain = 'Reskit.Org'
Credential = $DomCred
NewName = 'Tiger'
}
Add-Computer @JCHT
}
Invoke-Command @NCHT
These commands produce the output you can see in Figure 8.16.
Figure 8.16: Joining the domain
In this code fragment, you first created a script block that contains the commands necessary to join the Reskit domain and to change the host name. Then you use PowerShell remoting to run that script block inside the
HVDirect
VM. This has the effect of joining the Reskit domain and changing the host name from the name Windows created for you to
Tiger
. As the output shows, you have to restart the system for these changes to take effect.
Once you reboot and these changes take effect, you have a VM with a VM name of
HVDirect
and a host name of
Tiger
.
To complete the renaming of the host and join the host to the domain, you need to restart the host. To do this, you use the
Restart‐VM
command from the Hyper‐V host.
# 10. Reboot and wait for the restarted VM
Restart-VM -VMName $VMName -Wait -For IPAddress -Force
This command reboots the VM and waits for it to restart and get an IP address. This illustrates how you can use PowerShell to reboot another host and wait until the host has fully restarted and can accept incoming network connections. After the VM has rebooted, its FQDN is now Tiger.Reskit.Org.
Once the VM has restarted the
HVDirect
VM, you can check inside the VM to get the host name (which was changed to
Tiger
in “Configuring VM Networking”). Also, since the host has been joined to the domain, you use domain credentials to invoke commands inside the VM.
You can check the host name using the
hostname
command. But since the VM credentials have changed, you need to recreate a credential object, as follows:
# 11. Get hostname of the HVDirect VM
$RKAdmin = 'Reskit\Administrator'
$PS = 'Pa$$w0rd'
$RKPW = ConvertTo-SecureString -String $PS -AsPlainText -Force
$T = 'System.Management.Automation.PSCredential'
$DomCred = New-Object -TypeName $T -ArgumentList $RKAdmin, $RKPW
$NCHT.Credential = $DomCred
$NCHT.ScriptBlock = {hostname}
Invoke-Command @NCHT
This set of commands produces the output you see in Figure 8.17.
Figure 8.17: Obtaining the host name
Now that you have joined the
HVDirec
t VM to the Reskit domain, you can use the domain credentials when running a remote session. In this case you saw that the
HVDirect
VM has the host name
Tiger
.
With Hyper‐V, your VMs contain virtual hardware—virtual NICs, virtual CPUs, virtual disk controllers, virtual disks, virtual memory, and so on. Once you have a VM created, you can use commands in the Hyper‐V module to configure the virtual hardware on your VMs.
This section uses the Hyper‐V Server
HV1
(created in “Installing and Configuring Hyper‐V”) and the
HVDirect
VM you created in “Creating a Hyper‐V VM” and updated in “Configuring VM Networking.”
Depending on the VM generation on your VMs, some hardware can be hot‐added/removed. Some changes to virtual hardware, for example, changing the number of virtual processors in a VM, can be done only while the VM is turned off.
# 1. Turn off the HVDirect VM
$VMName = 'HVDirect'
Stop-VM -VMName $VMName
Get-VM -VMName $VMName
You can see the output from these commands in Figure 8.18.
Figure 8.18: Shutting down a VM
To update the virtual hardware in a VM, you need to turn off the VM before adjusting the hardware. Some hardware changes can, however, be made while the VM is running.
With Windows Server 2019 and Generation 1 VMs, you can adjust the amount of virtual memory for a hard drive. Additionally, for Generation 2 VMs, you can add or remove network adapters while the VM is running. Both VM generations support hot‐add hot‐adding of SCSI disks of SCSI disks
.
With a Hyper‐V VM, you can specify the startup order, using the
Set‐VMBios
command as follows:
# 2. Set the StartupOrder in the VM's BIOS
$Order = 'IDE','CD','LegacyNetworkAdapter','Floppy'
Set-VMBios -VmName $VMName -StartupOrder $Order
Get-VMBios $VMName
This produces the output you see in Figure 8.19.
Figure 8.19: Updating VM BIOS
When you next attempt to start the VM, Hyper‐V attempts to boot from the first volume in the first IDE controller (which is where Hyper‐V inserted the C: drive for your VM). Changing the BIOS startup order means when you start up a VM, Hyper‐V does not attempt to boot from a DVD image but boots from the system drive.
Like a physical machine, Hyper‐V allows you to add virtual processors to the VM, using the
Set‐VMProcessor
command.
# 3. Set CPU count for HVDirect
Set-VMProcessor -VMName $VMName -Count 2
Get-VMProcessor -VMName $VMName |
Format-Table VMName, Count
This produces the output you see in Figure 8.20.
Figure 8.20: Changing the VM processor count
This code gives the
HVDirect
VM a total of two virtual processors. When Windows is running inside the VM, it sees that the virtual hardware has two CPUs and uses both.
If you have multiple cores in your Hyper‐V Host, then you can allocate larger numbers of virtual processors to VMs. You might, for example, devote eight cores or more to a Microsoft SQL Server VM.
You can also vary the memory allocated for the VM by using the
Set‐VMMemory
command, as follows:
# 4. Set VM memory
$VMHT = [ordered] @{
VMName = $VMName
DynamicMemoryEnabled = $true
MinimumBytes = 768MB
StartupBytes = 960MB
MaximumBytes = 1GB
}
Set-VMMemory @VMHT
Get-VMMemory -VMName $VMName
This produces the output you see in Figure 8.21.
Figure 8.21: Changing the VM memory allocation
You can specify any amount of memory you want, but Hyper‐V needs to have sufficient free memory on the VM host to allocate, in this case, a 1GB maximum amount of virtual RAM for this VM.
In setting VM memory, you can only start VMs that, in total, use less RAM than you have available on your host.
Larger VMs frequently need multiple disks. Hyper‐V's IDE controllers enable you to support a maximum of four virtual disk drives (or three if you are using a DVD). To support more disks, you can add additional virtual SCSI controllers to the VM, each of which can contain many VHD drives. To add an SCSI controller, you use the
Add‐VMScsiController
command as follows:
# 5. Add an ScsiController to the VM
Add-VMScsiController -VMName $VMName
Get-VMScsiController -VMName $VMName
This produces the output you see in Figure 8.22.
Figure 8.22: Adding an SCSI controller
As you can see in the output, the
HVDirect
VM now has two SCSI controllers you can use.
With the changes to the virtual hardware made, you use the
Start‐VM
command to start the
HVDirect
VM.
# 6. Restart the HVDirect VM
Start-VM -VMName $VMName
Wait-VM -VMName $VMName -For IPAddress
When you run these commands from
HV1
, Hyper‐V starts up the
HVDirect
VM. You can use the
Wait‐VM
command to wait until the VM is up and running and has an IP address with which you can connect.
To demonstrate adding a virtual disk to a VM, first you use
New‐VHD
from
HV1
to create a new VHD, as follows:
# 7. Create a new VHDX file
$VHDPath = 'C:\Vm\Vhds\HVDirect-D.VHDX'
New-VHD -Path $VHDPath -SizeBytes 8GB -Dynamic
This command creates a new virtual disk drive and produces the output shown in Figure 8.23.
Figure 8.23: Creating a new virtual disk
Because this is for demonstration and not production use, you define a maximum size of 8GB.
You can now use the
Add‐VMHardDiskdrive
command to add the newly created VHDX to the
HV1
VM.
# 8. Add the VHD to the ScsiController
$VHDHT = @{
VMName = $VMName
ControllerType = 'SCSI'
ControllerNumber = 0
ControllerLocation = 0
Path = $VHDPath
}
Add-VMHardDiskDrive @VHDHT
This command immediately adds the VHDX to the virtual SCSI controller, and you can now begin to use it. You can use the scripts shown in Chapter 5 “Managing Windows Storage,” including the ones in “Managing Disks and Volumes” and “Managing NTFS Permissions.”
You use the
Get‐VMScsiController
command to see details of the virtual SCSI disks within the VM, as follows:
# 9. Get SCSI Disks in the VM
Get-VMScsiController -VMName $VMName |
Select-Object -ExpandProperty Drives
Figure 8.24 shows the SCSI virtual disk drives contained in the
HVDirect
VM.
Figure 8.24: Viewing SCSI disks
Nested virtualization is a feature that allows you to install Hyper‐V inside a Hyper‐V VM, running a VM inside another VM. This nesting has a number of use cases. The VMs used in writing this book are all based on nested virtualization, for example. To learn more about nested virtualization, see docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization.
In this section you explore nested virtualization by enabling this feature on the
HVDirect
VM and then adding the Hyper‐V role to the VM. Without nested virtualization, the installation of Hyper‐V in the
HVDirect
VM would not succeed. Once nested virtualization has been enabled, you can install Hyper‐V inside the nested VM.
This section uses the
HVDirect
VM, which you set up in “Creating a Hyper‐V VM.”
To configure nested virtualization in a VM, you must first shut down the VM, using
Stop‐VM
.
# 1. Stop HVDirect VM
$VMName = 'HVDIRECT'
Stop-VM -VMName $VMName
With the VM stopped, you can now configure nested virtualization (and add an extra virtual processor for this VM) using the
Set‐VMProcessor
command as follows:
# 2. Change the VM's processor to support virtualization
$VMName = 'HVDIRECT'
$VMHT = @{
VMName = $VMName
ExposeVirtualizationExtensions = $true
Count = 2
}
Set-VMProcessor @VMHT
Get-VMProcessor -VMName $VMName |
Format-Table -Property Name, Count,
ExposeVirtualizationExtensions
You can see the output of these commands in Figure 8.25.
Figure 8.25: Configuring the VM processor
These commands expose hardware virtualization features to this VM and add a second virtual processor to the VM.
Because you are going to be running VMs inside this VM, you need to enable MAC address spoofing on the virtual NIC inside the
HVDirect
VM, using
Set‐VMNetworkAdapter
. The code looks like this:
# 3. Enable MAC Address spoofing on the virtual NIC
Get-VM -VMName $VMName |
Get-VMNetworkAdapter |
Set-VMNetworkAdapter -MacAddressSpoofing On
MAC address spoofing is one approach to networking of nested VMs. Using Network Address Translation is an alternative. Using NAT, you would create a new internal virtual switch and configure the switch to support NAT. For more information on supporting NAT, see docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization.
You restart the VM and view the VM status by using the following commands:
# 4. Restart the VM
Start-VM -VMName $VMName
Wait-VM -VMName $VMName -For Heartbeat
Get-VM -VMName $VMName
You can see the output from these commands in Figure 8.26.
Figure 8.26: Restarting HVDirect
You need a credentials object to run commands in a remoting session. You create the credentials object using
New‐Object
.
# 5. Create credentials for HVDirect
$User = 'Reskit\Administrator'
$PHT = @{
String = 'Pa$$w0rd'
AsPlainText = $true
Force = $true
}
$PSS = ConvertTo-SecureString @PHT
$Type = 'System.Management.Automation.PSCredential'
$CredRK = New-Object -TypeName $Type -ArgumentList $User,$PSS
Now that the VM is running, as a test of nested virtualization, you can attempt to install the Hyper‐V Windows feature inside the VM, using the following commands:
# 6. Install Hyper-V inside the HVDirect VM
$SB = {
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools
}
$IHT = @{
VMName = $VMName
ScriptBlock = $SB
Credential = $CredRK
}
Invoke-Command @IHT
These commands use PowerShell remoting to install the Hyper‐V Windows feature and produce the output shown in Figure 8.27.
Figure 8.27: Installing Hyper‐V in HVDirect
As indicated in the output, you need to restart the VM to complete the installation of Hyper‐V.
To restart the VM, you need to stop and then restart the VM, using the following commands:
# 7. Restart the VM to finish adding Hyper-V
Stop-VM -VMName $VMName
Start-VM -VMName $VMName
Wait-VM -VMName $VMName -For IPAddress
Get-VM -VMName $VMName
These commands produce the output shown in Figure 8.28.
Figure 8.28: Restarting HVDirect
As you can see from the output, the VM has restarted. As an alternative to using the
Stop‐VM
and
Start‐VM
commands, you could have used
Restart‐Computer
and specified the VM's host name.
To complete your look at nested virtualization, you can examine the Hyper‐V feature that you just installed in the VM and the Hyper‐V services that support Hyper‐V. You use the following commands to view these details:
# 8. Check Hyper-V inside HVDirect VM
$SB = {
Get-WindowsFeature *Hyper* |
Format-Table Name, InstallState
Get-Service VM*
}
Invoke-Command -VMName $VMName -ScriptBlock $SB -Credential $CredRK
You can view the output produced from these commands in Figure 8.29.
As you can see from the output, Hyper‐V and related features are installed. Additionally, you can see that the key Hyper‐V integration services are installed and the needed services are all running. Without nested virtualization, none of these services would have been installed or running.
To find out more about these services, see docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/integration-services.
Figure 8.29: Examining Hyper‐V within HVDirect
A benefit of Hyper‐V, and any virtualization solution, is the ability to save a state and later revert to that state. You might take a checkpoint for a VM just prior to adding an application that you can later revert back to.
Hyper‐V supports two types of checkpoints: standard and production. A standard checkpoint is a snapshot of a VM and its system memory at the moment that the checkpoint is initiated. A production checkpoint uses the Volume Shadow Copy Service (or File System Freeze in Linux VMs) to create a data‐consistent backup of the VM. Production checkpoints do not take a snapshot of system memory. For more details on Hyper‐V checkpoints, see docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/checkpoints.
In this section you create checkpoints and examine the results of taking and reverting to a checkpoint.
This section uses the
HVDirect
VM you created in “Creating a Hyper‐V VM.” You run the commands in this section on
HV1
, the Hyper‐V host you set up in “Installing and Configuring Hyper‐V.” You must run these commands in an elevated console (or in VS Code that you run as Administrator).
In this section you run numerous commands within the
HVDirect
VM, and for that you need to create a credential object for the Reskit Administrator user. You create the credential object using
New‐Object
as follows:
# 1. Create credentials for HVDirect VM
$RKUN = 'Reskit\Administrator'
$PS = 'Pa$$w0rd'
$RKP = ConvertTo-SecureString -String $PS -AsPlainText -Force
$T = 'System.Management.Automation.PSCredential'
$RKCred = New-Object -TypeName $T -ArgumentList $RKUN,$RKP
In this section you create checkpoints and files within the
C:
drive for the
HVDirect
VM to observe the effect of taking and reverting to checkpoints. Before doing this, you look at the contents of
C:
in the
HVDirect
VM, using
Invoke‐Command
.
# 2. Look at C:\ in HVDirect before starting
$VMName = 'HVDirect'
$ICHT = @{
VMName = $VMName
ScriptBlock = {Get-ChildItem -Path C:\ | Format-Table}
Credential = $RKCred
}
Invoke-Command @ICHT
These commands produce the output you see in Figure 8.30.
Figure 8.30: Examining the
HVDirect C:
drive
You use the
Checkpoint‐VM
command to create a Hyper‐V checkpoint as follows:
# 3. Create a checkpoint of HVDirect
$CPHT = @{
VMName = $VMName
SnapshotName = 'Checkpoint1'
}
Checkpoint-VM @CPHT
This command creates a VM checkpoint for the
HVDirect
VM. For each virtual disk drive in the VM, Hyper‐V creates a differencing disk each time you create a new checkpoint. When Hyper‐V takes the checkpoint, the previous base disk is frozen, and Hyper‐V makes any changes to the differencing disk(s). Each additional checkpoint you take creates further differencing disks.
This means in a case where you have a large number of checkpoints, a disk read being performed by a VM might have to read all of the differencing disks to carry out the I/O operation. Unless there is a good reason, you should avoid having excessive checkpoints as it can affect disk performance.
Having taken a first checkpoint, you can view the supporting checkpoint files using
Get‐ChildItem
.
# 4. Look at the files created to support checkpoints
$Parent = Split-Path -Parent (Get-VM -Name $VMName |
Select-Object -ExpandProperty HardDrives).Path |
Select-Object -First 1
Get-ChildItem -Path $Parent
Figure 8.31 shows the output from these commands.
Figure 8.31: Examining the checkpoint files
These commands discover the folder name that Hyper‐V uses to store the VM's virtual hard drives and then get the files stored in that folder. As you can see in the output, there are two base virtual disks.
You see four files in this output. The first is the VM's C: drive with the second the VM's D: drive. The two additional files are the differencing disks Hyper‐V creates when you create the checkpoint.
To illustrate the effects of checkpoints, you can create some content on the
HVDirect
VM. This content is created after you created the first checkpoint.
# 5. Create some content in a file on HVDirect and display it
$SB = {
$FileName1 = 'C:\File_After_Checkpoint_1'
'After Checkpoint 1' |
Out-File -FilePath $FileName1
Get-Content -Path $FileName1
}
$ICHT = @{
VMName = $VMName
ScriptBlock = $SB
Credential = $RKCred
}
Invoke-Command @ICHT
These commands create a file in the
C:
drive in
HVDirect
and then view the content of this file, producing the output you see in Figure 8.32.
Figure 8.32: Creating content on
HVDirect
After creating a file in
C:
, you can take a further checkpoint using
Checkpoint‐VM
.
# 6. Take a second checkpoint
$SNHT = @{
VMName = $VMName
SnapshotName = 'Checkpoint2'
}
Checkpoint-VM @SNHT
After taking the two checkpoints, you can again view the existing checkpoints by using the
Get‐VMCheckPoint
alias.
# 7. Get the VM checkpoint details for HVDirect
Get-VMCheckPoint -VMName $VMName
This command produces the output shown in Figure 8.33.
Figure 8.33: Viewing Hyper‐V checkpoints
The
Get‐VMCheckpoint
command is an alias to
Get‐VMSnapShot
. In early versions of Hyper‐V, the terminology for this technology was inconsistent. System Center VM Manager, for example, used the term checkpoint, while Hyper‐V called it a snapshot. Additionally, the term snapshot was often confused with the Volume Shadow Copy Service snapshots that backup programs use. In Hyper‐V with Server 2012 R2, the Hyper‐V team renamed the term. Thus, the command that creates the snapshot/checkpoint is now named
Checkpoint‐VM
. However, instead of renaming the other VM snapshot cmdlets, the team chose to keep the existing cmdlet names, such as
Get‐VMSnapshot
, and instead created aliases such as
Get‐VMCheckpoint.
With two checkpoints taken for the
HVDirect
VM, you can look at the files that Hyper‐V is using to support the two virtual disks in the VM.
# 8. Look at the files supporting the two checkpoints
Get-ChildItem -Path $Parent
You can view the output from this command in Figure 8.34.
Figure 8.34: Viewing checkpoint files
As you can see, there are now two differencing disks for each of the original VHDX files.
With two checkpoints taken, you create a new file in the
HVDirect
VM to demonstrate the content that is created after you take the second checkpoint. You then view the contents of that file, as follows:
# 9. Create and display another file in HVDirect
# (after you have taken Checkpoint2)
$SB = {
$FileName2 = 'C:\File_After_Checkpoint_2'
'After Checkpoint 2' |
Out-File -FilePath $FileName2
Get-ChildItem -Path C:\ -File | Format-Table
}
$ICHT = @{
VMName = $VMName
ScriptBlock = $SB
Credential = $RKCred
}
Invoke-Command @ICHT
These commands display the two files you created in the
C:
drive. You can view the output from these commands in Figure 8.35.
You have, thus far, created two checkpoints of the VM and have added some content beyond the second checkpoint. You can now use the
Restore‐VMCheckpoint
command to revert the VM to the first checkpoint.
# 10. Restore the VM back to the checkpoint named Checkpoint1
$CP1 = Get-VMCheckpoint -VMName $VMName -Name Checkpoint1
Restore-VMCheckpoint -VMSnapshot $CP1 -Confirm:$false
Start-VM -Name $VMName
Wait-VM -For IPAddress -Name $VMName
Figure 8.35: Viewing checkpoint files after the second checkpoint
These commands first find Checkpoint1 and then revert the
HVDirect
VM to the earlier checkpoint. Once it is reverted, you start the VM, waiting until it has fully started.
With the VM reverted to the point at which you took the first checkpoint, you can observe the files available in the
C:
drive in
HVDirect
using
Get‐ChildItem
.
# 11. See what files we have now in the VM
$ICHT = @{
VMName = $VMName
ScriptBlock = {Get-ChildItem -Path C:\ |
Format-Table }
Credential = $RKCred
}
Invoke-Command @ICHT
You can see the output from these commands in Figure 8.36.
Figure 8.36: Viewing files in the VM
In this output, you can see that neither of the two files you created after taking the first checkpoint is missing. This is to be expected.
Hyper‐V enables you to roll forward and apply a checkpoint you made previously. You can do this by using the
Restore‐VMCheckpoint
command.
# 12. Roll forward to Checkpoint2
$Checkpoint2 = Get-VMCheckpoint -VMName $VMName -Name Checkpoint2
Restore-VMCheckpoint -VMSnapshot $Checkpoint2 -Confirm:$false
Start-VM -Name $VMName
Wait-VM -For IPAddress -Name $VMName
These commands find the second checkpoint and roll the VM forward to the state that existed when you took the second checkpoint.
Now that you have rolled the VM forward to the state that existed when you created the second checkpoint, you can look at the files that exist inside the
HVDirect
VM, using
Get‐ChildItem
(remotely), as shown here:
# 13. Observe the files you now have on HVDirect VM
$ICHT = @{
VMName = $VMName
ScriptBlock = {Get-ChildItem -Path C:\ |
Format-Table }
Credential = $RKCred
}
Invoke-Command @ICHT
Figure 8.37 shows the output from these commands.
Figure 8.37: Viewing files in the VM after rolling forward
As you can see in this output, the file you created after Checkpoint1 is available. However, as is to be expected, the file you created after you took the second checkpoint is lost.
This illustrates a key point about checkpoints. If you do have to revert to an earlier checkpoint, consider carefully what state your VM is in before reverting. If you revert a VM but want to keep any data modified after the last checkpoint, you should take an additional checkpoint (Checkpoint3) before reverting. You can always remove the checkpoints later.
With two checkpoints taken, you can view the Hyper‐V checkpoint details using
Get‐VMCheckpoint
, as shown here:
# 14. View checkpoints for HVDirect
Get-VMCheckpoint -VMName $VMName
You can view the output of this command in Figure 8.38, where you can see the two checkpoints you have taken thus far for the
HVDirect
VM.
Figure 8.38: Viewing checkpoints for HVDirect
You can use the
Remove‐VMSnapshot
command to remove the checkpoints for the
HVDirect
VM.
# 15. Remove all the checkpoints for HVDirect
Get-VMCheckpoint -VMName $VMName |
Remove-VMSnapshot
These commands use both cmdlet name (
Remove‐VMSnapshot
) and an alias name (
Get‐VMCheckpoint
). If you are writing scripts to manage VM backups, you should be consistent with which commands, or cmdlet nouns, you use.
Now that you have removed all the checkpoints, you can reexamine the files supporting the
HVDirect
VM, using
Get‐ChildItem
.
# 16. Check VM data files again
Get-ChildItem -Path $Parent
You can see the output from this command in Figure 8.39.
Figure 8.39: Viewing virtual hard disks
With all the checkpoints removed, you now just have a single VHDX file for each virtual disk. The state of the VM, however, is that of the second checkpoint.
Hyper‐V Replica (HVR) is a feature of Hyper‐V that creates a full replica of a VM for disaster recovery. HVR takes a running VM, such as the
HVDirec
t VM you used in earlier sections of this chapter, running on the
HV1
VM host, and replicates it to a second host,
HV2
. In the case of a disaster affecting
HV1
,
HV2
has an up‐to‐date copy of the
HVDirect
VM, which you could then use.
With HVR, you can co‐locate the replica source and target in another nearby Hyper‐V host, for example, in the same rack in your computer suite. Alternatively, you can locate the target across a WAN. The Hyper‐V hosts whose VMs you replicate can be any combination of workgroup, domain‐joined, or clustered hosts. Additionally, there is no specific dependency on AD. This provides simple and easy disaster recovery across a range of scenarios.
HVR uses change tracking with asynchronous replication. This means that, initially, HVR creates a full duplicate of the VM's data on the replication target's host. Then, as changes are made on the source VM, HVR writes the changes to a log file and replays them on the replica target's VM host.
HVR also allows for extended replication, that is, from the replication target to a second extended target. You might use this to create basic VM replication within a single data center and create a third replica in your off‐site DR location. This provides quick failover in the case of relatively minor hardware issues and full disaster recovery via the extended replicas.
This section makes use of two Hyper‐V servers:
HV1
and
HV2
. You created HV1 in “Installing and Configuring Hyper‐V” and updated it in later sections in this chapter. Before you work with the code in this section, you need a second Hyper‐V host,
HV2
. This host is another domain‐joined Windows Server 2019 Enterprise.
After installing Windows Server 2019 Enterprise edition onto
HV2
, you need to configure the host to support virtualization. If
HV2
is a VM, then you can configure the VM from the VM host, as follows:
# 0.1 Configure HV2 VM from the VM host
# If HV2 is a VM, configure it on the Hyper-V Host running HV2
# Stop the VM
Stop-VM -VMName HV2
# Enable nested virtualization and set processor count for HV2
$VMHT = @{
VMName = 'HV2'
ExposeVirtualizationExtensions = $true
Count = 4
}
Set-VMProcessor @VMHT
# Set VM Memory for HV2
$VMHT = [ordered] @{
VMName = 'HV2'
DynamicMemoryEnabled = $true
MinimumBytes = 768MB
StartupBytes = 2GB
MaximumBytes = 4GB
}
Set-VMMemory @VMHT
# Restart HV2 VM
Start-VM -VMName HV2
Wait-VM -VMName HV2 -For IPAddress
After
HV2
, newly configured to support virtualization and related features, has rebooted, log into it as Domain Admin and then add the Hyper‐V Windows feature using
Install‐WindowsFeature
.
# 0.2 Login to HV2 to add Hyper-V feature to HV2
# Install the Hyper-V feature on HV2
Import-Module -Name Servermanager -WarningAction SilentlyContinue
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools
# Reboot HV2 to complete the installation of Hyper-V
Restart-Computer
# Login to HV2 again and configure Hyper-V Host on HV2
# Create folders to hold VM details and disks
$VMS = 'C:\VM\VMS'
$VHDS = 'C:\VM\VHDS\'
New-Item -Path $VMS -ItemType Directory -Force | Out-Null
New-Item -Path $VHDS -ItemType Directory -force | Out-Null
# Build Hash Table to Configure the VM Host
$VMCHT = @{
# Where to store VM configuration files on
VirtualMachinePath = $VMS
# Where to store VHDx files
VirtualHardDiskPath = $VHDS
# Enable NUMA spanning
NumaSpanningEnabled = $true
# Enable Enhanced Session Mode
EnableEnhancedSessionMode = $true
# Specify Resource metering save interval
ResourceMeteringSaveInterval = (New-TimeSpan -Hours 2 )
}
Set-VMHost @VMCHT
# Create new External Switch
$NIC = Get-NetIPConfiguration | Select-Object -First 1
New-VMSwitch -Name External -NetAdapterName $NIC.InterfaceAlias
This snippet also creates an external switch in the HV2 VM. That virtual switch enables HV1 and HV2 to communicate.
To simplify security of HVR, you set each VM host to enable delegation, using
Set‐ADComputer
as follows:
# 1. Configure HV1 and HV2 to be trusted for delegation in AD on DC1
$SB1 = {
Set-ADComputer -Identity HV1 -TrustedForDelegation $True
}
Invoke-Command -ComputerName DC1 -ScriptBlock $SB1
$SB2 = {
Set-ADComputer -Identity HV2 -TrustedForDelegation $True
}
Invoke-Command -ComputerName DC1 -ScriptBlock $SB2
These commands enable Kerberos delegation for the two Hyper‐V servers. You can read a bit more about delegation in argonsys.com/microsoft-cloud/library/live-migration-via-constrained-delegation-with-kerberos-in-windows-server-2016
/
.
To complete the configuration of delegation you need to restart both hosts using
Restart‐Computer
.
# 2. Reboot the HV1 and HV2
Restart-Computer -ComputerName HV1 -Force
Restart-Computer -ComputerName HV2 -Force
You begin the setup of HVR using the command
Set‐VMReplicationServer
as follows:
# 3. Once both systems are restarted, logon back to HV2,
# set up both servers as a replication server
$VMRHT = @{
ReplicationEnabled = $true
AllowedAuthenticationType = 'Kerberos'
KerberosAuthenticationPort = 42000
DefaultStorageLocation = 'C:\Replicas'
ReplicationAllowedFromAnyServer = $true
ComputerName = 'HV1', 'HV2'
}
Set-VMReplicationServer @VMRHT
Before you can replicate a VM between Hyper‐V hosts, you need to use
Enable‐VMReplication
to configure the replication as follows:
# 4. Enable HVDirect on HV1 to be a replica source with HV2 the target
$VMRHT = @{
VMName = 'HVDirect'
Computer = 'HV1'
ReplicaServerName = 'HV2'
ReplicaServerPort = 42000
AuthenticationType = 'Kerberos'
CompressionEnabled = $true
RecoveryHistory = 5
}
Enable-VMReplication @VMRHT
This command initializes the replication of the
HVDirect
VM. The HVR replica source VM is on
HV1
, and the target is on
HV2.
This command specifies that Kerberos is to be used to authenticate the two hosts involved in VM replication. Since both
HV1
and
HV2
are members of the
Reskit
domain (and you have configured them for Kerberos delegation), this is straightforward to configure.
If the source and target Hyper‐V hosts are in different security realms, then you can use certificate authentication. For a look at how you can set up replication using self‐signed certificates, see medium.com/@pbengert/setup-2-hyper-v-2016-servers-enable-hyper-v-replica-with-self-created-certificates-and-connect-to-fceef21c8b8e.
Now that you have enabled replication, you can view the replication status of each Hyper‐V host using
Get‐VMReplicationServer
.
# 5. View the replication status of HV1 and HV2
Get-VMReplicationServer -ComputerName HV1
Get-VMReplicationServer -ComputerName HV2
You can see the output from these commands in Figure 8.40.
Figure 8.40: Viewing replication status
Before initiating the replication, use
Get‐VM
to ensure that the VM is running on
HV1
.
# 6. Check HVDirect on HV1
Get-VM -ComputerName HV1 -VMName HVDirect
As you can see in the output, shown in Figure 8.41, the
HVDirect
VM is up and running on
HV1
.
Figure 8.41: Viewing VM status
Having previously defined the replication source and target for HVDirect, you are ready to initiate replication. To do that, use
Start‐VMInitialReplication
.
# 7. Start the initial replication from HV1 to HV2
Start-VMInitialReplication -VMName HVDirect -ComputerName HV1
This command starts the creation of a replica. Hyper‐V first has to make a copy on
HV2
of the VM hard drives, which can take some time.
To view the state of the replication of
HVDirect
, you can use the
Measure‐VMReplication
command.
# 8. Examine the initial replication state on HV1 just after
# you start the initial replication
Measure-VMReplication -ComputerName HV2
Figure 8.42 shows the output of this command, issued shortly after the initial replication began.
Figure 8.42: Examining the replication status
The initial replication can take some time; this depends on the available bandwidth between
HV1
and
HV2
, the size of the VM, and the workload on each Hyper‐V host. On a fast network, the initial replication of the
HVDirect
VM you created in this chapter should take two to three minutes.
You can use
Measure‐VMReplication
repeatedly to watch the progress of the initial replication.
# 9. Wait for replication to finish, then examine the
# replication status on HV2
Measure-VMReplication -ComputerName HV2
Figure 8.43 shows the output of this command after the initial replication has completed.
Figure 8.43: Viewing the progress of replication
You can run this command multiple times to observe the progress until you see, as in the output from this step, that Hyper‐V has completed the initial replication.
Once initial replication has completed, Hyper‐V detects changes to the VM on
HV1
and replicates them to
HV2
.
You can test the failover by using the
Start‐VMFailOver
command.
# 10. Test HVDirect failover from HV1 to HV2
$VM = Start-VMFailover -AsTest -VMName HVDirect -Confirm:$false
Start-VM $VM
This snippet initiates a test of the replica failover. When you test an HVR replica failover, Hyper‐V creates a new VM on the replication target host with a new name. This VM is, in effect, the replica of the VM, running but with a different Hyper‐V‐generated VM name.
During the test, the original VM on
HV1
continues to run and Hyper‐V continues to replicate any changes.
Use
Get‐VM
to see the VMs that are now running on
HV2
, as follows:
# 11. View the status of VMs on HV2
Get-VM -ComputerName HV2
The output, shown in Figure 8.44, shows the VMs now running on
HV2
.
Figure 8.44: Viewing the VMs running on HV2
The first VM you see in this output is the replica target for the
HVDirect
VM. The second is the VM failover test. Note that the replication test VM name has
‐ Test
appended to the replicated VM's name. Thus, the test VM's name is
HVDirect ‐ Test
.
To test replication, you first run some commands on the
HVDirect
VM running on
HV1
.
# 12. Get VM Details in replica source
$RKUN = 'Reskit\Administrator'
$PS = 'Pa$$w0rd'
$RKP = ConvertTo-SecureString -String $PS -AsPlainText -Force
$CREDHT = @{
TypeName = 'System.Management.Automation.PSCredential'
Argumentlist = $RKUN, $RKP
}
$RKCred = New-Object @CREDHT
$SB1 = {
$SB1a = @{
VMName = 'HVDirect'
ScriptBlock = {hostname;ipconfig}
Credential = $using:RKCred
}
Invoke-Command @SB1a
}
Invoke-Command -Computer HV1 -Script $SB1
You can see the output from this command in Figure 8.45.
Figure 8.45: Getting the VM details on the replica source
The output from these commands shows that the
HVDirect
VM is up and running normally on
HV1
. This VM has an IP address and network details provided by the DHCP server you created on
DC1
.
Once the failover test VM has started, you can also examine it using the same commands.
# 13. Get VM details in replica test VM on HV2
$SB2 = {
$SB2a = @{
VMName = 'HVDirect - Test'
ScriptBlock = {hostname;ipconfig}
Credential = $using:RKCred
}
Invoke-Command @SB2a
}
Invoke-Command -Computer HV2 -Script $SB2
You can see the output from these commands in Figure 8.46.
Figure 8.46: Testing the replica VM
The output shows that the test VM is up and running and can process commands. Note that the host name of the test VM is
Tiger
. This is also the host name for the
HVDirect
VM (running on
HV1
). You created this host name when you joined the VM to the domain in “Configuring VM Networking.” But you also see that there is no TCP/IP networking configured. Given how you have configured
HV2
so far, this is to be expected.
This step also illustrates sending a script block to a host (
HV2
) and then having that script invoke a second script block inside a VM. If you are managing many Hyper‐V servers, which each run multiple VMs, this can be a useful technique to target a particular VM running on a particular Hyper‐V host.
You can now test the failover VM, possibly using PowerShell to investigate the VM. In production, you should ensure that relevant services are up and running and that, if needed, the failover VM could be used to recover from a disaster befalling
HV1
.
Once you have ensured that the failover test has succeeded and that the test VM is up and running (all but the networking), you can stop it using the
Stop‐VMFailover
command.
# 14. Stop the failover test
Stop-VMFailover -VMName HVDirect
Prior to the failover test, you had the working
HVDirect
VM on
HV1
plus the replica on
HV2
. The failover test created a new and temporary VM on
HV2
, which Hyper‐V removes when you stop the failover test.
With the failover test stopped, you can again view the status of the two VM hosts, using
Get‐VM
.
# 15. View the status of VMs on HV1 and HV2 after failover stopped
Get-VM -ComputerName HV1
Get-VM -ComputerName HV2
You can see the output from these commands in Figure 8.47.
Figure 8.47: Viewing VM status
The output shows that all traces of the failover VM on
HV2
are now gone from
HV2
. As you can see, the two Hyper‐V hosts are back to the pre‐failover test state where
HV1
continues to run the
HVDirect
VM with Hyper‐V replicating any changes from
HV1
to the replica on
HV2
.
When you performed the failover test of
HVDirect
, you notice that the test VM (
HVDirect ‐ Test
) had no networking setup. As noted, this is normal. If you want specific network address details (such as IP address and subnet mask), you can set them using the
Set‐VMNetworkadapterFailoverConfiguration
command.
# 16. Set Failover IP address for HVDirect on HV2
$NAHT = @{
IPv4Address = '10.10.10.142'
IPv4SubnetMask = '255.255.255.0'
IPv4PreferredDNSServer = '10.10.10.10'
}
Get-VMNetworkAdapter -VMName HVDirect -ComputerName HV2 |
Set-VMNetworkAdapterFailoverConfiguration @NAHT
Connect-VMNetworkAdapter -VMName HVDirect -SwitchName External
This snippet obtains the network details of the
HVDirect
replica VM as currently residing on
HV2
. This VM is not active and is the target of Hyper‐V VM replication—but the VM does have a virtual NIC.
You can use the commands shown previously to set IP address configuration in the event of any failover. These commands also ensure that the virtual NIC is associated with a switch. The result of these commands is to set up the replica to have a different network configuration and to attach to a virtual switch in the case of further failover. With this configured, when you fail over the
HVDirect
VM to
HV2
, Hyper‐V connects the NIC in the VM to a switch and configures the virtual NIC with an appropriate IP address configuration.
With the steps so far, you have configured HVR to maintain a replica on a second Hyper‐V host so that Hyper‐V replicates all changes from
HV1
to the replica on
HV2
.
To simulate a real‐life failover, you first stop the
HVDirect
VM on
HV1
.
# 17. Stop HVDirect on HV1 prior to performing a failover
Stop-VM HVDirect -ComputerName HV1
This simulates the failure of the VM on
HV1
. However, failover is not automatic. If you wanted automatic failover, you could use failover clustering and cluster the Hyper‐V role.
Using HVR, failover is not automatic but something you need to do in two steps (as noted if you want automatic failover, you should deploy failover clustering).
To start the failover, you use the
Start‐VMFailover
on
HV2
. This tells Hyper‐V to begin a failover.
# 18. Start VM failover from HV1
Start-VMFailover -VMName HVDirect -Confirm:$false
You can use the
Start‐VMFailover
for several purposes.
In effect, this command tells Hyper‐V what kind of a failover it is to perform. By using the
‐Confirm:$false
, you ensure that
Start‐VmFailover
does not prompt for confirmation.
Once you have started the failover, you can complete it using
Complete‐VMFailover
, like so:
# 19. Complete the failover
$CHT = @{
VMName = 'HVDirect'
ComputerName = 'HV2'
Confirm = $false
}
Complete-VMFailover @CHT
This command completes the failover. Note that this command also removes all recovery points on the VM that Hyper‐V has failed over.
Note that in this case you used a hash table to specify the parameters for
Complete‐VMFailOver
—another way to invoke a cmdlet.
Once the VM failover has completed, you have a working VM on
HV2
, although it is not running. To start the VM, you use the
Start‐VM
command and then wait until the VM is up and running on
HV2
.
# 20. Start the replicated VM on HV2
Start-VM -VMname HVDirect -ComputerName HV2
Wait-VM -VMName HVDirect -For IPAddress
These commands start the failover replica on
HV2
. As it takes some time for the VM to start, you can use the
Wait‐VM
command to wait until the
HVDirect
VM is up and running on
HV2
and has a working IP address.
One reason to use this two‐step approach is to enable you to make a good decision as to when to start the replica.
You can repeat the use of
Get‐VM
on both Hyper‐V servers to view the VMs on the two virtualization hosts.
# 21. See VMs on HV1 and HV2 after the planned failover
Get-VM -ComputerName HV1
Get-VM -ComputerName HV2
You can see the output from these commands in Figure 8.48.
As the output shows, the
HVDirect
VM is running on
HV2
but stopped on
HV1
.
Figure 8.48: Checking VM status after failover
With the steps so far, you have set up and initiated a failover of the
HVDirect
VM from
HV1
to
HV2
. Having set up failover network details, you can verify the networking configuration by running the following commands:
# 22. Retest Migrated HVDirect VM
$SB4 =@{
VMName = 'HVDirect'
ScriptBlock = {hostname; ipconfig}
Credential = $rkcred
}
Invoke-Command @SB4
You can see the output from these commands in Figure 8.49.
Figure 8.49: Verifying the VM networking configuration
The output shows that the VM has the host name
Tiger
and has a new IP configuration (the one that you set using
Set‐VMNetworkAdapterFailoverConfiguration
in “Setting Failover IP Address for VM Failover”).
In this section you have configured and tested HVR and VM failover. You now have the
HVDirect
VM up and running on
HV2
.
Hyper‐V provides you with the ability to move both a VM and its virtual disk drives to other systems with the VM up and running—live migration.
This section uses the two Hyper‐V hosts you have used in this chapter. This section assumes you have created the
HVDirect
VM and that it's running on
HV1
.
In the previous section, you ended up with the
HVDirect
VM running on HV2. You can revert the running of
HVDirect
back to HV1 with this syntax:
# 0. Revert VMs before starting
Stop-VM -Name HVDirect -ComputerName HV2 -Force
Remove-VM -Name HVDirect -ComputerName HV2 -Force
Start-VM HVDirect -ComputerName HV1
You start this section by examining the state of the
HVDirect
nested VM on
HV1
, using the
Get‐VM
command.
# 1. View the HVDirect VM on HV1 and verify that it is running and not saved
Get-VM -Name HVDirect
You can see the results of this command in Figure 8.50.
Figure 8.50: Viewing
HVDirect
VM
You should see the
HVDirect
VM, which you created in “Creating a Hyper‐V VM.” Depending on how you have configured the VM, your output might be slightly different—for example you might see a different amount of memory.
Next, you need to see the folder that Hyper‐V is currently using to hold the configuration information for the
HVDirect
VM. Do that using the
Get‐VM
command.
# 2. Get the VM configuration location
(Get-VM -Name HVDirect).ConfigurationLocation
You can see the output of this command in Figure 8.51.
Figure 8.51: Viewing the VM configuration path
If you have run the code in “Managing VM Replication,” you may see a different path. Irrespective of where Hyper‐V stores this information, later steps in this section change the location.
In an enterprise deployment of Hyper‐V, you would typically hold the virtual hard drives on a SAN or via an SMB3 scale‐out file server. In production, the VM details and the virtual hard drives are on separate hosts connected by a fast network.
You use the
Get‐VMHardDiskDrive
command to get details of the virtual hard drives contained in the
HVDirect
VM.
# 3. Get Hard Drive locations
Get-VMHardDiskDrive -VMName HVDirect |
Format-Table -Property VMName, ControllerType, Path
You can see the output of this command in Figure 8.52.
Figure 8.52: Getting the VM hard drive locations for
HVDirect
If you have run the commands in “Managing VM Replication,” you may see a different file paths, but the virtual drive name is the same. And as with the VM details location, what is important is where the files are now since they change using the later steps in this section.
You can move the virtual disk drives used by a running VM using the
Move‐VMStorage
command.
# 4. Move the VMs to the C:\HVD_NEW folder
$MHT = @{
Name = 'HVDirect'
DestinationStoragePath = 'C:\HVD_NEW'
}
Move-VMStorage @MHT
This command moves the files to the path you specify. In this case, you are just moving the virtual disks on a local hard drive. Instead of storing the VHD files on the local hard disk, you could store them on a remote host or your SAN.
It is important to also note that moving files did not require the VM to be stopped—this was a “live” storage migration.
After you have moved the VM's storage, you can view the configuration details again using the
Get‐VM
and
Get‐VMHardDiskDrive
commands.
# 5. View the configuration details after moving the VM's storage
(Get-VM -Name HVDirect).ConfigurationLocation
Get-VMHardDiskDrive -VMName HVDirect |
Format-Table -Property VMName, ControllerType, Path
Figure 8.53 shows the output from these commands.
Figure 8.53: Viewing the VM configuration path
As you can see in the output, the virtual disk drives for the
HVDirect
VM are now in a different location. Had you been running applications inside the VM, they would continue running as normal.
Prior to migrating an entire VM, you should first look at the VMs currently running on
HV2
, using
Get‐VM
.
# 6. Get the VM details for VMs from HV2
Get-VM -ComputerName HV2
This command produces no output—there are no VMs running on
HV2
.
Installing Hyper‐V does not enable VM replication by default. But that is easy to change using
Enable‐VMMigration
.
# 7. Enable VM migration on both HV1 and HV2
Enable-VMMigration -ComputerName HV1, HV2
This command enables VM replication on both
HV1
and
HV2
.
Hyper‐V provides a number of options for configuring migration. These allow for the different deployment scenarios you might find in production. You might run VMs in production on domain‐joined hosts but need to migrate VMs to a host in a work group or a separate domain. In this case, you use Kerberos authentication and configure the replication using
Set‐VMHost
, as follows:
# 8. Configure VM Migration on both hosts
$SVHT = @{
UseAnyNetworkForMigration = $true
ComputerName = 'HV1', 'HV2'
VirtualMachineMigrationAuthenticationType = 'Kerberos'
VirtualMachineMigrationPerformanceOption = 'Compression'
}
Set-VMHost @SVHT
Because both
HV1
and
HV2
are in the Reskit domain, you can use Kerberos for authentication between the two hosts. Were these hosts in different security realms (for example, with one Hyper‐V host in your network and the other in a disaster recovery partner's network), then you could use certificate authentication.
To migrate a running VM from one host (
HV1
) to another (
HV2
), you use the
Move‐VM
command.
# 9. Move the VM to HV2
$Start = Get-Date
$VMHT = @{
Name = 'HVDirect'
ComputerName = 'HV1'
DestinationHost = 'HV2'
IncludeStorage = $true
DestinationStoragePath = 'C:\HVDirect' # on HV2
}
Move-VM @VMHT
$Finish = Get-Date
Hyper‐V performs the migration as fast as it can, but the migration time depends on several factors, including the load on the two Hyper‐V servers and the quality of the network.
After the migration has completed, you can subtract the two date/time objects to calculate how long it took Hyper‐V to migrate the VM from
HV1
to
HV2
.
# 10. Display the time taken to migrate
$OS = "Migration took: [{0:n2}] minutes"
$OS -f ($($Finish-$Start).TotalMinutes)
You can see the output of these commands in Figure 8.54.
Figure 8.54: Displaying migration time
The migration time shown in this figure came from running this step on a high‐speed multiprocessor system. In production, the time taken to migrate a VM will vary depending on the size of the virtual hard drives and CPU load on both the two VM hosts. You also need to factor in the load on the network(s) connecting the two Hyper‐V hosts. If you migrate a large production VM across a suboptimal WAN, migration times are likely to be a lot longer. If you plan to use migration often, it might be useful to test the migration time to inform future planning.
Live migration using Move‐VM is an easy way to move a VM to a new home (and back again as needed). But for large VMs, the time it takes to copy the virtual hard disks may be an issue. If you are regularly moving VMs around, the Hyper‐V Replica tool, as you saw in “Using VM Replication,” might be more useful.
Now that you have migrated your
HVDirect
VM to
HV2
, you can use
Get‐VM
to look at the VMs on
HV1
.
# 11. Check the VMs on HV1
Get-VM -ComputerName HV1
Assuming that the migration was successful, you should see no output from this command—there are no VMs running on
HV1
.
You can also use
Get‐VM
to look at the VMs on
HV2
.
# 12. Check the VMs on HV2
Get-VM -ComputerName HV2
You can see the output from this command in Figure 8.55.
Figure 8.55: Viewing the VMs on HV2
In this case, you should see the
HVDirect
VM is now running on
HV2
.
You can also get the details of where Hyper‐V now stores the VM configuration details for the
HVDirect
VM and the details of the virtual drives used in this VM, like so:
# 13. Look at the details of the moved VM
(Get-VM -Name HVDirect -Computer HV2).ConfigurationLocation
Get-VMHardDiskDrive -VMName HVDirect -Computer HV2 |
Format-Table -Property VMName, Path
You can see the output from these commands in Figure 8.56.
Figure 8.56: Examining VM details
As you can see, the VM configuration details are now stored in
C:\HVDirect
, and the virtual hard drives are held in
C:\HVDirect\Virtual Hard Disks
.
If you deploy Hyper‐V in production, you may find you are running different VMs that belong to different cost centers and you need to measure resource usage of VMs for chargeback. You can use Hyper‐V resource metering to determine the resources used by a given VM. In turn, this can enable you to measure accurately both the assigned capacity and current usage of key resources (such as CPU). This Hyper‐V feature removes the need to develop chargeback solutions, which can be complex and expensive to develop, depending on your requirements.
With resource metering, Hyper‐V enables you to measure the following key resources:
This section uses the Hyper‐V VM (
HVDirect
) and the two Hyper‐V hosts (
HV1
,
HV2
) that you have used throughout this chapter. The section assumes that
HVDirect
VM is running on
HV2
(that is, the state after you've completed “Managing VM Movement”).
You can ensure that you have at least one VM running on
HV2
, using
Get‐VM
.
# 1. Get-VMs on HV2
$VM = Get-VM
$VM
You can see the output from these two commands in Figure 8.57.
Figure 8.57: Examining VM details
You should see, in this figure, just one VM,
HVDirect
.
You use the
Enable‐VMResourcedMetering
command to enable Hyper‐V to do resource monitoring for the
HVDirect
VM.
# 2. Enable resource monitoring of HVDirect
Enable-VMResourceMetering -VM $VM
This command directs Hyper‐V to do the resource monitoring for just one VM. In general, you will probably want to enable resource monitoring on all your VMs.
If the VM is not running, you can use the
Start‐VM
command to start the VM.
# 3. Start VM if needed
If ($VM.State -ne 'Running') {
Start-VM $VM
Wait-VM -VM $VM -FOR IPAddress
}
This ensures the VM is up and running.
You need a credential object for the
HVDirect
VM, which you can create as follows:
# 4. Create Credentials for HVDirect
$User = 'Tiger\Administrator'
$PHT = @{
String = 'Pa$$w0rd'
AsPlainText = $true
Force = $true
}
$PSS = ConvertTo-SecureString @PHT
$Type = 'System.Management.Automation.PSCredential'
$CredHVD = New-Object -TypeName $Type -ArgumentList $User,$PSS
These commands create a credential object for the VM. In this case, you are creating credentials for the administrator of the host.
With the
HVDirect
VM running and with Hyper‐V measuring resource usage, you can get an initial set of measurements by using
Measure‐VM
.
# 5. Get Initial Measurements
Measure-VM -VM $VM
You can see the output from this command in Figure 8.58.
Figure 8.58: Measuring VM resource usage
To get the VM to do some compute work (and increase the CPU usage of the
HVDirect
VM), you can invoke a simple compute‐bound script block inside the VM.
# 6. Do some Compute Work in the VM
$SB ={
1..10000000 | ForEach-Object {$I++;$I--}
}
Invoke-Command -VMName HVDirect -ScriptBlock $SB -Cred $CredHVD
These commands, which produce no output, increment and then decrement the value of the
$I
variable within a PowerShell session running on the VM. These operations primarily use CPU time in the VM.
After starting and running some compute work in the VM, you can re‐measure the resources used by
HVDirect
with the
Measure–VM
command.
# 7. Get Additional Measurements
Measure-VM -VM $VM
You can see the output in Figure 8.59.
Figure 8.59: Remeasuring VM resource usage after computation
As you can see in the output, the amount of average CPU usage has gone up based on the compute work you just carried out.
The exact numbers that
Measure‐VM
produces for you are highly likely to differ from those shown in this chapter. The key thing to note is that after doing some computation within a VM, the measurements show an increased use of CPU within the VM. In a chargeback scenario, the extra work might attract additional costs to the VM owner.
In this chapter, you examined numerous aspects of Hyper‐V, including installing Hyper‐V, creating and managing VMs, configuring and using nested virtualization, and using VM replication and VM (and VM storage) migration. You also saw how to measure VM resource usage on the VM host.