Monday, September 26, 2011

Connecting GNS3 and Microsoft Hyper-V

Most network administrators identify complex pieces of their networks that they would prefer to test changes in a lab environment with. This can include everything from simple routing changes to complex issues involving Network Address Translation, Policy Based Routing, Quality of Service, and complex access control lists and tunneling.  With the world becoming more virtual and the cost of downtime increasing, companies and individuals are increasingly looking to sophisticated, cost effective alternatives to maintaining a complete separate lab environment. One example of an alternative to a physical lab environment is to create a virtualized test environment using Dynamips/GNS3.

Dynamips/GNS3 allows network engineers to test complex pieces of routing configurations in an environment running actual Cisco IOS before putting changes into production that could disrupt network operation and cost the company thousands (or millions) of dollars. Out of the box, it is not always possible to test specific configurations, particularly if the desired changes affect routing, filtering, or NAT between specific hosts. Another piece that is missing from a straight Dynamips/GNS3 environment is the simulation of actual traffic flows between endpoints. This becomes especially important when dynamic ports are being used for applications such as SQL Server or Microsoft RPC/DCOM.

Utilizing Dynamips/GNS3 along with Hyper-V allows a true end-to-end simulation of an application environment to test/debug routing configuration changes. The routing environment (or at least the critical pieces) can be created using the routers/IOS images that are compatible with GNS3 and the cloud object in GNS3 can be configured to bridge to a network adapter on the system. An Internal virtual network (one that allows connectivity between the host system and VMs) allows a virtual network adapter to be created in the OS that can be assigned an IP address and  connected to the GNS3 topology using the cloud object.

Internal networks in Hyper-V resemble managed switches because they allow a number of VMs (and the host system) to communicate and allow individual host network adapters to have VLAN tagging enabled. This allows an easy test of a router-on-a-stick configuration or allows the network model to be condensed in GNS3 and Hyper-V to save resources on the host system.

After the Internal network is created in the Virtual Network Manager of Hyper-V, the network can be included in the GNS3 topology and the virtual machines can communicate across the virtual network in GNS3.

In this example, I have attached a Cisco 3725 to my virtual network supporting my Exchange 2010 test system and a DC. I simply configured the fa0/0 interface to communicate with the other nodes and communication can occur regularly.

Using the combination of Hyper-V and GNS3 is particularly valuable because it allows end-to-end testing and verification of routing configuration and allows production traffic to be truly simulated by creating VMs with identical applications/configuration and testing the impact of changes on the traffic between systems.  Although this does not provide a complete solution from a switching configuration viewpoint, most of the changes that have a high impact on the network occur on routers and firewalls, both of which can be effectively simulated using GNS3.

Emulating a Managed Switch With Dynamips/GNS3

Background

These script snippets and the final script help solve the problem of not having a centralized way of rebooting a set of systems. This require WMI (default TCP port 135) to function between the system that is initiating the reboot and the system that is being rebooted. Additionally, the account that is running the script (or scheduled task) requires permissions to reboot the system. This requires the "Force shutdown from a remote system" right that is given to the Administrators group by default (and also to the domain Server Operators group on domain controllers).

Expansion of an IP Range

I created a function called ExpandRange:
function ExpandRange([string] $network, [int]$start, [int] $end) {$retval = @()

while ($start -le$end) {
$temp =$network + $start$retval += $temp$start++
}

return $retval }  This function does little more than take a string argument, a start, and an end, and iterates through and returns an array of the string and each number in the range appended. This is especially straightforward for Class C network addresses: #Returns array holding 192.168.0.1 to 192.168.0.254$hosts += ExpandRange -network "192.168.0." -start 1 -end 254  
Expanding class A, B, and C networks follows from running the ExpandRange function multiple times building from the first octet to the last octet. Classless ranges require performing a little bit of math to figure out the start and end IP addresses, but are also very simple using the start and end parameters.

Performing the Reboot

The Win32_OperatingSystem WMI class has two methods of interest with regard to reboots and shutdown: The reboot() method and the Win32Shutdown(int) method. Another method also exists for organizations that need to specify reasons for reboots, Win32ShutDownTracker. The reboot() method will not force a reboot (if applications block the system from shutting down), but the Win32Shutdown method can force a reboot. The integer parameter that is currently used breaks down as follows:

 Bit position (value) Meaning 0 (0) Log off 1 (1) Shut down 2 (2) Reboot 3 (4) Force action 4 (8) Power off

It follows from this table that a forced reboot would be 2 + 4 = 6. In PowerShell, the method can be invoked using the Get-WMIObject cmdlet. Using the -ComputerName option allows the WMI class instance to be retrieved from multiple systems. To perform the reboot:
Get-WmiObject -computername $i Win32_OperatingSystem -ErrorAction SilentlyContinue | ForEach-Object {$_.Win32Shutdown(6)}

Make it Run Faster With Concurrency

Unfortunately, just doing a Foreach-Object of the array that is built from the ExpandRange function above is a O(n) operation. This can be slow waiting for unreachable IP addresses to time out and a sparsely populated IP range can cause a script to run for a very long time. Using jobs in powershell allows this to become a number of smaller O(n) operations running concurrently.
while ($hosts.count -gt 0) { #split list into smaller lists$dispatch = @()

#Full blocks of $job_size if ($hosts.count -gt $job_size) {$dispatch = $hosts[0 .. ($job_size - 1)]
$hosts =$hosts[$job_size .. ($hosts.count-1)]
}
#Partial blocks (there should either be 0 or 1 of these)
else {
$dispatch =$hosts
$hosts = @() } #reboot the smaller block of hosts in a separate job and continue kicking off reboots of other hosts Start-Job -InputObject$dispatch -ScriptBlock {
foreach ($i in$Input.'<>4__this'.Read()) {
#Perform the Reboot
Get-WmiObject -computername $i Win32_OperatingSystem -ErrorAction SilentlyContinue | ForEach-Object {$_.Win32Shutdown(6)}
}
}
}
Wait-Job *
Remove-Job *