Tuesday, 12 May 2015

Naming VMWare Guest (Windows) NIC's

One of the things that annoy's me a little bit (A lot!) is when the adapters on a server have no meaningful name and you are only left with the network address to try and work out what the hell the network is, on some systems where you may have multiple adapters then this is only harder.

We talked over at work how best to identify what network the machine was on and work from there, we use Cisco Nexus 1000v switches on some of our vmware estate, so I initially thought of using CDP to determine the VLAN ID or name.. however I dismissed it as soon as I thought of it. The key was in the word 'some', so this potentially means this process wouldn't work for test and dev environments where an enterprise plus licence wasn't / isn't currently present.

So the option we came up with is using the MAC address to identify the correct adapter and then set the name based on the vmware port group.

To achieve the rename in the guest I am using the
Invoke-VMScript
command, which allows you to execute a command in the guest providing you have the correct credentials, vmware tools running and tcp port 902 open in the correct places (or is it 901? - 902 I think, but I've had a beer now!)

In order to do the rename, I currently use
Get-Netadapter
and
Rename-NetAdapter
commands which are only available in 2012 onwards, I will over time amend this to work with 2008 (prob using wmi and netsh), but this is only an initial draft, so the usual caveat's apply!

The script builds a scriptblock object to pass through to command, which took a little bit of fiddling to ensure that some variables weren't expanded such as $_.MacAddress in the where clause, but then the other variables were expanded, I'm sure when I revisit this I will change my mind of how to do it, but for now it works, so function over form.

FWIW, I have made it fail back to the administrator username if the supplied username fails auth.. but modify this to suit your own environment.

Script:

# Name VM Guest Adapters
# David Wallis 12/05/2015 blog.wallis2000.co.uk

# Variables
$viServer = "vmware.blah.local"
$ServerName = "Server001"
$Username = "Admin123"
$Password = "Password"

# Add Snapin if needed
If (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
    Add-PSSnapin VMware.VimAutomation.Core | Out-Null 
}

# Connect to Vsphere
$null = Connect-VIServer $viServer 

# Hide Progress Bars as System Center Orchestrator might not like these 
$ProgressPreference='SilentlyContinue'

# get VM Object
$vm = Get-VM -Name $ServerName -ErrorAction stop
 
function RenameNic
{
    [CmdletBinding()]
    param (
     [Parameter(Mandatory=$true)]
     [String] $User,
  
  [Parameter(Mandatory=$true)]
     [String] $GuestPw,
  
  [Parameter(Mandatory=$true)]
     [String] $MacAddress,
  
  [Parameter(Mandatory=$true)]
     [String] $NewInterfaceName
 )

  # Replace colons with dashes in the MAC address so that we can use it to match with the get-NetAdapter cmdlet.
  $macAddress = $macAddress.Replace(":","-")

  # Construct Scriptblock to execute the command
  $command = 'Get-Netadapter | where {$_.MacAddress -eq ' +  [char]34 + $macAddress + [char]34 + "} | Rename-NetAdapter -NewName " + [char]34 + $NewInterfaceName + [char]34
  Write-Verbose "Attempting to execute command within the VM ($($VM)): $($command)"
  $ScriptBlock = [scriptblock]::Create($command)
  
  # Try and invoke the command within VM
 try
 {  
  $output = Invoke-VMScript -vm $vm -guestuser $Username -guestpassword $Password -scripttype powershell -scripttext $ScriptBlock -ErrorAction stop
  # Nothing should be returned.. but the output would be in the below
  # $output.ScriptOutput
 }
 catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidGuestLogin]
 {
  # Invalid Guest Login
  Write-Verbose 'Invalid credentials trying the username "Administrator"'
  $output = Invoke-VMScript -vm $vm -guestuser "Administrator" -guestpassword $Password -scripttype powershell -scripttext $ScriptBlock -ErrorAction stop
  write-output $output.ScriptOutput
  
 }
 catch
 {
  throw
 }
 
}

# Get all the Adapters assigned to the VM and rename the nic to the vm portgroup name using the MAC
# to identify the correct adapters - this will only work on 2012 onwards currently
$Adapters = $vm | Get-NetworkAdapter | Select NetworkName, MacAddress
foreach ($adapter in $Adapters){
 write-verbose "Renaming Adapter with MAC Address ($($adapter.MacAddress))"
 RenameNic -User $Username -GuestPw $Password -MacAddress $($adapter.MacAddress) -NewInterfaceName $($adapter.NetworkName) -verbose
}

1 comment:

  1. Quick Update: If I run this as powershell v2, then it fails to authenticate, but also the try catch fails to handle the error. Works fine under v3 though.

    ReplyDelete