hashicorp / packer-plugin-hyperv

Packer plugin for Hyper-V Builder
https://www.packer.io/docs/builders/hyperv
Mozilla Public License 2.0
19 stars 24 forks source link

Incorrect IP address used for retrieving preseed config (stuck on blue screen) #99

Open jshbrntt opened 1 year ago

jshbrntt commented 1 year ago

Overview of the Issue

When attempting to build the following debian-11 template with Packer, found here in the Microsoft/MSLab-templates repository.

The build will get stuck on Waiting for SSH to become available... due to it attempting to retrieve the debian-11-preseed.cfg from the incorrect IP address.

The plugin currently obtains the IP address used to specify the URL to the debian-11-preseed.cfg file here in the following PowerShell command.

param([string]$switchName, [int]$addressIndex)
$HostVMAdapter = Hyper-V\Get-VMNetworkAdapter -ManagementOS -SwitchName $switchName | Select-Object -First 1
if ($HostVMAdapter){
  $HostNetAdapter = Get-NetAdapter | Where-Object { $_.DeviceId -eq $HostVMAdapter.DeviceId }
  if ($HostNetAdapter){
    $HostNetAdapterConfiguration = @(Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $HostNetAdapter.InterfaceIndex | Where-Object SuffixOrigin -notmatch "Link")
    if ($HostNetAdapterConfiguration){
      return @($HostNetAdapterConfiguration.IpAddress)[$addressIndex]
    }
  }
} else {
  $HostNetAdapterConfiguration=@(Get-NetIPAddress -CimSession $env:computername -AddressFamily IPv4 | Where-Object { ( $_.InterfaceAlias -notmatch 'Loopback' ) -and ( $_.SuffixOrigin -notmatch "Link" )})
  if ($HostNetAdapterConfiguration) {
    return @($HostNetAdapterConfiguration.IpAddress)[$addressIndex]
  } else {
    return $false
 }
}

Reproduction Steps

When running the following part of the PowerShell script on my host machine, I get the following output.

PS C:\Users\jshbrntt> Hyper-V\Get-VMNetworkAdapter -ManagementOS -SwitchName 'Default Switch'

Name                   IsManagementOs VMName SwitchName     MacAddress   Status IPAddresses
----                   -------------- ------ ----------     ----------   ------ -----------
Container NIC a4f898fb True                  Default Switch 00155DFDCF45 {Ok}
Container NIC a8fe71a1 True                  Default Switch 00155D3A43A4 {Ok}

The second part of the command pipes this output to Select-Object -First 1 so it returns first object return by the prior command.

However, there are two network adapters on my system configured by Hyper-V.

PS C:\Users\jshbrntt> $HostVMAdapter1 = Hyper-V\Get-VMNetworkAdapter -ManagementOS -SwitchName 'Default Switch' | Select-Object -First 1
PS C:\Users\jshbrntt> $HostVMAdapter2 = Hyper-V\Get-VMNetworkAdapter -ManagementOS -SwitchName 'Default Switch' | Select-Object -Skip 1
PS C:\Users\jshbrntt> Get-NetAdapter -IncludeHidden | Where-Object { $_.DeviceId -eq $HostVMAdapter1.DeviceId }

Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
----                      --------------------                    ------- ------       ----------             ---------
vEthernet (nat)           Hyper-V Virtual Ethernet Adapter             58 Up           00-15-5D-FD-CF-45        10 Gbps

PS C:\Users\jshbrntt> Get-NetAdapter -IncludeHidden | Where-Object { $_.DeviceId -eq $HostVMAdapter2.DeviceId }

Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
----                      --------------------                    ------- ------       ----------             ---------
vEthernet (Default Swi... Hyper-V Virtual Ethernet Adapter #2          63 Up           00-15-5D-3A-43-A4        10 Gbps

You can see that because selects the vEthernet (nat) adapter it then goes on to use the incorrect IP address in the preseed URL.

PS C:\Users\jshbrntt> ipconfig
#...
Ethernet adapter vEthernet (Default Switch):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::4cb5:7bcd:a676:346d%63
   IPv4 Address. . . . . . . . . . . : 172.26.208.1
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   Default Gateway . . . . . . . . . :
#...
Ethernet adapter vEthernet (nat):

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::d945:a2e:a496:eb94%58
   IPv4 Address. . . . . . . . . . . : 172.26.160.1
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   Default Gateway . . . . . . . . . :

packer build log

PS D:\git\MSLab-templates\templates\debian-11> packer build -var "ssh_key=$env:PUBLIC_SSH_KEY" -var "iso_path=https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.6.0-amd64-netinst.iso" .
Warning: A checksum of 'none' was specified. Since ISO files are so big,
a checksum is highly recommended.

  on debian-11.pkr.hcl line 66:
  (source code not available)

hyperv-iso.debian-11: output will be in this color.

==> hyperv-iso.debian-11: Creating build directory...
==> hyperv-iso.debian-11: Retrieving ISO
==> hyperv-iso.debian-11: Trying https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.6.0-amd64-netinst.iso
==> hyperv-iso.debian-11: Trying https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.6.0-amd64-netinst.iso
==> hyperv-iso.debian-11: https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-11.6.0-amd64-netinst.iso => D:\git\MSLab-templates\templates\debian-11\packer_cache\6dffeb8388737d92718e3b7ba4d339ba6e1335cb.iso
==> hyperv-iso.debian-11: Starting HTTP server on port 8079
==> hyperv-iso.debian-11: Creating switch 'Default Switch' if required...
==> hyperv-iso.debian-11:     switch 'Default Switch' already exists. Will not delete on cleanup...
==> hyperv-iso.debian-11: Creating virtual machine...
==> hyperv-iso.debian-11: Enabling Integration Service...
==> hyperv-iso.debian-11: Setting boot drive to os dvd drive D:\git\MSLab-templates\templates\debian-11\packer_cache\6dffeb8388737d92718e3b7ba4d339ba6e1335cb.iso ...
==> hyperv-iso.debian-11: Mounting os dvd drive D:\git\MSLab-templates\templates\debian-11\packer_cache\6dffeb8388737d92718e3b7ba4d339ba6e1335cb.iso ...
==> hyperv-iso.debian-11: Skipping mounting Integration Services Setup Disk...
==> hyperv-iso.debian-11: Mounting secondary DVD images...
==> hyperv-iso.debian-11: Configuring vlan...
==> hyperv-iso.debian-11: Determine Host IP for HyperV machine...
==> hyperv-iso.debian-11: Host IP for the HyperV machine: 172.26.160.1
==> hyperv-iso.debian-11: Starting the virtual machine...
==> hyperv-iso.debian-11: Waiting 3s for boot...
==> hyperv-iso.debian-11: Typing the boot command...
==> hyperv-iso.debian-11: Waiting for SSH to become available...

Typed boot command showing the incorrect preseed URL

boot-cmd

Stuck on blue screen

blue-screen

After it gets stuck you can connect to the virtual machine and press Alt + F2 to access a terminal.

Debugging with ping and wget

Then run the following commands to ascertain that the virtual machine cannot connect to the host using the vEthernet (nat) adapter's IP address (172.26.160.1), only when the vEthernet (Default Switch) adapter's IP address (172.26.208.1) is used can the preseed.cfg file be retrieved by the virtual machine.

ping-wget

Plugin and Packer version

PS C:\Users\jshbrntt> packer version
Packer v1.8.5

Your version of Packer is out of date! The latest version
is 1.8.6. You can update by downloading from www.packer.io/downloads

PS C:\Users\joshua.barnett> packer plugins installed
C:\Users\jshbrntt\AppData\Roaming\packer.d\plugins\github.com\hashicorp\hyperv\packer-plugin-hyperv_v1.0.4_x5.0_windows_amd64.exe

Simplified Packer Buildfile

https://github.com/microsoft/MSLab-templates/tree/48109b672dad7599d62c9771d22ce5711274e04e/templates/debian-11/debian-11.pkr.hcl

Operating system and Environment details

Edition         Windows 10 Pro
Version         22H2
Installed on    09/01/2023
OS build        19045.2728
Experience      Windows Feature Experience Pack 120.2212.4190.0

Log Fragments and crash.log files

machv commented 1 year ago

Hello @jshbrntt, I tried your proposed change on my machine (Windows 11, 22H2 [10.0.22621.1555]) and unfortunately with that updated command I am not getting any output at all:

PS C:\> Hyper-V\Get-VMNetworkAdapter -ManagementOS -SwitchName "Default Switch" | Get-VMNetworkAdapterIsolation | Where-Object { $_.IsolationMode -eq "Vlan" }
PS C:\>

I've checked and compared to your Windows instance I have only one adapter connected to Default Switch:

PS C:\> Hyper-V\Get-VMNetworkAdapter -ManagementOS -SwitchName "Default Switch"

Name                                           IsManagementOs VMName SwitchName     MacAddress   Status IPAddresses
----                                           -------------- ------ ----------     ----------   ------ -----------
Host Vnic C08CB7B8-9B3C-408E-8E30-5E16A3AEB444 True                  Default Switch 00155D005C79 {Ok}

PS C:\>

So I am not 100% sure this is the best fix. In order to repro your issue, what else have you installed that might be using Default Switch?

nywilken commented 1 year ago

Hi @jshbrntt thanks for opening up this change. From the read it appears that this fix is specific to the case where the default switch has multiple adapters, and agree with @machv that this may not be the best fix. I'm running the same build but with a single adapter in my Default Switch and run into the blue screen issue because it is not connected to an external network.

Have you considered creating a new virtual switch with just the natted adapter?