After my last post on Get/Set-OSCustomizationNicMapping, I started looking further at what options there were to configure network settings for guests that were “already” created.
It is one thing to be able to set the network adapter properties during the cloning process and something entirely different to do it after the fact. Maybe a mistake was made during the cloning process. More likely a network migration could be planned, and a completely different way of doing things would be needed.
Using Invoke-VMScript
In January, I wrote a post on how to Update VMware Windows Guest DNS and WINS through PowerCLI that uses the Invoke-VMScript cmdlet to run a batch file in Windows to set the DNS and WINS information. For those versed with netsh, it is powerful, but there are requirements…
One pretty big requirement is that the name of the network adapter must be known. On older VM’s, or possibly P2V’ed VM’s the network adapter name could be something like “Local Network Connection 2”, “Local Network Connection 3”, etc. Using the above mentioned script is going to fail if the connection name is not known. The only way around that, would be to put some logic in to determine the name to use when calling the script. Additionally using netsh with DNS and WINS requires the addition of new values, and deletion of old values.
Another issue with the Invoke-VMScript method, is that it requires different scripts for Windows and Linux guests.
A Different Way
So I started to peruse the online docs for the current vSphere 4.0 Update 1 and found the Get/Set-VMGuestNetworkInterface cmdlets. Just like my last post, I couldn’t really find any example scripts of anyone using it.
Here is the syntax for these cmdlets:
Get-VMGuestNetworkInterface
Syntax
Get-VMGuestNetworkInterface [[-VM] <VirtualMachine[]>] [-VMGuest <VMGuest[]>] [-Server <VIServer[]>] [-ToolsWaitSecs <Int32>] [-GuestPassword <SecureString>] [-GuestUser <String>] [-GuestCredential <PSCredential>] [-HostPassword <SecureString>] [-HostUser <String>] [-HostCredential <PSCredential>] [<CommonParameters>]Set-VMGuestNetworkInterface
Syntax
Set-VMGuestNetworkInterface -VmGuestNetworkInterface <VMGuestNetworkInterface[]> [-WinsPolicy <DhcpPolicy>] [-Wins <String[]>] [-DnsPolicy <DhcpPolicy>] [-Dns <String[]>] [-IPPolicy <DhcpPolicy>] [[-Gateway] <Object>] [[-Netmask] <String>] [[-Ip] <IPAddress>] [-ToolsWaitSecs <Int32>] [-GuestPassword <SecureString>] [-GuestUser <String>] [-GuestCredential <PSCredential>] [-HostPassword <SecureString>] [-HostUser <String>] [-HostCredential <PSCredential>] [-WhatIf] [-Confirm] [<CommonParameters>]
One thing that struck me as odd, was that both of these commands have the following statements as part of their documentation:
… Consider that this functionality is experimental. …
and
…Notes
Supported on ESX 3.5 and newer. …
So which is it? Maybe @cshanklin can address this at some point.
How Does It Really Work?
Are the Get/Set-VMGuestNetworkInterface cmdlets really that different from Invoke-VMScript? Not really, except for the fact that VMware has taken some of the guesswork out of the process. These cmdlets actually call scripts in the Scripts folder located under the installation path of the vSphere PowerCLI. There are separate scripts for Windows OSes and Linux OSes (currently only supported on RHEL 5).
The netsh scripting limitation I mentioned earlier (network connection name) is actually taken care of by these scripts. Additionally these scripts can be modified/added to if desired.
There are a couple things to be aware of.
- Set-VMGuestNetworkInterface does not work in my environment if the vNic is disconnected.
- I could not use the vSphere PowerCLI in x64 mode to run the script. The PowerCLI stated that I needed to use the 32bit PowerCLI instead.
- WINS settings are not available in Linux guests.
How To Update
Now how do I go and update IP addresses on several machines (possibly those that I created in my last post)?
Here are the contents of my text file (C:vms.csv) that contained my VM names and other settings.
basevm,datastore,vmhost,custspec,vmname,ipaddress,subnet,gateway,pdnswins,sdnswins,vlan
BASEVM,DS1,ESXi1,W2K3,VM01,192.168.0.80,255.255.255.0,192.168.0.1,192.168.0.199,192.168.0.198,Primary
BASEVM,DS1,ESXi1,W2K3,VM02,192.168.0.81,255.255.255.0,192.168.0.1,192.168.0.199,192.168.0.198,Primary
BASEVM,DS1,ESXi1,W2K3,VM03,192.168.0.82,255.255.255.0,192.168.0.1,192.168.0.199,192.168.0.198,Primary
BASEVM,DS1,ESXi1,W2K3,VM04,192.168.255.83,255.255.255.0,192.168.0.1,192.168.0.199,192.168.0.198,Secondary
BASEVM,DS1,ESXi1,W2K3,VM05,192.168.255.84,255.255.255.0,192.168.0.1,192.168.0.199,192.168.0.198,Secondary
So I’ll modify it because I didn’t mean to use 192.168.0.x, I meant to use 192.168.1.x. And I’ll pull out the things I don’t need, like basevm, datastore, vmhost, & custspec.
vmname,ipaddress,subnet,gateway,pdnswins,sdnswins,vlan
VM01,192.168.1.80,255.255.255.0,192.168.1.1,192.168.1.199,192.168.1.198,Primary
VM02,192.168.1.81,255.255.255.0,192.168.1.1,192.168.1.199,192.168.1.198,Primary
VM03,192.168.1.82,255.255.255.0,192.168.1.1,192.168.1.199,192.168.1.198,Primary
VM04,192.168.255.83,255.255.255.0,192.168.1.1,192.168.1.199,192.168.1.198,Secondary
VM05,192.168.255.84,255.255.255.0,192.168.1.1,192.168.1.199,192.168.1.198,Secondary
Now I’ll save it as C:vms-newip.csv.
Also, unlike the Get/Set-OSCustomizationNicMapping cmdlet, I’ll have to connect specifically to the host and the guest with appropriate credentials. I have to do this, because credentials are required in the guest to make the change.
The Script
I’ll use the following script to update the VM’s.
########################################################## # updateip.ps1 # Jase McCarty 6/6/2010 # Posh Script to update IP # addresses in Virtual Machines ########################################################## Connect-VIServer vcenter.jasemccarty.com $HostCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter ESX host credentials", "", "") $GuestCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter Guest credentials", "", "") $vmlist = Import-CSV C:vms.csv foreach ($item in $vmlist) { # I like to map out my variables $vmname = $item.vmname $ipaddr = $item.ipaddress $subnet = $item.subnet $gateway = $item.gateway $pdnswins = $item.pdnswins $sdnswins = $item.sdnswins #Get the current interface info $GuestInterface = Get-VMGuestNetworkInterface -VM $vmname -HostCredential $HostCred -GuestCredential $GuestCred #If the IP in the VM matches, then I don't need to update If ($ipaddr -ne $($GuestInterface.ip)) { Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -IP $ipaddr -Netmask $subnet -Gateway $gateway -DNS $pdnswins,$sdnswins -WINS $pdnswins,$sdnswins } }
As can be seen, it doesn’t take a complex script to update IP information in guests.
Keep in mind that not all of the attributes that I chose to use are required. If desired, only the IP, DNS, WINS, etc can be updated. My script just happens to update several of these items. Additionally, this can be used to change a guest from a static IP address to a DHCP address as well.
Hopefully this script will help you when presented with a similar task of updating IP addresses/DNS/WINS settings.
For More Info
For more info on each of these commands, look here for the VMware documentation:
Hi Jase
this works great on Windows 2003 guests but not Windows 2008 – seems like the Get-VMGuestNetworkInterface calls a .bat file which gets run on the guest but that is not compatible with windows 2008 – any ideas on how to fix this ?
cheers
I’ll have to give it a spin on a Windows 2008 (& R2) and report back.
I’m not sure if I am missing this, but how does this script determine which nic to assign the ip/dns etc to?
I was using your previous method with invoke Script. to do multiple nics on a single host, which I had to specify local area connection 3, and 2 for each ip.. I’m not sure how the script above identifies this. care to share the light?
Thank you
– Ryan
Actually I wrote this script to be used with VM’s with a single nic.
I haven’t tried it on a VM with multiple nics.
I’ll have to spin up a VM and try it out. I’ll let you know what I find.
Looks like Windows 7/2008 support was added in PowerCLI 5.0.
I’ve confirmed that it works on 2008 R2, but haven’t been able to confirm Windows 7.
Found your site and I like reading your posts! Very interesting. I got your script running and it’s awesome. I had a question about using your script to update multiple nics(eth0 and eth1). I am not to efficient in coding and I wanted to see what you would suggest. Thanks!
Using this script, I would recommend putting a little logic around this section:
This:
If ($ipaddr -ne $($GuestInterface.ip)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -IP $ipaddr -Netmask $subnet -Gateway $gateway -DNS $pdnswins,$sdnswins -WINS $pdnswins,$sdnswins
}
Could look like:
$adapter = $item.NetworkAdapter
If ($adapter -eq $(“Network adapter 1”)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -IP $ipaddr -Netmask $subnet -Gateway $gateway -DNS $pdnswins,$sdnswins -WINS $pdnswins,$sdnswins
}
If ($adapter -eq $(“Network adapter 2”)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -IP $ipaddr -Netmask $subnet -Gateway $gateway -DNS $pdnswins,$sdnswins -WINS $pdnswins,$sdnswins
}
You’d have to make sure that your variables could handle ranges for each of the adapters though. Something like a $ipaddr1 $subnet1 $gateway1 and a $ipaddr2 $subnet2 $gateway2… etc.
Hope that helps…
Jase
Jase,
I think I tried what you suggested, but it’s still only updating Network adapter 1. I don’t get any errors running the code below but it just doesn’t know how to update Network adapter 2. I added the lines for the new variables in the .csv as well but it doesn’t know how to differentiate between the two interfaces. Seems like the interface(eth0 or eth1) needs to be specific in the Set-VMGuestNetworkInterface somewhere but the problem is I don’t know where =). Thanks much!
Connect-VIServer vCenter
$HostCred = $Host.UI.PromptForCredential(“Please enter credentials”, “Enter ESX host credentials”, “”, “”)
$GuestCred = $Host.UI.PromptForCredential(“Please enter credentials”, “Enter Guest credentials”, “”, “”)
$vmlist = Import-CSV C:\VMs_NewIP.csv
foreach ($item in $vmlist) {
# I like to map out my variables
$vmname = $item.vmname
$ipaddr1 = $item.ipaddress
$subnet1 = $item.subnet
$gateway1 = $item.gateway
$adapter1 = $item.NetworkAdapter
$ipaddr2 = $item.ipaddress2
$subnet2 = $item.subnet2
$gateway2 = $item.gateway2
$adapter2 = $item.NetworkAdapter2
#Get the current interface info
$GuestInterface = Get-VMGuestNetworkInterface -VM $vmname -HostCredential $HostCred -GuestCredential $GuestCred
#If the IP in the VM matches, then I don’t need to update
If ($adapter1 -eq $(“Network adapter 1”)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -Ip $ipaddr1 -Netmask $subnet1 -Gateway $gateway1
}
If ($adapter2 -eq $(“Network adapter 2”)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -Ip $ipaddr2 -Netmask $subnet2 -Gateway $gateway2
}
}
Jase,
I think I tried what you suggested, but it’s still only updating Network adapter 1. I don’t get any errors running the code below but it just doesn’t know how to update Network adapter 2. I added the lines for the new variables in the .csv as well but it doesn’t know how to differentiate between the two interfaces. Seems like the interface(eth0 or eth1) needs to be specific in the Set-VMGuestNetworkInterface somewhere but the problem is I don’t know where =). Thanks much!
Connect-VIServer vCenter
$HostCred = $Host.UI.PromptForCredential(“Please enter credentials”, “Enter ESX host credentials”, “”, “”)
$GuestCred = $Host.UI.PromptForCredential(“Please enter credentials”, “Enter Guest credentials”, “”, “”)
$vmlist = Import-CSV C:\VMs_NewIP.csv
foreach ($item in $vmlist) {
# I like to map out my variables
$vmname = $item.vmname
$ipaddr1 = $item.ipaddress
$subnet1 = $item.subnet
$gateway1 = $item.gateway
$adapter1 = $item.NetworkAdapter
$ipaddr2 = $item.ipaddress2
$subnet2 = $item.subnet2
$gateway2 = $item.gateway2
$adapter2 = $item.NetworkAdapter2
#Get the current interface info
$GuestInterface = Get-VMGuestNetworkInterface -VM $vmname -HostCredential $HostCred -GuestCredential $GuestCred
#If the IP in the VM matches, then I don’t need to update
If ($adapter1 -eq $(“Network adapter 1”)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -Ip $ipaddr1 -Netmask $subnet1 -Gateway $gateway1
}
If ($adapter2 -eq $(“Network adapter 2”)) {
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface -HostCredential $HostCred -GuestCredential $GuestCred -Ip $ipaddr2 -Netmask $subnet2 -Gateway $gateway2
}
}
@jase
Jase,
I think I tried what you suggested, but it’s still only updating Network adapter 1. I don’t get any errors running the code below but it just doesn’t know how to update Network adapter 2. I added the lines for the new variables in the .csv as well but it doesn’t know how to differentiate between the two interfaces. Seems like the interface(eth0 or eth1) needs to be specific in the Set-VMGuestNetworkInterface somewhere but the problem is I don’t know where =). Thanks much!
FYI…I tried posting the code below but it’s doesn’t seem to work. Thanks!
Sorry I haven’t had the opportunity to test your code…
I’ll see if I can whip something up…
Jase
Jase,
I am running into a problem and wondering if you could help me out again. The code is posted below. I had this script working on a ESXi4.1 environment. I took the same script and I am trying to run it on an ESXi5 environment. I get the following error.
Get-VMGuestNetworkInterface : 7/9/2012 11:12:06 AM Get-VMGuestNetworkInterface You must specify at least one of the VM and VMGuest parameters.
At C:\Documents and Settings\Administrator\Desktop\PowerCLI_Scripts\Update_Multiple_IPsandHosts_Script.ps1:39 char:48
+ $GuestInterface = Get-VMGuestNetworkInterface <<<< -VM $vmname -VMGuest $vmguest -HostCredential $HostCred -GuestCredential $GuestCred
+ CategoryInfo : InvalidArgument: (:) [Get-VMGuestNetworkInterface], VimException
+ FullyQualifiedErrorId : Core_GetVmGuestInfoBaseCmdlet_ValidateParameters_MandatoryParameters,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVmGuestNetworkInterface
Code is below:
Connect-VIServer myVcenter
# Pop-up that will prompt for the ESX credentials
$HostCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter ESXi host credentials", "", "")
# Pop-up that will prompt for the VM credentials
$GuestCred = $Host.UI.PromptForCredential("Please enter credentials", "Enter Guest credentials", "", "")
# Populating variable from the .csv file
$vmlist = Import-CSV C:\Documents and Settings\Administrator\Desktop\PowerCLI_Scripts\VMs_NewIPs_ForMultipleHost.csv
"VM LIST"
Write-Output $vmlist
# Clearing the console
clear
foreach ($item in $vmlist) {
# Mapping out variables
$vmname = $item.vmname
$vmguest = $item.vmguest
$ipaddr1 = $item.ipaddress1
$subnet1 = $item.subnet1
#$gateway1 = $item.gateway1
$ipaddr2 = $item.ipaddress2
$subnet2 = $item.subnet2
#$gateway2 = $item.gateway2
# Get the current interface info
$GuestInterface = Get-VMGuestNetworkInterface -VM $vmname -VMGuest $vmguest -HostCredential $HostCred -GuestCredential $GuestCred
foreach ($interface in $GuestInterface) {
"VM NAME"
Write-Output $vmname
"IP ADRRESS ONE"
Write-Output $ipaddr1
"IP ADDRESS TWO"
Write-Output $ipaddr2
"IP INTERFACE"
Write-Output $interface.Ip
If ($ipaddr1 -ne $($interface.Ip) -and $interface.RouteInterfaceId -eq "eth0") {
"Setting IP configuration for eth0 on " + $vmname + "………………please wait…"
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface[0] -HostCredential $HostCred -GuestCredential $GuestCred -Ip $ipaddr1 -Netmask $subnet1
#-Gateway $gateway1
}
If ($ipaddr2 -ne $($interface.Ip) -and $interface.RouteInterfaceId -eq "eth1") {
"Setting IP configuration for eth1 on " + $vmname + "………………please wait…"
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $GuestInterface[1] -HostCredential $HostCred -GuestCredential $GuestCred -Ip $ipaddr2 -Netmask $subnet2
#-Gateway $gateway2
}
} # End Inner For Each
} # End Outter For Each
You’ll have to give me some time… I’m not sure when I’ll have the cycles.
Will do what I can.
Thank you,
Jase
Not a problem at all…Appreciate the response.
I’m looking for a suggestion or comments on a situation where I’d like to use Get/Set-VMGuestNetworkInterface against Win2k8 64bit VM’s with PowerCLI v4.1. We know windows 2008 isn’t supported with the default installation of v4.1 but since the implementation of the cmdled is simply running a batch file within the OS, I’m not sure why you can’t take the file (GetVmGuestNetworkInterface_windows7Server64Guest.bat) which is included with PowerCLI v5 and copy it into the Scripts directory of your PowerCLI 4.1 installation.
Logically I thought this would work since I did verify the bat file works from within the OS but the cmdlet fails with a “Unable to parse script output” error when run through PowerCLI v4.1.
Any thoughts on how this can be done?
To be honest, I haven’t used the script in quite a while.
I’m wondering what the differentiator is between x64 and x86 OS’es is relative to this.
Maybe Alan Renouf (http://www.virtu-al.net/) has an answer…
Please note that Get-VMGuestNetworkInterface is bound to OS’s languages (in Windows OS at least)
In fact, the scripts provided by vmware (ex. : GetVmGuestNetworkInterface_windows7Server64Guest.bat) is parsing the output of the command “ipconfig /all” … the parsing is looking for specific words/characters/spaces/etc in the output … and as you can imagine, it only works when that output is run on English version of the OS. Hence the “Unable to parse script output” error when running in a French or German or whatever non-english guest Windows version.
Since I was struggling with that error myself, I hope it helps someone else..
Hi ,
I needed to get and set default gateway on guest virtual machine using the following Power CLI cmdlet.
Get-VMGuestNetworkInterface -vm -GuestUser -GuestPassword
When I run the cmdlet I get the following error on the vSphere PowerCLI shell.
Permission to perform this operation was denied. Required privilege ‘VirtualMachine.GuestOperations.Modify’ on managed object with id ‘VirtualMachine-vm-4073’.
However,I can list the VM in the PowerCLI shell successfully using Get-VM cmdlet.
Can you please let me know which permission is required to run Get-VMGuestNetworkInterface, whom to assign and from where ?
Do we need to install VMWare tools on guest VM ? is that a prerequisite for running this cmdlet.
Thanks,
Regards,
Gagan
Gagan,
I’m a little rusty here, as this is an old post.
I do believe you are required to have the VMware Tools installed in the guest to be able to get/set parameters inside of it.
Hi,
Can anybody help me to get the interface information for centos7 and redhat 7?
Thanks in advance.