OlivierD
Contributor
Contributor

Change vnic-portgroup Assignment during Clone operation

Jump to solution

Hello,

I've got a powershell script that creates VMs from a Template, and I want to change the vnic-portgroup

assignement in my Clone Specification.

$vmcSpec = New-Object VMware.Vim.VirtualMachineCloneSpec

$vmspec.Config = New-Object VMware.Vim.VirtualMachineConfigSpec

How can access to the nic configuration through $vmspec.Config ? With deviceChange property ?

Thanks for your help

Olivier

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership

Yes, you will have to use the VirtualDeviceConfigSpec via the deviceChange property.

A useful trick is to first find the device in question and then just change the required properties.

In this case only the network (portgroup) needed to be changed

$templateName = <template-name>
$newVM = <VM-name>
$esxName = <ESX-hostname>
$poolName = <resourcepoolname>
$nicName = <NIC-name>                                # Ex "Virtual Ethernet Adapter"
$newPGName = <new-portgroup-name>
$folderName = <foldername>
$datastoreName = <datastorename>

$fromVM = Get-View -Id (Get-Template $templateName).Id
$folder = Get-Folder $folderName | Get-View
$esx = Get-VMHost $esxName | Get-View
foreach($pg in $esx.Network){
	if((Get-View $pg).Name  -eq $newPGName){
		break
	}
}

$found = $false
foreach($dev in $fromVM.Config.Hardware.Device){
	if($dev.DeviceInfo.Label -eq $nicName){
		$found = $true
		break
	}
}

$spec = New-Object VMware.Vim.VirtualMachineCloneSpec
$spec.Config = New-Object VMware.Vim.VirtualMachineConfigSpec 
$devSpec = New-Object VMware.Vim.VirtualDeviceConfigSpec
$devSpec.device = $dev
$devSpec.Device.Backing.DeviceName = $newPGName
$devSpec.Device.Backing.Network = $pg
$devSpec.Operation = "edit"
$spec.Config.deviceChange += $devSpec

$spec.location = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.location.datastore = (Get-Datastore $datastoreName | Get-View).MoRef
$spec.location.host = (Get-VMHost $esxName | Get-View).MoRef
$spec.Location.Pool = (Get-ResourcePool $poolName | Get-View).MoRef
$spec.powerOn = $false
$spec.template = $false

$fromVM.CloneVM_Task($folder.MoRef, $newVM, $spec)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
3 Replies
LucD
Leadership
Leadership

Yes, you will have to use the VirtualDeviceConfigSpec via the deviceChange property.

A useful trick is to first find the device in question and then just change the required properties.

In this case only the network (portgroup) needed to be changed

$templateName = <template-name>
$newVM = <VM-name>
$esxName = <ESX-hostname>
$poolName = <resourcepoolname>
$nicName = <NIC-name>                                # Ex "Virtual Ethernet Adapter"
$newPGName = <new-portgroup-name>
$folderName = <foldername>
$datastoreName = <datastorename>

$fromVM = Get-View -Id (Get-Template $templateName).Id
$folder = Get-Folder $folderName | Get-View
$esx = Get-VMHost $esxName | Get-View
foreach($pg in $esx.Network){
	if((Get-View $pg).Name  -eq $newPGName){
		break
	}
}

$found = $false
foreach($dev in $fromVM.Config.Hardware.Device){
	if($dev.DeviceInfo.Label -eq $nicName){
		$found = $true
		break
	}
}

$spec = New-Object VMware.Vim.VirtualMachineCloneSpec
$spec.Config = New-Object VMware.Vim.VirtualMachineConfigSpec 
$devSpec = New-Object VMware.Vim.VirtualDeviceConfigSpec
$devSpec.device = $dev
$devSpec.Device.Backing.DeviceName = $newPGName
$devSpec.Device.Backing.Network = $pg
$devSpec.Operation = "edit"
$spec.Config.deviceChange += $devSpec

$spec.location = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.location.datastore = (Get-Datastore $datastoreName | Get-View).MoRef
$spec.location.host = (Get-VMHost $esxName | Get-View).MoRef
$spec.Location.Pool = (Get-ResourcePool $poolName | Get-View).MoRef
$spec.powerOn = $false
$spec.template = $false

$fromVM.CloneVM_Task($folder.MoRef, $newVM, $spec)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
OlivierD
Contributor
Contributor

Thank you for the tip.

Here is the extract of my script (My template has 2 nics) :

$vmcSpec = New-Object VMware.Vim.VirtualMachineCloneSpec

$templateId = get-view -Id (Get-Template -Name $vmtemplate).Id

$vmcSpec.Config = New-Object VMware.Vim.VirtualMachineConfigSpec

#Create an array of VirtualDevice

$nics = @(New-Object VMware.Vim.VirtualDevice)

#Get Nics from template

foreach ($dev in $templateId.Config.Hardware.Device ) {

if ($dev.DeviceInfo.Label -eq "Network Adapter 1" ) {

$nics[0] = $dev

}

if ($dev.DeviceInfo.Label -eq "Network Adapter 2" ) {

$nics += New-Object VMware.Vim.VirtualDevice

$nics[1] = $dev

}

}

#Nic0

$nicSpec0 = New-Object VMware.Vim.VirtualDeviceConfigSpec

$nicSpec0.device = $nics[0]

$nicSpec0.Device.Backing.DeviceName = $nic0_pg

$nicSpec0.Device.Backing.Network = $pg

$nicSpec0.Operation = "edit"

$vmcSpec.Config.deviceChange += $nicSpec0

#Nic1

$nicSpec1 = New-Object VMware.Vim.VirtualDeviceConfigSpec

$nicSpec1.device = $nics[1]

$nicSpec1.Device.Backing.DeviceName = $nic1_pg

$nicSpec1.Device.Backing.Network = $pg

$nicSpec1.Operation = "edit"

$vmcSpec.Config.deviceChange += $nicSpec1

etc ....

Thank you for your help

Olivier

0 Kudos
IanGibbs
Enthusiast
Enthusiast

This example code won't work  in current versions of vCenter. Don't know if it ever did.

1. "Property 'DeviceName' cannot be found on this object; make sure it exists and is settable."

This will be the first error you get from this code. To resolve, replace

$devSpec.Device.Backing.DeviceName = $newPGName

with

$nicBacking = New-Object VMware.Vim.VirtualEthernetCardNetworkBackingInfo
$nicBacking.deviceName = $newPGName
$devSpec.Device.Backing = $nicBacking

2. "Get-VMHost : Cannot validate argument on parameter 'Name'. The argument is null or empty."

This will be your next error. To fix this, in each of the following lines (in various places), add -Name after the Get- cmdlet:

a - $folder = Get-Folder $folderName | Get-View
b - $esx = Get-VMHost $esxName | Get-View
c - $spec.location.host = (Get-VMHost $esxName | Get-View).MoRef
d - $spec.Location.Pool = (Get-ResourcePool $poolName | Get-View).MoRef

such as

$esx = Get-VMHost -Name $esxName | Get-View


As a side note, if you don't have any resource pools in use, you can put the clone in the root of the cluster like this:

$spec.Location.Pool = (Get-Cluster -Name $cluster_name | Get-ResourcePool -Name "Resources" | Get-View).MoRef
0 Kudos