I trolled the forums for some time, looking to see if anyone had put VyOS on Hyper-V. I saw several attempts and one deal-breaker: VyOS running Debian Wheezy (7.something) will install and recognize the non-legacy vNICs of Hyper-V 2012 R2, but during a reboot or reset network connectivity will be severed on all vNICs using VLANs. There are two ways to get around this flaw:
- Reapply the VLAN settings while the VyOS VM is up and running or…
- Completely shut down and boot the VyOS VM.
I decided to automate option #1 and here’s how I did it…
[list=1]
[]Pull down the latest Wheezy-Transit build. I got mine from here. Put the VyOS Wheezy Live ISO on your Hyper-V server.
[]Open Hyper-V Manager. Create a new VM.
[list]
[]Name: VyOS
[]1 vCPU
[]512 MB RAM
[]1x 8GB VHD
[]1x DVD Drive
[]2x vNIC - Non-Legacy
[/list]
[]Open the properties for this VM and…
[list]
[]“Mount” the Live CD ISO in the DVD Drive
[]Assign the 1st vNIC to a Virtual Switch that connects to a physical NIC on the Hyper-V server
[]Assign the 2nd vNIC to a Virtual Switch that is Internal-only
[/list]
[]Boot the VM
[]Log in to the VM
[list]
[]vyos/vyos
[/list]
[]Run this command “install system”. NOTE: I tried the recommended path of “install image” but the Debian Live image failed to boot. It dumped me out to an “(initramfs)” prompt. I tried “install image” twice before going with “install system”.
[]Follow the prompts to continue/finish the installation
[]Run this command “poweroff”
[]When powered off, unmount the ISO
[]Power on the VyOS VM
[]Type “cat /etc/debian_version”. Make sure you are at 7.0 at least.
[]Execute the following commands in the VyOS console:[code]
configure
edit interfaces ethernet eth0
set description ‘External_Network’
set address 192.168.1.10/24
set duplex auto
set speed auto
commit
exit
edit interfaces ethernet eth1
set description 'VLAN_Trunk'
delete address
set duplex auto
set speed auto
commit
exit
# Set up VLANs
# VLAN 30
set interfaces ethernet eth1 vif 30 description 'VLAN 30'
set interfaces ethernet eth1 vif 30 address '192.168.30.1/24'
# Set System Parameters
set system domain-name Domain.com
set system host-name VyOS
set system name-server 192.168.1.1
commit
save
exit
reboot
[/code]
[]Open a PowerShell window with Administrative Rights on the Hyper-V host.
[]Execute this command to list all NICs on your VyOS VM:
Get-VMNetworkAdapter -VMName 'VyOS'
[*]Add a “WHERE” clause to filter the list to just the NIC that is connected to the Internal-only virtual switch. In my example, my Internal-only virtual switch is called “Tenant Logical Switch”.
Get-VMNetworkAdapter -VMName 'VyOS' | WHERE {$_.SwitchName -ieq 'Tenant Logical Switch'}
[*]Pipe this returned object into ‘Get-VMNetworkAdapterVLAN’ to see which VLANs (if any) are currently assigned to this vNIC.
Get-VMNetworkAdapter -VMName 'VyOS' | WHERE {$_.SwitchName -ieq 'Tenant Logical Switch'} | Get-VMNetworkAdapterVlan
[*]Pipe this returned object into ‘Set-VMNetworkAdapterVLAN’ to enable VLAN Trunking on this vNIC.
Get-VMNetworkAdapter -VMName 'VyOS' | WHERE {$_.SwitchName -ieq 'Tenant Logical Switch'} | Set-VMNetworkAdapterVlan -Trunk -NativeVlanId 0 -AllowedVlanIdList 1-4094
[*]Create this PowerShell file on the Hyper-V host:[code]
<# This script is triggered by, and executed by the Task Scheduler.
Log: Microsoft-Windows-Hyper-V-Worker/Admin
Source: Hyper-V-Worker
Event ID: 18512 & 18514
This is an entry that gets made in the Event Log when the VM is rebooted from the Hyper-V console from a running state:
Log Name: Microsoft-Windows-Hyper-V-Worker-Admin
Source: Microsoft-Windows-Hyper-V-Worker
Date: 4/9/2014 12:31:13 AM
Event ID: 18512
Task Category: None
Level: Information
Keywords:
User: NT VIRTUAL MACHINE\6D4B300A-49C9-4B73-8734-C404427E73BB
Computer: HyperVHost.Domain.com
Description:
‘VyOS’ was reset. (Virtual machine ID 6D4B300A-49C9-4B73-8734-C404427E73BB)
Event Xml:
18512
0
4
0
0
0x8000000000000000
568
Microsoft-Windows-Hyper-V-Worker-Admin
HyperVHost.Domain.com
VyOS
6D4B300A-49C9-4B73-8734-C404427E73BB
This is an entry that gets made when the VM is rebooted from within the OS from a running state:
Log Name: Microsoft-Windows-Hyper-V-Worker-Admin
Source: Microsoft-Windows-Hyper-V-Worker
Date: 4/9/2014 12:24:23 AM
Event ID: 18514
Task Category: None
Level: Information
Keywords:
User: NT VIRTUAL MACHINE\6D4B300A-49C9-4B73-8734-C404427E73BB
Computer: HyperVHost.Domain.com
Description:
‘VyOS’ was reset by the guest operating system. (Virtual machine ID 6D4B300A-49C9-4B73-8734-C404427E73BB)
Event Xml:
18514
0
4
0
0
0x8000000000000000
561
Microsoft-Windows-Hyper-V-Worker-Admin
HyperVHost.Domain.com
VyOS
6D4B300A-49C9-4B73-8734-C404427E73BB
This is an entry that gets made when the VM is booted fresh.
There is no need to execute this code on this Event Log ID.
Log Name: Microsoft-Windows-Hyper-V-Worker-Admin
Source: Microsoft-Windows-Hyper-V-Worker
Date: 4/9/2014 12:26:29 AM
Event ID: 18500
Task Category: None
Level: Information
Keywords:
User: NT VIRTUAL MACHINE\6D4B300A-49C9-4B73-8734-C404427E73BB
Computer: HyperVHost.Domain.com
Description:
‘VyOS’ started successfully. (Virtual machine ID 6D4B300A-49C9-4B73-8734-C404427E73BB)
Event Xml:
18500
0
4
0
0
0x8000000000000000
565
Microsoft-Windows-Hyper-V-Worker-Admin
HyperVHost.Domain.com
VyOS
6D4B300A-49C9-4B73-8734-C404427E73BB
#>
$Rebooted_VMs = Get-VM | WHERE {$.State -eq ‘Running’ -and $.UpTime -lt ([TimeSpan]‘00:00:10’)};
ForEach ($VM in $Rebooted_VMs) {
$vNICs = Get-VMNetworkAdapter -VMName $VM.Name;
ForEach ($vNIC in $vNICs){
$VLAN_Properties = Get-VMNetworkAdapterVLAN -VMNetworkAdapter $vNIC;
Switch ($VLAN_Properties.OperationMode) {
('Trunk') { Set-VMNetworkAdapterVLAN -VMNetworkAdapter $vNIC `
-Trunk `
-AllowedVlanIdList ($VLAN_Properties.AllowedVlanIdListString) `
-NativeVlanID ($VLAN_Properties.NativeVlanID) }
('Isolated') { Set-VMNetworkAdapterVLAN -VMNetworkAdapter $vNIC `
-Isolated `
-PrimaryVlanId ($VLAN_Properties.PrimaryVlanID) `
-SecondaryVlanID ($VLAN_Properties.SecondaryVlanID)}
('Promiscuous') { Set-VMNetworkAdapterVLAN -VMNetworkAdapter $vNIC `
-Isolated `
-PrimaryVlanId ($VLAN_Properties.PrimaryVlanID) `
-SecondaryVlanIDList ($VLAN_Properties.SecondaryVlanIDListString)}
('Access') { Set-VMNetworkAdapterVLAN -VMNetworkAdapter $vNIC `
-Access `
-VlanID $VLAN_Properties.AccessVlanID }
('Untagged') { Set-VMNetworkAdapterVLAN -VMNetworkAdapter $vNIC `
-Untagged }
}
}
}[/code]
[]Save the PowerShell code as ‘Scheduled_Task-Run_When_VM_Reboots.ps1’.
[]Place the PowerShell script somewhere on the Hyper-V host’s local drives. On my server, I placed it in ‘E:\Hyper-V\Scripts’.
[]Open Notepad on the Hyper-V server
[]Copy this code and paste it into Notepad:<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2014-04-09T16:04:55.0777598</Date>
<Author>The_Gecko</Author>
<Description>A Hyper-V VM warm-cycled, not a full power cycle, but a reset or reboot. Execute these commands when that event happens.</Description>
</RegistrationInfo>
<Triggers>
<EventTrigger>
<Enabled>true</Enabled>
<Subscription><QueryList><Query Id="0" Path="Microsoft-Windows-Hyper-V-Worker-Admin"><Select Path="Microsoft-Windows-Hyper-V-Worker-Admin">*[System[Provider[@Name='Microsoft-Windows-Hyper-V-Worker'] and EventID=18512]]</Select></Query></QueryList></Subscription>
</EventTrigger>
<EventTrigger>
<Enabled>true</Enabled>
<Subscription><QueryList><Query Id="0" Path="Microsoft-Windows-Hyper-V-Worker-Admin"><Select Path="Microsoft-Windows-Hyper-V-Worker-Admin">*[System[Provider[@Name='Microsoft-Windows-Hyper-V-Worker'] and EventID=18514]]</Select></Query></QueryList></Subscription>
</EventTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>Queue</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe</Command>
<Arguments>"E:\Hyper-V\Scripts\Scheduled_Task-Run_When_VM_Reboots.ps1"</Arguments>
</Exec>
</Actions>
</Task>
[]Down near the bottom of this code you will find a reference to “E:\Hyper-V\Scripts\Scheduled_Task-Run_When_VM_Reboots.ps1”. Edit this path to point to the location where you saved the PowerShell script created above.
[]Save this file as “Commands Executed on a VM Warm-Cycle.xml”
[]Start “Task Scheduler” on the Hyper-V host
[]Go to Action → Import Task
[]Point it towards the XML file you just created.
[]Done!
[/list]
Time to test if it works:
[list=1]
[]Create another VM
[]Open the Hyper-V properties for the second VM
[list]
[]Make sure that second VM has a non-legacy vNIC
[]Connect the second VM’s vNIC to the Internal-only Virtual Switch
[]Enable virtual LAN Identification
[]Set the VLAN to 30
[/list]
[]Log in to the second VM
[]Assign the second VM’s vNIC an IP address of 192.168.30.2
[]Ping the VyOS VM (192.168.30.1): “ping -t 192.168.30.1”
[]Reboot the VyOS VM
[*]Watch the pings fail during the reboot cycle and begin to succeed again during the VyOS boot process
[/list]
This process was developed on a Dell R710 server running Windows Server 2012 R2. Fortunately, what you see here will run on all flavors of Windows Server 2012 R2, including the free Hyper-V 2012 R2 Hypervisor.
If I have made any mistakes or was not clear about any particular step, please send me a PM with the problem (and with a correction if you can provide one) and I will correct this post. I strive for completeness and correctness.
Edited on 2014-04-11 10:20 AM EST - Fixed duplicate “eth0” commands. Added “exit” commands. Changed “system install” to “install system” and added notes about “install image” experiences.