A client I was working with was having an issue with their Virtual Machine (VM) running on Hyper-V. It was an odd one that I have never seen before. The VM was running Server 2008 R2 and had a single synthetic Virtual NIC attached with a static IP. The problem was that when the VM was restored from a saved state, occasionally, the network would not work. This obviously caused issues for users that needed to connect to the VM via RDP. Luckily, this VM did not completely rely on the Internet, so minor downtime when the VM was restored from a saved state wasn’t a major issue. Disconnecting and reconnecting the NIC in Hyper-V did not fix the issue, and ipconfig /renew wouldn’t fix anything since the IP address was static. The only thing the admin was able to do to temporarily fix the issue (until the next saved state restore) was to log into the VM via Hyper-V console and disable and then enable the NIC that was having issues. Unfortunately, time was a factor in finding a solution, and I was unable to physically see the hardware or VM in action. This made it very difficult to figure out what was causing the issue in the first place. A workaround seemed to be a much better use of time than spending hours trying to deduce the problem via E-mail.
The restore action for the saved state was done by via script. So it would be very easy to tie in another script to essentially disable and enable the NIC after the VM was restored. From what I can tell, this can’t be done using the Hyper-V Powershell APIs from the host. Also, since the network was the problem, I couldn’t run a remote script from the host to fix the NIC. Anything that could be done would have to be done within the VM. Granted this is not a solution to the original problem, but a workaround, and given more time we would have looked into what the actual cause was. So, here is the workaround to the problem.
Start-Sleep -s 60 foreach ($adapter in get-wmiobject win32_networkadapter | where {$_.MACAddress.length -gt 0}) { Write-Host $adapter.ServiceName $adapter.disable() Start-Sleep -s 5 $adapter.enable() }
I placed that code in a ps1 file within the VM. Started the script and immediately took another saved state snapshot.
Here is how it works. The first line of code adds a 60 timer.That means I have 60 seconds from starting the script to take and complete a saved state snapshot. At whenever time later, when the VM is restored from the saved state it will continue to count down the timer. Once the timer has finished, the script will look through all of the network adapters that have MAC addresses (i.e. none of those tunnel adapters) and it will then disable and enable them. Thus re-allowing stable RDP connections to the actual NICs in the VM.
Chances are people finding this post will have a different need for the script than my use. So, the slimmed down version without all the sleeping and writing to console is:
foreach ($adapter in get-wmiobject win32_networkadapter | where {$_.MACAddress.length -gt 0}) { $adapter.disable() $adapter.enable() }