Archive

Posts Tagged ‘powercli’

PowerCLI cmdlets: Get/Set-VMGuestNetworkInterface

June 8th, 2010 Jase No comments

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:

PowerCLI cmdlets: Get/Set-OSCustomizationNicMapping

June 5th, 2010 Jase No comments

At some point in the near future, I have to create several hundred new VM’s.  These VM’s will be using the same Customization Specification, but some will need to have Static IP addresses, and others will need to have DHCP addresses that are reserved based on Mac Address.

The Task
Alright, how am I going to create 400-500 VM’s with specific names and specific IP’s (with some being DHCP)?  I know there are some tools like the RCU from NetApp that will rapidly provision VM’s, but I’m not looking for 100% clones, as not all of these are going to be used for the same purpose (not using VDI here).

Customization Specifications typically can only be used once per VM when attempting to use a Static IP address.  Using DHCP, a Customization Specification can be easily reused, as it doesn’t change.  The problem is, what if I want to give each VM a Static IP.  That requirement makes it a little more difficult.

The Tool: PowerCLI
There are a couple new cmdlets in the 4.0 Update 1 release of the PowerCLI that will help accomplish this task.

  • Get-OSCustomizationNicMapping
  • Set-OSCustomizationNicMapping

Using these together in a PowerCLI script, settings like IP address (if static), DHCP, gateway, DNS & WINS settings, and Mac Address can easily be set.

The syntax for these are as follows:

Get-OSCustomizationNicMapping
SYNTAX
Get-OSCustomizationNicMapping [-Spec] <OSCustomizationSpec[]> [-Server <VIServer[]>] [<CommonParameters>]

Set-OSCustomizationNicMapping
SYNTAX
Set-OSCustomizationNicMapping -OSCustomizationNicMapping <OSCustomizationNicMapping[]> [-Position <Int32>] [-Server <VIServer[]>] [-IpMode <OSCustomizationIPMode>] [-VCApplicationArgument <String>] [[-IpAddress] <String>] [[-SubnetMask] <String>] [[-DefaultGateway] <String>] [-AlternateGateway <String>] [[-Dns] <String[]>] [-Wins <String[]>] [-WhatIf] [-Confirm] [<CommonParameters>]

Set-OSCustomizationNicMapping -OSCustomizationNicMapping <OSCustomizationNicMapping[]> [-NetworkAdapterMac <String>] [-Server <VIServer[]>] [-IpMode <OSCustomizationIPMode>] [-VCApplicationArgument <String>] [[-IpAddress] <String>] [[-SubnetMask] <String>] [[-DefaultGateway] <String>] [-AlternateGateway <String>] [[-Dns] <String[]>] [-Wins <String[]>] [-WhatIf] [-Confirm] [<CommonParameters>]

Get-Help Get/Set-OSCustomizationNicMapping -full can give you more information on each of these cmdlets.

My Script
So I put together a little script to read content from a file, set a nic mapping for the selected Customization Specification, clone the VM, and set the appropriate VLAN for the VM.

The text file proceeds with the assumption that the DNS and WINS servers are the same.  The pdnswins and sdnswins variables are used twice each, one for the primary DNS/WINS and once for the secondary DNS/WINS.  Here are the contents of my text file that contains 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

I saved the file as C:\vms.csvEven though I named the file with a .csv extenstion, I decided to use colons rather than commas.  I did this because I wanted to send multiple DNS/WINS entries to my script, but I’ll get into that a little later. I have updated the script to use the standard comma delimiter.

The script to clone the VM’s and set their appropriate values

##########################################################
# cloneandsetip.ps1
# Jase McCarty 6/5/2010
# Posh Script to clone VM's and set appropriate
# IP addresses in Windows Virtual Machines
##########################################################
Connect-VIServer vcenter.jasemccarty.com

$vmlist = Import-CSV C:\vms.csv

foreach ($item in $vmlist) {

	# I like to map out my variables
	$basevm = $item.basevm
	$datastore = $item.datastore
	$vmhost = $item.vmhost
	$custspec = $item.custspec
	$vmname = $item.vmname
	$ipaddr = $item.ipaddress
	$subnet = $item.subnet
	$gateway = $item.gateway
	$pdns = $item.pdnswins
	$pwins = $item.pdnswins
	$sdns = $item.sdnswins
	$swins = $item.sdnswins
	$vlan = $item.vlan

	#Get the Specification and set the Nic Mapping (Apply 2 DNS/WINS if 2 are present)
	If ($Varable) {
		Get-OSCustomizationSpec $custspec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIp -IpAddress $ipaddr -SubnetMask $subnet -DefaultGateway $gateway -Dns $pdns,$sdns -Wins $pwins,$swins
	} else {
		Get-OSCustomizationSpec $custspec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIp -IpAddress $ipaddr -SubnetMask $subnet -DefaultGateway $gateway -Dns $pdns -Wins $pwins
	}

	#Clone the BaseVM with the adjusted Customization Specification
	New-VM -Name $vmname -VM $basevm -Datastore $datastore -VMHost $vmhost | Set-VM -OSCustomizationSpec $custspec -Confirm:$false

	#Set the Network Name (I often match PortGroup names with the VLAN name)
	Get-VM -Name $vmname | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $vlan -Confirm:$false

	#Remove the NicMapping (Don't like to leave things unkept)
	Get-OSCustomizationSpec $custspec | Get-OSCustomizationNicMapping | Remove-OSCustomizationNicMapping -Confirm:$false
}

Set-OSCustomizationNicMapping is very powerful.  Further examination of the documentation will show that things like setting the Mac Address and Alternate Gateway are also possible.

The Gotchas
There are a couple gotchas that I found, and you might want to be aware of.

  • The setting -PrimaryWins in the documentation does not work, use -Wins. Documentation and error messages will continue to state -PrimaryWins, but that attribute doesn’t work.
  • Multiple settings for DNS/WINS must read something like this 192.168.0.199,192.168.0.198.

    I had some difficulty passing 2 DNS/WINS entries into a single variable, so I am basically performing a check to see if a second entry is present.

In Closing
Thanks VMware for the very useful cmdlets to help make our jobs easier.

For more info on each of these commands, look here for the VMware documentation:

VMworld 2010 Call for Papers – Need a little help

May 14th, 2010 Jase No comments

Well I have submitted papers for the last 3 VMworlds, and unfortunately have not been selected.  I’ll admit some of those previous submissions were good enough, but missed a the oomph to put them over the top.

I submitted a paper, yes, just a single paper this year, and with some help, I could be selected.  This year, VMware is doing something a little different.  Public voting is being considered in the select process.

The paper I submitted details how to leverage VMware vSphere, NetApp SnapMirror, NetApp SnapManager for Virtual Infrastructure (SMVI), vSphere PowerCLI, and PoshOnTap to spin up a warm DR site.  I chose this topic, because this is how I set a solution up last year when VMware SRM did not support NFS storage.  This session talks about how to quickly recover a SnapMirror replicated site using PowerCLI, with some PoshOnTap included.

So if you feel like voting for my session, head over to VMworld.com at the following URL: http://www.vmworld.com/community/conferences/2010/cfpvote/pcbusiness.

You will be required to login to vote, but joining VMworld.com is free.

Thanks for any and all votes, and best of luck to everyone else who submitted a paper/presentation.

Set Guest OS I/O Timeout Settings via PowerShell

April 29th, 2010 Jase 5 comments

Back in October 2009, I wrote a post on how to remotely set the TimeoutValue for the Disk service in Windows per NetApp’s best practices.  It is kind of a pain to grab a list of VM’s, make a bunch of batch files, call them, and so on.

I was playing around with the PSRemoteRegistry PowerShell module, and figured out a better way of doing it… Using PowerShell.

To make this work
A few things are needed:

  • PowerShell 2.0
  • vSphere PowerCLI
  • PSRemoteRegistry
  • vCenter Server and appropriate access by the account running the script
  • Connectivity to the Guest as the changes are made via a remote registry call
  • Credentials in the VM to make changes using the same account running the script
  • Run this script from the vSphere PowerCLI

The Workflow
The script will basically need to enumerate all VM’s, perform a registry query to see if the TimeoutValue exists, and depending on what the result is, either update the setting or create it if it does not exist.  Because this only relates to Windows OSes, I chose to only look at VM’s running Windows.  Also, no point in attempting the update on a VM that isn’t powered on, given that I’m making a remote registry call.

The PowerShell functions that help with the process are Test-RegValue and Set-DWord, both of which are part of the Remote Registry PowerShell Module.  I’m not going to go into the syntax of these functions, but more information can be found on them using Get-Help Test-RegValue and Get-Help Set-DWord once the PSRemoteRegistry module is loaded.

Two variables I’m using are $tovdec and $tovhex which are TimeOut Value in Decimal and TimeOut Value in Hexadecimal.  These can easily be changed to a value that is appropriate with whatever storage is being used, based on the recommendations of the storage vendor (NetApp, EMC, etc).

The Script
Here is the script I came up with:

##########################################################
# correctvmtimeout.ps1
# Jase McCarty 4/29/2010
# Posh Script to set/correct TimeoutValue
# in Windows Virtual Machines
##########################################################

#Import the PSRemoteRegistry
Import-Module PSRemoteRegistry

#Connect to vCenter Server
Connect-VIServer MYvCenterServer

# Specify the Hive, RegKey, and DWORD Value
$Hive = "LocalMachine"
$DiskKey = "SYSTEM\CurrentControlSet\Services\Disk"
$tovdec = "190"
$tovhex = "0xBE"

# Get only Windows VM's that are Powered On and are Windows Guests
Get-VM | Sort-Object Name | Where { $_.PowerState -eq "PoweredOn" } | %{get-view $_.ID} | Foreach {If ($_.guest.GuestFamily -eq "windowsGuest") {

     # Check to see if the value is present, and if it is, what is the value
     $Key = Test-RegValue -CN $_.Name -Hive $Hive -Key $DiskKey -Value TimeoutValue -PassThru

     If ($Key -eq $false) {
          Write-Host $_.Name,incorrect,missing,correcting
          Set-RegDWord -CN $strComputer -Hive $Hive -Key $DiskKey -Value TimeoutValue -Data $tovhex -Force
          }
else {
          If ($Key.Data -eq $tovdec) {
              Write-Host $Key.ComputerName, correct,$Key.Data
          }
          else    {
             Write-Host $Key.ComputerName,incorrect,$Key.Data,correcting
             Set-RegDWord -CN $Key.ComputerName -Hive $Hive -Key $DiskKey -Value TimeoutValue -Data $tovhex -Force
          }
       }
    }
}

I hope this helps anyone looking to perform a mass update of the TimeoutValue registry setting.  Additionally, this could be integrated into a config/check script that is run from time to time to ensure that all VM’s are held in compliance to the appropriate values a storage vendor recommends.

I have a couple different types of storage, so maybe I will add some additional logic to determine the storage provider, and adjust accordingly… Now to find the time to do it.

And many thanks to Shay Levy for the work on the PSRemoteRegistry module!

PowerCLI Script – With Voice

February 19th, 2010 Jase 3 comments

I was looking at some tweets, and noticed one from @ScriptingGuys about how to add voice to a PowerShell script.  Here is the actual tweet: http://twitter.com/ScriptingGuys/statuses/9343448757

Here’s the syntax in an example:
(New-Object -ComObject sapi.spvoice).speak(“Greetings Professor Falken”)
(New-Object -ComObject sapi.spvoice).speak(“Shall we play a game”)

So I took one of my PowerShell scripts, and modified it.  I chose my PowerCLI: NFS Settings for vSphere (NetApp NFS Recommendations) script, because it is a short script, and it was easy to update.

#***************************************************************************
#
# Update TCP and NFS Advanced Configuration Settings for vSphere w/Voice
# Author: Jase McCarty
# Date: 2/19/2010
#
#***************************************************************************

<span style="color: #0000ff;">(New-Object -ComObject sapi.spvoice).speak("What is the ESX Host Name or IP Address")</span>
$ESXHOST = Read-Host “Enter ESX Host Name or IP”
Connect-VIServer $ESXHOST

<span style="color: #0000ff;"> (New-Object -ComObject sapi.spvoice).speak("Now updating TCP and NFS Advanced Configuration Settings on host " + $ESXHOST)</span>
Write-Host “Updating TCP and NFS Advanced Configuration Settings on host ” + $ESXHOST

# Update TCP Settings
Set-VMHostAdvancedConfiguration -VMHost $ESXHOST -Name Net.TcpipHeapSize  -Value 30
Set-VMHostAdvancedConfiguration -VMHost $ESXHOST -Name Net.TcpipHeapMax  -Value 120

# Update NFS Settings (For ESX 3.5, MaxVolumes should be 32)
Set-VMHostAdvancedConfiguration -VMHost $ESXHOST -Name NFS.MaxVolumes  -Value 64
Set-VMHostAdvancedConfiguration -VMHost $ESXHOST -Name  NFS.HeartbeatMaxFailures -Value 10
Set-VMHostAdvancedConfiguration -VMHost $ESXHOST -Name  NFS.HeartbeatFrequency -Value 12
Set-VMHostAdvancedConfiguration -VMHost $ESXHOST -Name  NFS.HeartbeatTimeout -Value 5

(New-Object -ComObject sapi.spvoice).speak("NetApp Settings Complete")

Pretty cool addition.  A good use of this, (as well as text prompts) would be when running commands against vCenter, “vocally” indicating changes to objects (hosts, clusters, guests, etc) as they are being modified.

This might be a little much, but when running a script against many objects, it would not require having to watch the screen for output while the script is running.  Attention could then be focused on other things.

I don’t know if anyone is going to use this little addition, as it does take extra code.  Administrators who approach scripts like I do (with many status messages and the like) might find this as a cool addition.

Figured I’d share.

$NVPG = Get-VMHost $ESXHOST | Get-VirtualSwitch -Name “vSwitch0″ | New-VirtualPortGroup -Name “VLAN100″ -VLanId “100″;
Categories: Virtualization Tags: , , ,