PowerCLI cmdlets: Get/Set-OSCustomizationNicMapping

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:

25 Replies to “PowerCLI cmdlets: Get/Set-OSCustomizationNicMapping

  1. Quick question, where do you specify which vm template to use when deploying these? Is that ‘basevm?’

    Thanks

  2. Doh! Just re-read it and saw where you specified the custom spec. However what did you specify when making your customization specifications file? Specifically under Network? Typical? and just allowed the script to set the IP addresses? Or Custom setting?

    Also you are deploying these from a template? Just cloning another VM? Is that correct?

  3. Thanks Jase

    However, I run into 2 problems when I attempt to use a template:

    “New-VM : 3/9/2011 2:23:10 PM New-VM Could not find VirtualMachine with name ‘Template_w2k3r2e64’.” When in fact there is a template with that name.

    “New-VM : 3/9/2011 2:23:10 PM New-VM Value cannot be found for the mandatory parameter VM”

    Any ideas?

  4. Ok, I got it working(sort of)with some changes to your script. Now its failing when it attempts to run Remove-OSCustomizationNicMapping after it creates the first VM. It fails in the same spot no matter how many I try to deploy at once.

    cmdlet Remove-OSCustomizationNicMapping at command pipeline position 3
    Supply values for the following parameters:
    OSCustomizationNicMapping[0]:

    Can you contact me offline to discuss? Would be more than happy to share my results once this is working as it should.

    Thanks Jase!

  5. I got around that error with this.

    Get-OSCustomizationSpec $custspec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IPMode UseDHCP

    To just set it back to dchp.

    My issue is Im not getting the IP’s to apply at all. Ive tried lots of variations to the syntax and nothing works. I can open the custspec and see the IP’s getting added in there but they dont apply to the VM created from my template.

    Did you change and of the New-VM stuff?

    1. I haven’t made any changes to the script.

      I’ll have to run through this in my new lab and see if there are any updates for vSphere 4.1.

      Thanks,
      Jase

  6. Thanks Jase
    I have a very similiar script that will do the same, the only thing I am unsure of, is how do you set the Network Label (PortGroup) for the network adapter you are creating the NicMapping for? There does not seem to be a switch for attaching network label.
    We have many PortGroups in the cluster and I need to assign the correct network label to the NetworkAdapter so that the cusomisation wizard can complete and connect to the domain.

    thanks
    Paul

  7. Please ignore that last post, I had not read all of the script and can see you set it with:
    Get-VM -Name $vmname | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $vlan -Confirm:$false

    I had thought maybe we could have done it through the Set-OSCustomizationNicMapping
    cmdlt.

    Cheers
    Paul

  8. I tried using the script on Linux templates?
    Its not setting the default gateway on boot?
    Is there something I am missing? Do I need to modify script for linux VMs?

  9. @Mark
    Also seeing these errors, not sure what to do?

    New-VM : 2/17/2012 12:29:04 PM New-VM An item with the same key has a
    lready been added.
    At U:\powercli\deployvm.ps1:36 char:11
    + New-VM <<<< -Name $vmname -template $basevm -Datastore $datastore -VMHos
    t $vmhost | Set-VM -OSCustomizationSpec $custspec -Confirm:$false
    + CategoryInfo : NotSpecified: (:) [New-VM], VimException
    + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomatio
    n.ViCore.Cmdlets.Commands.NewVM

    cmdlet Remove-OSCustomizationNicMapping at command pipeline position 3
    Supply values for the following parameters:
    OSCustomizationNicMapping[0]: 0
    OSCustomizationNicMapping[1]: false
    OSCustomizationNicMapping[2]: false
    OSCustomizationNicMapping[3]: false
    OSCustomizationNicMapping[4]: true
    OSCustomizationNicMapping[5]:
    Remove-OSCustomizationNicMapping : Cannot bind parameter 'OSCustomizationNicMap
    ping'. Cannot convert the "0" value of type "System.String" to type "VMware.Vim
    Automation.ViCore.Types.V1.OSCustomization.OSCustomizationNicMapping".
    At U:\powercli\deployvm.ps1:42 char:105
    + Get-OSCustomizationSpec $custspec | Get-OSCustomizationNicMapping | Remov
    e-OSCustomizationNicMapping <<<< -Confirm:$false
    + CategoryInfo : InvalidArgument: (:) [Remove-OSCustomizationNicM
    apping], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomat
    ion.ViCore.Cmdlets.Commands.RemoveOSCustomizationNicMapping

  10. @Mark
    Note that you can no longer pipe to Remove-OSCustomizationNicMapping which is why your problem is occuring and now the command may look something more like this,
    Remove-OSCustomizationNicMapping -OSCustomizationNicMapping (Get-OSCustomizationSpec $custspec | Get-OSCustomizationNicMapping) -Confirm:$false
    This will stop you getting that error
    but beware as I believe this will remove the NIC1 altogether meaning you would have to create a new one on the next run of the script.

    If anyone knows the new commands that would be great.
    @Jase, I am currently developing this for multiple NICs, think I am going to add the adapters every time rather than just modify the existing ones. Unless you already had something that did multiple NICs? If not don’t worry I’ll try and create new ones, thanks for this post really gave me a great starting point.

  11. Hi, I am trying to use this script to deploy about 45 servers. All with static IP’s.

    I find that I have to run it in the 32 bit version of PowerCLI.

    My problem is that the Set-OSCustomizationNicMapping does not work. It does not modify the Custom Spec at all. I am working on vSphere 5.5 and PowerCLI 5.5 Release 1. Is this a problem?

    here is the code:

    $custspec = “PowerCLI”
    $ipaddr = “10.0.0.2”
    $subnet = “255.255.255.0”
    $gateway = “10.0.0.1”
    $pdns = “10.0.0.20”

    Get-OSCustomizationSpec $custspec |
    Get-OSCustomizationNicMapping |
    Set-OSCustomizationNicMapping -IpMode UseStaticIp -IpAddress $ipaddr -SubnetMask $subnet -DefaultGateway $gateway -Dns $pdns

  12. @OldDog
    I copied a working OSCustomizationSpec and used that. It worked, at least on one machine. So I am thinking there was something wrong with my original, I will try with the rest of my servers in the morning.

  13. #Remove the NicMapping (Don’t like to leave things unkept) Get-OSCustomizationSpec ++

    This was causing the script to fail. apparently in 5.5 the Set-OSCustomizationNicMapping expects there to be something in the Nic fields, even if its just DHCP. When I commented this piece out, the script ran as expected. It just overwrites whatever might be in there. It might pay to set everything back to DHCP after the script has run in order to get ready for the next batch.

  14. Hi,
    I have a code for NIC customization:
    My Query : I have 2 NIC cards, first IP requires a gateway and second IP should have no gateway. I get error for below code that when i use ‘UseStaticIP’ IPmode it requires gateway for second IP too. Can you please suggest how to handle in customization code ? I have used same cmds using if else based on number of NICs.
    CODE:
    $nicMapping = Get-OSCustomizationNicMapping -OSCustomizationSpec $specClone
    $specClone | New-OSCustomizationNicMapping -Position $l -IpMode UseStaticIP -IpAddress $ipTemp -SubnetMask $subnetMaskTemp -Dns $dnsServers[$k].split(‘,’)

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.