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
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
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
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
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