Chapter 8
Managing Hyper‐V

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:

  • In “Installing and Configuring Hyper‐V,” you start to look at Hyper‐V by installing and configuring the Hyper‐V feature on Windows Server 2019.
  • In “Creating a Hyper‐V VM,” you learn that once you have a VM host up and running, you can create a VM inside the host. You configure Hyper‐V Virtual Machine Networking. Then you look at configuring the VM network.
  • In “Using PowerShell Direct,” you configure and use the PowerShell Direct (PS Direct) feature to manage a VM without network connectivity. PS Direct enables you to run scripts inside a VM even if the VM does not have networking configured. This is a useful part of setting up a VM.
  • In “Configuring VM Networking,” you configure Hyper‐V Virtual Machine Networking. Then you look at configuring the VM network.
  • In “Configuring VM Hardware,” you learn that once you have a VM created, you can use commands in the Hyper‐V Module to configure the virtual hardware on your VMs.
  • In “Implementing Nested Virtualization,” you learn that nested virtualization allows you to install Hyper‐V inside a Hyper‐V VM, running a VM inside another VM. In this chapter, you explore nested virtualization by enabling this feature on the HVDirect VM and then adding the Hyper‐V role to the VM.
  • In “Using VM Checkpoints,” you learn that a checkpoint is a snapshot of a VM's state at a given time. You can create multiple checkpoints and move between them.
  • In “Using VM Replication,” you learn that Hyper‐V Replica (HVR) is a feature of Hyper‐V that creates a full replica of a VM for disaster recovery.
  • In “Managing VM Movement,” you learn that Hyper‐V allows you to move either a VM or a VM's storage to a different location or onto a different host.
  • In “Measuring VM Resource Usage,” you look at monitoring resources used by a VM. In this final section, you learn how to monitor the resources that each VM uses.

Systems Used in This Chapter

This chapter uses three hosts:

Figure 8.1 shows the systems in use in this chapter.

image

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.

Installing and Configuring Hyper‐V

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.

Before You Start

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

Installing the Hyper‐V Feature on 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.

image

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.

Rebooting HV1

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 

Creating Folders to Hold VM Disks and VM Details

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.

Building a Configuration Hash Table

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.

Reviewing Key VM Host Settings

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.

image

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.

Creating a Hyper‐V VM

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.

Before You Start

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.

Creating Variables

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.

Verifying That the ISO Image Exists

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.

Importing the DISM Module

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.

Mounting the ISO Image

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.

image

Figure 8.4: Mounting the ISO disk image

Viewing ISO Image Contents

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.

image

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.

Creating a New VM in HV1

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.

image

Figure 8.6: Creating a new VM

Creating a VHDX File for the 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

Adding the VHD to the VM

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.

Adding the ISO Image to the VM

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.

Starting the VM

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 

Installing Windows Server 2019

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).

Viewing the Results

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.

image

Figure 8.7: Viewing newly created VM details

Using PowerShell Direct

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.

Before You Start

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.”

Creating Variables for Use in This Section

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.

Displaying Details of HVDirect VM

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.

image

Figure 8.8: Displaying VM details

Invoking a Command using VMName

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.

image

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.

Invoking a Command Based on VM ID

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.

image

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.”

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.

Before You Start

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.

Getting Virtual NIC Details from HVDirect

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.

image

Figure 8.11: Viewing NIC details

Creating a Credential for the VM

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.

Getting NIC Details

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.

image

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.

Creating a Virtual Switch

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.

image

Figure 8.13: Creating a virtual switch

Connecting the VM to the 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.

Enabling MAC Spoofing

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.

Viewing VM Network Information

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.

image

Figure 8.14: Viewing the virtual NIC configuration

Viewing IP Address Inside HVDirect

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.

image

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).

Joining the Reskit 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.

image

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.

Rebooting the VM

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.

Getting the Host Name of the HVDirect VM

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.

image

Figure 8.17: Obtaining the host name

Now that you have joined the HVDirect 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.

Configuring VM Hardware

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.

Before You Start

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.”

Turning Off the HVDirect VM

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.

image

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

.

Setting the Hardware Startup Order

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.

image

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.

Setting Socket Count

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.

image

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.

Setting VM Memory

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.

image

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.

Adding an SCSI Controller

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.

image

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.

Restarting the VM

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.

Creating a New Virtual Disk

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.

image

Figure 8.23: Creating a new virtual disk

Because this is for demonstration and not production use, you define a maximum size of 8GB.

Adding a Disk to a VM

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.”

Viewing SCSI Disks inside HVDirect

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.

image

Figure 8.24: Viewing SCSI disks

Implementing Nested Virtualization

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.

Before You Start

This section uses the HVDirect VM, which you set up in “Creating a Hyper‐V VM.”

Stopping HVDirect 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

Configuring Virtual Processor

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.

image

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.

Enabling MAC Address Spoofing

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.

Restarting the VM

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.

image

Figure 8.26: Restarting HVDirect

Creating Credentials

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

Installing Hyper‐V in HVDirect VM

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.

image

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.

Restarting the VM

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.

image

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.

Checking Hyper‐V in HVDirect

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.

image

Figure 8.29: Examining Hyper‐V within HVDirect

Using VM Checkpoints

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.

Before You Start

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).

Creating Credentials

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

Examining C: in the HVDirect VM

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.

image

Figure 8.30: Examining the HVDirect C: drive

Creating a Checkpoint

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.

Examining the Checkpoint Files

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.

image

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.

Creating Content in HVDirect

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.

image

Figure 8.32: Creating content on HVDirect

Taking a Second Checkpoint

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

Viewing Checkpoint Details for HVDirect

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.

image

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.

Examining Files Supporting Checkpoints

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.

image

Figure 8.34: Viewing checkpoint files

As you can see, there are now two differencing disks for each of the original VHDX files.

Creating Another File in HVDirect

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.

Reverting to Checkpoint1

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
image

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.

Viewing VM Files

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.

image

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.

Rolling Forward to Checkpoint2

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.

Viewing VM Files After Rolling Forward

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.

image

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.

Viewing Checkpoints in the VM

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.

image

Figure 8.38: Viewing checkpoints for HVDirect

Removing Checkpoints

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.

Checking VM Data Files after Removing Checkpoints

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.

image

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.

Using VM Replication

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 HVDirect 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.

Before You Start

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.

Configuring HV1 and HV2 for Delegation

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 /.

Rebooting HV1 and HV2

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

Setting VMReplication

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

Enabling Replication from the Source VM

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.

Viewing VM Replication Status

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.

image

Figure 8.40: Viewing replication status

Viewing VM 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.

image

Figure 8.41: Viewing VM status

Initiating Replication

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.

Examining Initial Replication State

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.

image

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.

Viewing Replication

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.

image

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.

Testing Replica Failover

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.

Viewing VM Status on HV2 after Failover

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.

image

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.

Getting VM Details from HV1

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.

image

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.

Getting VM Details from HV2

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.

image

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.

Stopping the Failover Test

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.

Viewing VM Status

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.

image

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.

Setting Failover IP Address for VM Failover

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.

Stopping HVDirect on HV1

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.

Starting Failover from HV1 to HV2

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.

  • To start a planned failover of a VM
  • To create a test virtual machine on a replica virtual machine
  • To failover a replica virtual machine to a chosen recovery point

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.

Completing the Failover of HVDirect

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.

Starting the Failover VM

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.

Checking VM Status After Failover

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.

image

Figure 8.48: Checking VM status after failover

Testing Failover VM Networking

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.

image

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.

Managing VM Movement

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.

Before You Start

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

Viewing the HVDirect VM

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.

image

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.

Getting VM Configuration Location

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.

image

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.

Getting VM Hard Drive Locations

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.

image

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.

Migrating VM Storage

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.

Viewing Configuration Details

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.

image

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.

Viewing VMs on HV2

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.

Enabling VM Migration

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.

Configuring VM Migration

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.

Migrating a VM Between Hosts

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.

Displaying Migration Time

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.

image

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.

Checking VMs on HV1

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.

Checking VMs on HV2

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.

image

Figure 8.55: Viewing the VMs on HV2

In this case, you should see the HVDirect VM is now running on HV2.

Examining Virtual Disk Details

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.

image

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.

Measuring VM Resource Usage

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:

  • Average CPU usage
  • Average physical memory usage
  • Minimum memory usage
  • Maximum memory usage
  • Maximum amount of disk space allocated to a virtual machine
  • Total incoming network traffic
  • Total outgoing network traffic

Before You Start

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”).

Getting VM Details

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.

image

Figure 8.57: Examining VM details

You should see, in this figure, just one VM, HVDirect.

Enabling VM Resource Monitoring

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.

Starting the HVDirect VM

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.

Creating Credentials for HVDirect

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.

Getting Initial Resource Measurements

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.

image

Figure 8.58: Measuring VM resource usage

Performing Compute Work

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.

Measuring VM Resource Usage Again

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.

image

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.

Summary

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.