Virtu-Al.Net

Virtually everything is poshable

PowerCLI: Easy vSwitch & PortGroup Setup

To get VMotion working the networking setup plays a big part, any of the following could cause you big issues:

  • A spelling mistake in a PortGroup name
  • A missing PortGroup
  • A PortGroup configured incorrectly
  • A non-existing PortGroup on one of your hosts
  • etc

This is why automation and PowerCLI is key to the setup of your vSwitches and PortGroup’s, you could add each vSwitch manually and then create a PortGroup for each VLAN you have trunked to your hosts manually but what are the chances you will miss one, what are the chances you will get the VLAN ID incorrect ?  And you sure do get bored of the wizard when you have 4 vSwitches and around 20 PortGroups !

The following code will take you through copying all vSwitches and PortGroups from an existing ESX server over to a new server, ensuring they are exactly the same.  It sure does save me time !

$VISRV = Connect-VIServer (Read-Host "Please enter the name of your VI SERVER")
$BASEHost = Get-VMHost -Name (Read-Host "Please enter the name of your existing server as seen in the VI Client:")
$NEWHost = Get-VMHost -Name (Read-Host "Please enter the name of the server to configure as seen in the VI Client:")

$BASEHost |Get-VirtualSwitch |Foreach {
   If (($NEWHost |Get-VirtualSwitch -Name $_.Name-ErrorAction SilentlyContinue)-eq $null){
       Write-Host "Creating Virtual Switch $($_.Name)"
       $NewSwitch = $NEWHost |New-VirtualSwitch -Name $_.Name-NumPorts $_.NumPorts-Mtu $_.Mtu
       $vSwitch = $_
    }
   $_ |Get-VirtualPortGroup |Foreach {
       If (($NEWHost |Get-VirtualPortGroup -Name $_.Name-ErrorAction SilentlyContinue)-eq $null){
           Write-Host "Creating Portgroup $($_.Name)"
           $NewPortGroup = $NEWHost |Get-VirtualSwitch -Name $vSwitch |New-VirtualPortGroup -Name $_.Name-VLanId $_.VLanID
        }
    }
}

, ,

20 Responses to “PowerCLI: Easy vSwitch & PortGroup Setup”

  • NiTRo says:

    Al, i had to put “$vSwitch = $_” after “$BASEHost |Get-VirtualSwitch |Foreach {” in case of only vSwitch0

  • Kcm says:

    Has anyone (else) tried this on ESX4? I keep getting this error
    “The argument cannot be null or empty.
    At :line:30 char:60
    + $NewPortGroup = $NEWHost |Get-VirtualSwitch -Name <<<< $vSwitch |New-VirtualPortGroup -Name $_.Name-VLanId $_.VLanID"

    Line 30 equates to "$NewPortGroup = $NEWHost……." on my script.

  • Virtu-Al says:

    @Kcm
    I havent tried it against ESX4 yet but will now !

  • Mike says:

    I had to modify the script a tiny bit (sounds like the above comment #1) to get it to work against ESX 4, but below is my version (with all thanks to Al!). I did get this to work for my vSphere hosts.

    $VISRV = Connect-VIServer (Read-Host “Please enter the name of your VI SERVER”)
    $BASEHost = Get-VMHost -Name (Read-Host “Please enter the name of your existing server as seen in the VI Client:”)
    $NEWHost = Get-VMHost -Name (Read-Host “Please enter the name of the server to configure as seen in the VI Client:”)

    $BASEHost |Get-VirtualSwitch |Foreach {
    $switch = $_.Name
    If (($NEWHost |Get-VirtualSwitch -Name $switch -ErrorAction SilentlyContinue)-eq $null){
    Write-Host “Creating Virtual Switch $($_.Name)”
    $NewSwitch = $NEWHost |New-VirtualSwitch -Name $_.Name-NumPorts $_.NumPorts-Mtu $_.Mtu
    #$vSwitch = $_
    }
    $BASEHost | Get-VirtualPortGroup -VirtualSwitch $switch | Foreach {
    $myPG = $_.name
    If (($NEWHost |Get-VirtualPortGroup -Name $myPG -ErrorAction SilentlyContinue)-eq $null){
    Write-Host “Creating Portgroup $($_.Name)”
    $NewPortGroup = $NEWHost |Get-VirtualSwitch -Name $vSwitch |New-VirtualPortGroup -Name $_.Name-VLanId $_.VLanID
    }
    }
    }

  • M@rcel says:

    Hi Al/Mike,

    I’m not very experienced with the PowerCLI, but am very interested in automating the creation of vSwitches and PortGroups. We are using ESX4.
    I tried pasting Mike’s script in the PowerCLI, but keep getting this error:

    Get-VirtualPortGroup : 28-1-2010 17:02:38 Get-VirtualPortGroup
    Could not find VirtualSwitch with name ‘vSwitch0′.
    At line:8 char:33
    + $BASEHost | Get-VirtualPortGroup <<<< -VirtualSwitch $switch | Foreach {
    + CategoryInfo : ObjectNotFound: (vSwitch0:String) [Get-VirtualPortGroup], VimException
    + FullyQualifiedErrorId : Core_ObnSelector_SelectObjectByNameCore_ObjectNotFound,VMware.VimAutomation.Commands.GetVirtualPortGroup

    I even do not get the questions for vCenter server, source and destination server. I'm running the PowerCLI with my vmWare admin account (not root)

    Any suggestions?

  • Mike says:

    Hmm.. not sure M@rcel. Double-check the way this gets pasted in to PowerCLI perhaps. Watch that line breaks don’t get put in where they shouldn’t be.

    Perhaps copy “my” version of the script and paste into notepad or some other text editor and watch for the line breaks. Have you tried to use PowerGUI and its Script Editor at all?

    Mike

  • Alan Renouf says:

    @Mike, strange, all works fine with my original script on ESX4 here. I will look through the differences.

  • Mike says:

    My only real change was to use a variable in place of $_ in the foreach loops. For some reason, it didn’t seem to get the scope of $_ without assigning it to a variable first and then using the variable ($switch or &myPG in my version).

    I learned a lot from looking at your script and tweaking it, Al (even if the tweaks turn out to have been unnecessary). Thanks!

  • Virtu-Al says:

    No problems, Im just glad its not just me using them ;)

  • Rene Nelson says:

    Does this script work with ESXi? I get the above Null or Empty error when running against ESX4i, but it works great running against ESX4.

  • Mike says:

    I used it just the other day against an ESXi 4 host, but not without some issues. I was using a version I am sorta working on that tries to create the vswitches, add portgroups and VMkernel ports and adds vnics to the vswitches. It does this by looking at an existing host and making the new host just like the old one. Still not much of my work – mainly Al’s.

    The part ESXi didn’t seem to like was the fact that the VMkernel ports are vmk0, vmk1, etc. instead of looking a bit like ESX portgroups. Still things to look at in “my” version before it is ready to use in Production.

  • [...] PowerCLI community expert Alan Renouf has provided a simple alternative solution to this problem via his blog (rather than reproduce the script here, I recommend you take a look at his blog once you’ve [...]

  • Mike says:

    I have worked more on “my” version of the script. It now looks at one host and configures another host to have the same vSwitches with portgroups and VLANs. It does ESXi and vmk interfaces and will ask you which of the vSwitches on the existing host you want to “copy” to the new host. This was helpful for me where I was occasionally changing a host from one cluster to another and I wanted to leave one vSwitch alone (this might be specific to my environment). My vMotion vmk interfaces are always on vSwitch0, thus the part where I ask what the vMotion IP is if the current vSwitch is vSwithc0. Sorry about that, but that’s the way it works for me.

    Use this in a testing area first, or use it for ideas. Full credit to Al as this is still mainly his work that I merely tweaked. I am NOT a programmer and someone will likely hate the way I do things. No worries.

    function AskEm {
    $caption = “Select:”;
    $message = “Add item $element to the new list?”;
    $yes = new-Object System.Management.Automation.Host.ChoiceDescription “&Yes”,”help”;
    $no = new-Object System.Management.Automation.Host.ChoiceDescription “&No”,”help”;
    $choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes,$no);
    $answer = $host.ui.PromptForChoice($caption,$message,$choices,0)
    switch ($answer){
    0 {$Global:NewList += @($element)}
    1 {continue}
    }
    }
    # initialize a variable
    $Global:NewList = $null

    $VISRV = Connect-VIServer # or ask (Read-Host “Please enter the name of your VI SERVER”)
    $BASEHost = Get-VMHost -Name (Read-Host “Please enter the name of your existing server as seen in the VI Client:”)
    $NEWHost = Get-VMHost -Name (Read-Host “Please enter the name of the server to configure as seen in the VI Client:”)

    # get the switches for the base host
    $MySwitches = $BASEHost |Get-VirtualSwitch

    # ask the user to select what switches to look at and copy
    foreach ($element in $MySwitches) {
    Askem
    }

    #go thru each switch selected above
    foreach ($switch in $NewList) {
    # check to see if the switch already exists on the new host – if so don’t create it.
    If (($NEWHost |Get-VirtualSwitch -Name $switch.Name -ErrorAction SilentlyContinue)-eq $null){
    # if not, create it…
    Write-Host “Creating Virtual Switch $($switch.Name) on $($NEWHost).”
    $NewSwitch = $NEWHost |New-VirtualSwitch -Name $switch.Name -NumPorts $switch.NumPorts -Mtu $switch.Mtu
    }
    Else {Write-Host “Vswitch $($switch.name) already exists on $($NEWHost). Checking port groups on this switch.”}

    If ($switch.Name -eq “vSwitch0″) {
    $MotionIP = Read-Host “What is the IP for the VMotion Network?”
    $MyVMKs = $BASEHost | Get-VMHostNetworkAdapter -VMKernel
    foreach ($vmk in $MyVMKs) {
    if (($NEWHost | Get-VMHostNetworkAdapter -VMKernel).devicename -ne $vmk.DeviceName) {
    Write-Host “Creating $($vmk) on $($NewHost).”
    $vmkpg = Get-VirtualPortGroup -Name $vmk.portgroupname -VMHost $BASEhost
    if ($vmk.PortGroupName -eq “VMkernel-VMotion”) {
    $NewVMK = $NEWHost | New-VMHostNetworkAdapter -PortGroup $vmk.portgroupname -SubnetMask $vmk.subnetmask -VMotionEnabled $vmk.vmotionenabled -VirtualSwitch $vmkpg.virtualswitchname -IP $MotionIP}
    else {$NewVMK = $NEWHost | New-VMHostNetworkAdapter -PortGroup $vmk.portgroupname -SubnetMask $vmk.subnetmask -VMotionEnabled $vmk.vmotionenabled -VirtualSwitch $vmkpg.virtualswitchname}
    get-virtualportgroup -VMHost $NEWHost -Name $vmk.portgroupname | Set-VirtualPortGroup -VLanId $vmkpg.vlanid
    }
    }
    }
    Else {
    $MyPGs = $switch | Get-VirtualPortGroup
    foreach ($Pg in $MyPGs) {
    If (($NEWHost |Get-VirtualPortGroup -Name $PG.Name-ErrorAction SilentlyContinue)-eq $null){
    Write-Host “Creating Portgroup $($PG.Name) on $($switch)”
    $NewPortGroup = $NEWHost |Get-VirtualSwitch -Name $switch |New-VirtualPortGroup -Name $PG.Name -VLanId $PG.VLanID
    }
    }
    }

    }

    Hope this helps…

  • [...] so let’s start with a new PowerCLI post. This post is
    inspired by the blog post of @alanrenouf: PowerCLI easy vswitch
    portgroup setup. I love the whole idea of taking a good working
    config from a vSphere host and use it on a fresh [...]

  • Ajay Nabh says:

    Hi Guys

    I am trying this script from 1 esxi to another esxi and both are 4.0 U2 and geting this error!! help if you guys can
    Connect-VIServer : A positional parameter cannot be found that accepts argument
    ‘$null’.
    At line:1 char:26

  • Mike says:

    Hi Ajay.

    That has nothing to do with ESXi or ESX. That command is trying to connect to your vCenter server.

    In the command:

    $VISRV = Connect-VIServer # or ask (Read-Host “Please enter the name of your VI SERVER”)

    the “#” is a commentor, meaning everything after that is ignored. So, put the FQDN of your vCenter server just before the “#” or remove the “# or ask” part and it will ask when you run the script.

    Hope that helps…

    Mike

  • Ajay Nabh says:

    Thanks Mike

    script did prompt me for VI server and source/destination and it generate this error after accepting the infomation. I will try again as you mentioned. thanks heaps
    Ajay

  • [...] my recent post, Easy vSwitch & PortGroup Setup I thought I would give PrimalForms a go and create a quick GUI, PrimalForms is a great app from [...]

  • Dorothy says:

    Hi Mike,

    I’m using your version of the script. It’s working really well for me and I’ve made my own additions for our environment. The only piece I can’t get to work is the vmkernel creation (I had to remove this piece to test the rest).

    If I don’t modify the script, I get this error:
    [vSphere PowerCLI] > .\copyportgroups_tmp.ps1
    Unexpected token ‘What’ in expression or statement.
    At D:\copyportgroups_tmp.ps1:39 char:28
    + $MotionIP = Read-Host “What <<< .\copyportgroups_tmp.ps1
    Unexpected token ‘Creating’ in expression or statement.
    At D:\copyportgroups_tmp.ps1:43 char:21
    + Write-Host “Creating <<<< $($vmk) on $($NewHost).”
    + CategoryInfo : ParserError: (Creating:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

    Thanks for the help.

  • Rusty says:

    Script works a treat, but doesn’t add the nics.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>