“We’ve tried, it can’t be automated!” I’ve heard this more times than I can keep track of and if you read my previous blog you will know that I just do not agree. I have written about automation with Linux utilities, UCS PowerTool, AutoHotKey, Excel, etc… 99.999% of operations can be automated. So when a customer tells me that something cannot be automated I usually respond with “Have you tried …?”
Here is the scenario; the customer has an automated build process for ESX hosts. At the point where the host is ready to be connected to the Nexus 1000V the process becomes manual. The customer would like to use VMWare PowerCLI to migrate the host interface but the Cmdlet to retrieve Distributed Virtual Switches, Get-VirtualSwitch, just returns the DVS objects, there isn’t a Cmdlet to migrate the ESX vmnic interface.
Hold on a second, I know that VCenter knows about the Nexus 1000V because I see it in the interface. I know that VCenter can manipulate the Nexus 1000V because VCenter is where interface migration is done. I am fairly certain at this point that ESX interface migration from the VCenter vSwitch to the Nexus 1000V can be automated. But what to use to do it, there is no PowerCLI command like Set-ESXHostInterfaceToN1kv. This is typically where automation ends for many, sometimes you have to dive deep into the objects that the system manages and figure out what to do. Sometimes someone has already done a deep dive into something like what you are trying to do and maybe you can build off of their work.
In this instance I used the work shown here, http://www.lucd.info/2009/10/09/dvswitch-scripting-part-1-creation, it’s a blog about migrating from the VMWare vswitch to the VMWare Distributed Virtual Switch. I thought as I read it, that there could be something here that I can work with. I poked around a bit and tested some ideas and this is what I came up with, Set-EsxVmNic.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
<# .SYNOPSIS Set-EsxVmNic.ps1 Migrate an ESX Server's vmnic to an N1K DVS .DESCRIPTION Set-EsxVmNic Migrate an ESX Server's vmnic to an N1K DVS This code is provided for examples purposes only .NOTES John McDonough, Cisco Systems, Inc. (jomcdono@cisco.com) .PARAMETER VcenterHost The Vcenter hostame or IP address .PARAMETER VcenterUser A Vcenter user name .PARAMETER VcenterPass The Vcenter user's password .PARAMETER EsxServer An EsxServer .PARAMETER VmNic The vmnic to move to the N1KV .PARAMETER N1KV The N1KV to migrate the EsxServer VmNic to .EXAMPLE Set-EsxVmNic.ps1 -VcenterHost 10.10.20.30 -VcenterUser admin -VcenterPass admin123 -EsxServer 10.10.20.40 -VmNic vmnic0 -N1KV N1KV-POD1 #> param( [Parameter(Mandatory=$true,HelpMessage="Enter a Vcenter hostname or IP address")] [string] $VcenterHost, [Parameter(Mandatory=$true,HelpMessage="Enter Vcenter user")] [string] $VcenterUser, [Parameter(Mandatory=$true,HelpMessage="Enter Vcenter user's Password")] [string] $VcenterPass, [Parameter(Mandatory=$true,HelpMessage="Enter a ESX hostname or IP address")] [string] $EsxServer, [Parameter(Mandatory=$true,HelpMessage="Enter the vmnic to migrate")] [string] $VmNic, [Parameter(Mandatory=$true,HelpMessage="Enter the N1KV to migrate the vmnic to")] [string] $N1KV ); Connect-ViServer -Server $VcenterHost -User $VcenterUser -Password $VcenterPass # Get the N1KV object that that ESX host will be added to $dvsN1K= Get-VirtualSwitch -Distributed | ?{$_.name -eq $N1KV} # Get the ESX host object $vmHost=Get-VMHost -Name $EsxServer | Get-View # Create a DVS Configuration Specification $spec = New-Object VMware.Vim.DVSConfigSpec # Create a target host DVS Host member configuration specification and set the operation to add $tgthost = New-Object VMware.Vim.DistributedVirtualSwitchHostMemberConfigSpec $tgthost.operation = "add" # Create a Pnic backing object in the target host $tgthost.backing = New-Object VMware.Vim.DistributedVirtualSwitchHostMemberPnicBacking # Create a Pnic Device object $pnic = $vmHost.Config.Network.Pnic | ?{$_.Device -eq $VmNic} $tgthost.Backing.PnicSpec = New-Object VMware.Vim.DistributedVirtualSwitchHostMemberPnicSpec $tgthost.Backing.PnicSpec[0].pnicDevice = $vmHost.Config.Network.pnic[1].Device # Set the target host to the ESX host object reference $tgthost.host = $vmHost.MoRef # Set the DVS configuration specification host to the target host object reference $spec.Host = $tgthost # Get the current status of the N1KV and set the version in the configuration specification version $dvSw = Get-View -Id $dvsN1k.ExtensionData.MoRef $dvSw.UpdateViewData() $spec.ConfigVersion=$dvSw.Config.ConfigVersion # Run the task $taskMoRef = $dvSw.ReconfigureDvs_Task($spec) Disconnect-ViServer -Server $VcenterHost -Confirm:$false |
Lines 1-23 Metadata
Lines 25-43 Parameters – this script uses user and password parameters for connecting to vCenter, however a credential object can be used, up to you.
Line 45 – Connect to vCenter, since I was running the script from the PowerCLI command window I didn’t have to load the snapin but if I did I would use this code
1 2 3 4 5 |
# Enable PowerCLI CmdLets $vmAutomation = Get-PSSnapin | ?{$_.Name -eq "VMWare.VimAutomation.Core"} if (!$vmAutomation) { Add-PSSnapin VMware.VimAutomation.Core } |
Additionally, depending upon your environment and other PowerCLI cmdlets you are running within your script, for example Invoke-VMScript you may need to make sure the script is running in 32 bit mode. If that is the case add this code to your script to relaunch in 32 bit environment.
1 2 3 4 5 6 7 8 9 |
if ($env:Processor_Architecture -ne "x86") { #write-warning "Running x86 PowerShell..." if ($myInvocation.Line) { &"$env:WINDIR\syswow64\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line } else { &"$env:WINDIR\syswow64\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile -file "$($myInvocation.InvocationName)" $args } exit $lastexitcode } |
Back to the script.
Line 48 Get the Nexus 1000V Object for the 1000V that the ESX host vmnic is going to be migrated to.
Line 51 Get the ESX host object for the host whose vmnic is going to be migrated to the Nexus 1000V.
Line 54 Create a DVS configuration specification object.
Lines 57-58 Create a DVS Host member configuration specification and set the operation to add.
Line 61 Create a Pnic Backing object and add the to the member host configuration object.
Lines 64-66 Get the object that represents the vmnic in the ESX host and add that as a Pnic object to the Pnic Backing object. At this point there is an object for the Host that contains an object for the Pnic Backing that contains an object for the Pnic specification that has a member that specifies the Pnic itself, got it?
Line 69 Set the target host’s host member to the object reference from the ESX host object retrieved at line 51.
Line 72 Set the DVS configuration specification object host member to the target host object.
Lines 75-77 Get the current state of the Nexus 1000V and set the DVS configuration specification version to that configuration Version of the Nexus 1000V.
Line 80 Reconfigure the Nexus 1000V with the DVS configuration specification object that has been created. The task reference that is returned can be used to monitor the status of the task, refer to lucd’s blog for that bit of code.
Line 82 Disconnect from vCenter.
I should give a reference to the code formatter I used for this blog entry, it is the Source Code Beautifier at http://hilite.me/
As always I hope that helps your automation needs.
how about the function listed here..
http://www.lucd.info/2009/10/09/dvswitch-scripting-part-1-creation/
function Add-dvSwHost
This will add the host to the Nexus 1000V but you are unable to specify an uplink for your pnic to use. Anyway to add this in?
The DistributedVirtualSwitchHostMemberPnicSpec object allows for the attributes
UplinkPortgroupKey
UplinkPortKey
So you should be able to select the UplinkPortgroup perhaps even the specific port within that group, if it makes sense to do that. However I have not tried this but will update my lab and give it a shot and comment with my results.
The object reference is located here, http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.dvs.HostMember.PnicSpec.html
I would recommend reading all of lucd’s blogs, http://www.lucd.info/ there is in depth information in them on networking and adpaters as well as other things.
Regards,
John
Thanks, John.
Yes, I have read through all of LucD’s logs on dVs scripting. However, there is currently nothing that supports adding a Nexus 1000V with a specific uplink name.
Hopefully you are able to do so in your lab tests.
Thanks,
JD
John,
Here is the working funciton (modified) It adds the UplinkKey paramater.
Thanks for your help.
————————————————
function Add-dvSwHost{
param($dvSwitch, $hostMoRef, $pnic, $nrUplink,$UplinkKey)
$spec = New-Object VMware.Vim.DVSConfigSpec
$tgthost = New-Object VMware.Vim.DistributedVirtualSwitchHostMemberConfigSpec
$tgthost.operation = “add”
$tgthost.backing = New-Object VMware.Vim.DistributedVirtualSwitchHostMemberPnicBacking
0..($nrUplink – 1) | % {
$tgthost.Backing.PnicSpec += New-Object VMware.Vim.DistributedVirtualSwitchHostMemberPnicSpec
$tgthost.Backing.PnicSpec[$_].pnicDevice = $pnic[$_]
$tgthost.Backing.PnicSpec[$_].UplinkPortGroupKey = $UplinkKey
}
$tgthost.host = $hostMoRef
$spec.Host = $tgthost
$dvSwitch.UpdateViewData()
$spec.ConfigVersion = $dvSwitch.Config.ConfigVersion
$taskMoRef = $dvSwitch.ReconfigureDvs_Task($spec)
$task = Get-View $taskMoRef
while(“running”,”queued” -contains $task.Info.State){
$task.UpdateViewData(“Info”)
}
}