Set (or inject) guest network IP configuration from Hyper-V host to Ubuntu 18.04 VM

Posted: February 12, 2020 in Linux, Windows Server

Below script worked fine up to Ubuntu 18 because that distro introduced netplan.

Function Set-VMNetworkConfiguration {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true,
                   Position=1,
                   ParameterSetName='DHCP',
                   ValueFromPipeline=$true)]
        [Parameter(Mandatory=$true,
                   Position=0,
                   ParameterSetName='Static',
                   ValueFromPipeline=$true)]
        [Microsoft.HyperV.PowerShell.VMNetworkAdapter]$NetworkAdapter,
 
        [Parameter(Mandatory=$true,
                   Position=1,
                   ParameterSetName='Static')]
        [String[]]$IPAddress=@(),
 
        [Parameter(Mandatory=$false,
                   Position=2,
                   ParameterSetName='Static')]
        [String[]]$Subnet=@(),
 
        [Parameter(Mandatory=$false,
                   Position=3,
                   ParameterSetName='Static')]
        [String[]]$DefaultGateway = @(),
 
        [Parameter(Mandatory=$false,
                   Position=4,
                   ParameterSetName='Static')]
        [String[]]$DNSServer = @(),
 
        [Parameter(Mandatory=$false,
                   Position=0,
                   ParameterSetName='DHCP')]
        [Switch]$Dhcp
    )
 
    $VM = Get-WmiObject -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' | Where-Object { $_.ElementName -eq $NetworkAdapter.VMName } 
    $VMSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' }    
    $VMNetAdapters = $VMSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData') 
 
    $NetworkSettings = @()
    foreach ($NetAdapter in $VMNetAdapters) {
        if ($NetAdapter.Address -eq $NetworkAdapter.MacAddress) {
            $NetworkSettings = $NetworkSettings + $NetAdapter.GetRelated("Msvm_GuestNetworkAdapterConfiguration")
        }
    }
 
    $NetworkSettings[0].IPAddresses = $IPAddress
    $NetworkSettings[0].Subnets = $Subnet
    $NetworkSettings[0].DefaultGateways = $DefaultGateway
    $NetworkSettings[0].DNSServers = $DNSServer
    $NetworkSettings[0].ProtocolIFType = 4096
 
    if ($dhcp) {
        $NetworkSettings[0].DHCPEnabled = $true
    } else {
        $NetworkSettings[0].DHCPEnabled = $false
    }
 
    $Service = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace "root\virtualization\v2"
    $setIP = $Service.SetGuestNetworkAdapterConfiguration($VM, $NetworkSettings[0].GetText(1))
 
    if ($setip.ReturnValue -eq 4096) {
        $job=[WMI]$setip.job 
 
        while ($job.JobState -eq 3 -or $job.JobState -eq 4) {
            start-sleep 1
            $job=[WMI]$setip.job
        }
 
        if ($job.JobState -eq 7) {
            write-host "Success"
        }
        else {
            $job.GetError()
        }
    } elseif($setip.ReturnValue -eq 0) {
        Write-Host "Success"
    }
}

Usage:

Get-VMNetworkAdapter -VMName Ubuntu18| Set-VMNetworkConfiguration -IPAddress 192.168.1.238 -Subnet 255.255.255.0 -DNSServer 8.8.8.8 -DefaultGateway 192.168.1.1

 

Netplan is based on YAML based configuration system that makes configuration process very simple. Netplan has replaced the old configuration file /etc/network/interfaces that we previously used for configuring network interfaces in Ubuntu.

As result, i wasn’t able to set Ubuntu 18.04 VM IP address from Hyper-V host.

Install Hyper-V tools on Ubuntu VM:

sudo apt-get update 
sudo apt-get install linux-image-virtual linux-tools-virtual linux-cloud-tools-virtual
sudo reboot now

Check if Hyper-V daemon is running:

systemctl status hv-kvp-daemon
● hv-kvp-daemon.service - Hyper-V KVP Protocol Daemon
   Loaded: loaded (/lib/systemd/system/hv-kvp-daemon.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-02-12 09:07:53 UTC; 37min ago
 Main PID: 1463 (hv_kvp_daemon)
    Tasks: 1 (limit: 1054)
   CGroup: /system.slice/hv-kvp-daemon.service
           └─1463 /usr/lib/linux-tools/4.15.0-76-generic/hv_kvp_daemon -n

Check if there is any error message:

tail /var/log/syslog

If you get following errors:

sh: 1: /usr/libexec/hypervkvpd/hv_get_dns_info: not found
sh: 1: /usr/libexec/hypervkvpd/hv_get_dhcp_info: not found

Copy hyper-v daemon binaries to location mentioned in errors:

find /usr/|grep hv_set_ifconfig
/usr/src/linux-headers-4.15.0-55/tools/hv/hv_set_ifconfig.sh
/usr/sbin/hv_set_ifconfig
mkdir -p /usr/libexec/hypervkvpd/
cp /usr/sbin/hv_* /usr/libexec/hypervkvpd
systemctl restart hv-kvp-daemon

Disabling netplan

/usr/sbin/hv_set_ifconfig is python script which accepts IP, address, default gateway, network mask and DNS server as input parameters from Hyper-V host and edit /etc/network/interfaces file. I tried changing python script to edit /etc/netplan/50-cloud-init.yaml but it doesn’t work from Hyper-V host, so i disabled netplan completely

Edit /etc/default/grub file and add following line:

GRUB_CMDLINE_LINUX="netcfg/do_not_use_netplan=true"

update grub configuration

update-grub

Remove netplan and config files:

apt purge netplan.io
rm -rf /usr/share/netplan/*
rm -rf /etc/netplan/*

Install ifupdown

apt install ifupdown

Configure interface:

vi /etc/network/interfaces

auto eth0
iface eth0 inet static
address 192.168.0.10
netmask 255.255.255.0
gateway 192.168.0.1
broadcst 192.168.0.255
dns-nameservers 192.168.0.2 192.168.0.3
dns-search lan

Although we specified DNS servers in /etc/network/interfaces, it will be overwritten on reboot, to set DNS server permanently, edit /etc/systemd/resolved.conf :

[Resolve]
DNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844

Reboot Ubuntu VM

shutdown -r now

Now try to change IP address using Powershell code from begining of this post and you should be able to change Ubuntu 18 VM IP address

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s