Virtualization Headlines
Automatically Configure VirtualCenter Virtual Networking Using PowerShell

Hyper9's Brian Mortimore offers the following PowerShell script that goes out to a VMware VirtualCenter instance and grabs a list of all the Port Groups in use by every ESX host server under VC management.  He writes the following on his Hyper9 Blog:

So is there anyone else out there who has actually used ESX and VirtualCenter with 802.1q VLAN trunking???

By defining Virtual PortGroups on my ESX hosts, giving them the same VLanID number as a physical managed switch Vlan, and configuring my physical switch to trunk that VLan's traffic to the port used by the PortGroup's virtual switch ... BAM!!! You can have VM NICs assigned to virtual networks that span ESX hosts. Why would you want to do this? Well, for one, it is the only way to use VMware's DRS and HA services and have networking work smoothly, or at all. The problem is that it is a lot of steps and a lot of data to configure and maintain on each host in the cluster.

Let's imagine you have a VirtualCenter instance with 20 hosts. Imagine that you also have 35 different VLans that are in use on each host in the cluster. That means that you have had to configure 20 x 35 = 700 PortGroups and VLanIds correctly for everything to work right. Yikes! I am sure to fat finger at least one of those somewhere along the way. Using VirtualCenter to do this configuration is not practical. Each host and switch and portgroup must be configured individually in VirtualCenter. I would be clicking and copying and pasting from my spreadsheet all the live long day. Also, when I need to add a VLan I should not have to go set it up individually on each host under management.

I wrote a little PowerShell script that goes out to a VirtualCenter instance and grabs a list of all the Port Groups in use by every ESX host under VC management. It ignores the default 'VM Network', 'Service Console', and 'VMKernel' PortGroups. Then it goes out to each ESX host under management and makes sure that it has all of the VLans and that they are using the correct VLanId. It does some simple error checking. If the VLan ID's don't match up, the script prompts you to ask you to pick the right one. So now when I need to add a network, I can just add it to any host under management and then run my script to reconcile everything. I think its neat. Saves me time and human error.

Please use common sense when using this script. Don't just go running it on your production cluster without testing. If you do, don't blame me. :)

$VCHost = Read-Host "Please enter the hostname or IP of a VirtualCenter instance: "
$VCUser = Read-Host "User ID: "
$VCPassword = Read-Host "Password: "

# Get all the custom defined portgroups from the VC instance and build a list of unique portgoups names and vlan ids

# Define the Array (Dictionary actually) of PortGroups we want to add to the host
$PortGroupsToAdd = @{}

$VC = Get-VC -Server $VCHost -User $VCUser -Password $VCPassword
$ESXHosts = Get-VMHost

Write-Host "Connected to VirtualCenter " $VCHost
Write-Host "Found the following ESX hosts... "
Write-Host $ESXHosts
Write-Host "`nLooking for Port Groups configured on each host...`n"

foreach ($ESXHost in $ESXHosts){

$VirtualSwitches = Get-VirtualSwitch -VMHost $ESXHost
foreach ($VirtualSwitch in $VirtualSwitches){
$VirtualPortGroups = Get-VirtualPortGroup -VirtualSwitch $VirtualSwitch
foreach ($VirtualPortGroup in $VirtualPortGroups){
# Don't do anything for the console, kernel, or default VM portgroups
if (($VirtualPortGroup).Name -ne "Service Console") {
if (($VirtualPortGroup).Name -ne "VMkernel") {
if (($VirtualPortGroup).Name -ne "VM Network") {
$TemporaryArrayofNames = @()
foreach ($prtgroupinthearray in $PortGroupsToAdd.Keys){
$TemporaryArrayofNames += $PortGroupsToAdd[$prtgroupinthearray].Name
}

$PortGroupName = ($VirtualPortGroup).Name
$IsItInTheArray = $TemporaryArrayofNames -contains $PortGroupName

Write-Host "Found Port Group $PortGroupName on ESX Host $ESXHost"

if ($TemporaryArrayofNames -contains $PortGroupName){

# Check to see if all the info of this discovered portgroup matches what I already know

if ($PortGroupsToAdd[$PortGroupName].Key -ne $VirtualPortGroup.Key){
Write-Host "I know the network, but the key doesnt match what i know"
Write-Host `n
Write-Host "Please Pick the correct key from those below..."
Write-Host "1 - " $PortGroupsToAdd[$PortGroupName].Key "<-- What I had"
Write-Host "2 - " $VirtualPortGroup.Key "<-- What I found on " $ESXHost
Write-Host `n
$RealKey = Read-Host "Enter 1 or 2 to resolve the conflict and continue"
if ($RealKey -eq "2"){
$PortGroupsToAdd[$PortGroupName].Key = $VirtualPortGroup.Key
}}
if ($PortGroupsToAdd[$PortGroupName].VLanId -ne $VirtualPortGroup.VLanId){
Write-Host "I know the network, but the VLanId doesnt match what i know"
Write-Host `n
Write-Host "Please Pick the correct VLanId from those below..."
Write-Host "1 - " $PortGroupsToAdd[$PortGroupName].VLanId "<-- What I had"
Write-Host "2 - " $VirtualPortGroup.VLanId "<-- What I found on " $ESXHost
Write-Host `n
$RealKey = Read-Host "Enter 1 or 2 to resolve the conflict and continue"
if ($RealKey -eq "2"){
$PortGroupsToAdd[$PortGroupName].VLanId = $VirtualPortGroup.VLanId
}}
if ($PortGroupsToAdd[$PortGroupName].VirtualSwitchName -ne $VirtualPortGroup.VirtualSwitchName){
Write-Host "I know the network, but the VirtualSwitchName doesnt match what i know"
Write-Host `n
Write-Host "Please Pick the correct VirtualSwitchName from those below..."
Write-Host "1 - " $PortGroupsToAdd[$PortGroupName].VirtualSwitchName "<-- What I had"
Write-Host "2 - " $VirtualPortGroup.VirtualSwitchName "<-- What I found on " $ESXHost
Write-Host `n
$RealKey = Read-Host "Enter 1 or 2 to resolve the conflict and continue"
if ($RealKey -eq "2"){
$PortGroupsToAdd[$PortGroupName].VirtualSwitchName = $VirtualPortGroup.VirtualSwitchName
}}

Write-Host "I already know about this network. Ignoring it.`n"
}
else {
Write-Host "This network name is new to me, I will add it to my list."

$PortGroupName = $VirtualPortGroup.Name
$PortGroupKey = $VirtualPortGroup.Key
$PortGroupVLanId = $VirtualPortGroup.VLanId
$PortGroupVirtualSwitchName = $VirtualPortGroup.VirtualSwitchName

Write-Host "Port Group Name ............ $PortGroupName"
Write-Host "Port Group Key ............. $PortGroupKey"
Write-Host "Port Group VLanId .......... $PortGroupVLanId"
Write-Host "Port Group VirtualSwitch ... $PortGroupVirtualSwitchName`n"

$PortGroupsToAdd.$PortGroupName = $VirtualPortGroup

}}}}}}}

$TemporaryArrayofNames = @()
foreach ($prtgroupinthearray in $PortGroupsToAdd.Keys){
$TemporaryArrayofNames += $PortGroupsToAdd[$prtgroupinthearray].Name
}

# Ok, I finally have my list of networks I want to make sure are on my ESX hosts in the VC instance.
# Now I need to go through each host and make sure that it has all the networks on my list.

foreach ($ESXHost in $ESXHosts){
Write-Host "Now Configuring $ESXHost"
$ESXVirtualSwitches = Get-VirtualSwitch -VMHost $ESXHost
foreach ($ESXVirtualSwitch in $ESXVirtualSwitches){
$ESXVirtualPortGroups = Get-VirtualPortGroup -VirtualSwitch $ESXVirtualSwitch
$TemporaryArrayofESXPortGroupNames = @()
foreach ($ESXVirtualPortGroup in $ESXVirtualPortGroups){
$TemporaryArrayofESXPortGroupNames += $ESXVirtualPortGroup.Name
}

# Go through our list of PortGroups we want and add the ones appropriate for this virtual switch that don't exist already

foreach ($prtgroupinthearray in $PortGroupsToAdd.Keys){
if ($TemporaryArrayofESXPortGroupNames -notcontains $PortGroupsToAdd[$prtgroupinthearray].Name){
if ($PortGroupsToAdd[$prtgroupinthearray].VirtualSwitchName -eq $ESXVirtualSwitch.Name){

New-VirtualPortGroup -VirtualSwitch $ESXVirtualSwitch -Name $PortGroupsToAdd[$prtgroupinthearray].Name -VLanId $PortGroupsToAdd[$prtgroupinthearray].VLanId

}}}
# Bring back in our newly updated list of VLans
$ESXVirtualPortGroups = Get-VirtualPortGroup -VirtualSwitch $ESXVirtualSwitch

# Now go through each one and make sure it is configed for the right VLanId
foreach ($ESXVirtualPortGroup in $ESXVirtualPortGroups){

# Check to see if this portgroup already exists on the ESX host
# If it does exist, then we want to set the VLanId correctly

$PortGroupName = ($ESXVirtualPortGroup).Name

if ($TemporaryArrayofNames -contains $PortGroupName){
if ($ESXVirtualPortGroup.VirtualSwitchName -eq $PortGroupsToAdd[$PortGroupName].VirtualSwitchName){
if ($ESXVirtualPortGroup.VLanId -ne $PortGroupsToAdd[$PortGroupName].VLanId){
Write-Host "Found PortGroup $PortGroupName on ESX Host $ESXHost using VirtualSwitch $ESXVirtualSwitch"
Write-Host "But the VLanIds don't match up!"
Write-Host "Setting values for PortGroup $PortGroupName on ESX Host $ESXHost"
Set-VirtualPortGroup -VirtualPortGroup $ESXVirtualPortGroup -VLanId $PortGroupsToAdd.$PortGroupName.VLanId

}}}

}}}

Write-Host "`nDone configuring networks for VirtualCenter $VCHost"

Published Saturday, August 16, 2008 5:38 PM by David Marshall
Filed under:
Comments
User links about "virtualization" on iLinkShare - (Author's Link) - November 2, 2008 5:33 PM
To post a comment, you must be a registered user. Registration is free and easy! Sign up now!
Calendar
<August 2008>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456
Archives