VMware

June 26, 2009

Finding and fixing VMs connected to missing port groups.

Yesterday someone took the liberty of upgrading one of my ESX servers that I use to run a virtual vSphere lab. Fortunately he was kind enough to preserve all of the VMs, and they were restored and re-registered after the upgrade.

There was one detail that he didn’t notice, which was that my virtual vSphere lab VMs were all connected to an internal network called “Internal”. When I got in today my lab didn’t work at all because there was no networking between vCenter and the ESX hosts or their shared storage. The network cards all said they were attached to the “Internal” network, but there was no Internal network! Fortunately this was pretty easy to fix with PowerCLI.

First, let’s look at a script that will identify any VM that is connected to a non-existent network:

# Search for VMs that are connected to a non-existent portgroup.
$pgNames = Get-VirtualPortGroup | Foreach { $_.Name }
Get-VM | Where { $_ | Get-NetworkAdapter | Where { $pgNames -notcontains $_.NetworkName } }

This code starts by getting a list of all portgroup names. Then it goes through all VMs and identifies any VM that has at least one network adapter connected to a non-existent portgroup. Note that this assumes we are connected directly to ESX. If you need to use something like this against vCenter you should do it on a host-by-host basis. Anyway, when I ran it here was the result:

shot1

These are all the VMs of my virtual lab. Now let’s go about fixing the problem. First, creating the Internal virtual switch and portgroup are pretty easy:

# Create the missing switch and portgroup.
New-VirtualSwitch -Name Internal
Get-VirtualSwitch -Name Internal | New-VirtualPortGroup -Name Internal

Now the portgroup exists but there is one last problem: the VMs are not actually connected to the portgroup. Again, pretty easy to fix.

# The guests that were powered on will still be disconnected, so connect them.
Get-VM | Get-NetworkAdapter | Where { $_.NetworkName -eq "Internal" } |
  Set-NetworkAdapter -Connected:$true -Confirm:$false

With that, everything is back to normal.

May 01, 2009

New stuff in the VI Toolkit Extensions: Part 1, Routing

One nice new addition to ESX 4 is the ability to manage the complete routing table through the API, something that you had to do through the service console in previous releases.

So, how does PowerCLI help with automating all of this? Well, not much, really, PowerCLI doesn’t have any cmdlets related to routing. But this wouldn’t be a very interesting blog post if that was the end of the story. The nice thing about PowerCLI is that it gives you full access to VMware’s extremely powerful platform, which makes it easy to fill in any missing pieces we haven’t gotten to yet.

We have such a thing in the form of the VI Toolkit Community Extensions. One of the recent additions to the extensions is a set of commands that give you total control over ESX routing, and in a way that is compatible with all of PowerCLI’s cmdlets.

The new functions are as follows:

Get-TkeVMHostRoute
New-TkeVMHostRoute
Remove-TkeVMHostRoute

This stuff will look familiar to anyone who has used our cmdlets. If you’ve used our cmdlets before, chances are these will work the way you expect them to without a great deal of additional learning. Once you load the extensions you can run help on any of these function names and get a listing of the options they support.

Below is a quick run-down on how this stuff works. The first and easiest thing to do is to see what routes you have. I have an ESX 4 host with an IP address of 192.168.1.11. The key thing to note is that Get-TkeVMHostRoute requires a VMHost argument, and also allows you to pipe it in. To get a listing of its routes I run:

Get-VMHost 192.168.1.11 | Get-TkeVMHostRoute

Here’s some sample output:

shot1

With ESX 4 there are 3 types of routes, host routes which apply to the host, console routes, which apply to the service console (you won’t have these if you use ESXi) and the routing table. Above you can see that I have a host route and 3 entries in my routing table, and that my default route is 192.168.1.1.

Let’s see what adding and removing routing table entries looks like. Let’s suppose I can use 192.168.1.254 to reach the 10.24.0.0/16 network. Here’s how to do it:

Get-VMHost 192.168.1.11 |
 New-TkeVMHostRoute -TableRoute -Network 10.24.0.0 -PrefixLength 16 `
 -Gateway 192.168.1.254

Pretty simple, really. Here are the results of that.

shot2

New-TkeVMHostRoute can handle all 3 types of routes. Run help New-TkeVMHostRoute to learn more about it.

To remove routes from the routing table, all you do is pipe a route into Remove-TkeVMHostRoute, like this:

Get-VMHost 192.168.1.11 | Get-TkeVMHostRoute |
 Where { $_.Network -eq "10.24.0.0" } | Remove-TkeVMHostRoute

shot3

Something that’s not immediately obvious is how you change the host or service console route, since there’s no Set-TkeVMHostRoute. In truth there should be a Set-TkeVMHostRoute and probably will be one at some point. But for now this can be done using New-TkeVMHostRoute, which will just override any existing settings.

shot4

Changing your service console IP is similar, except you will also need to specify your GatewayDevice. If you have multiple service console IPs you can set each of them by specifying different gateway devices.

If this stuff looks useful to you, be sure to check out the VI Toolkit Extensions for this and a lot more great stuff. You should keep in mind that the extensions require PowerShell v2 CTP3, which is still in technical preview mode. But if that’s something you can use anyway you’ll find it to be extremely helpful.