we have requirement to keep clone the VMs with os disks only, is it doable with powercli?
Clone the VM then remove the non-system VMDK
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
We have multiple VMs which need to be cloned.
We have servers in few TBs so cloning 50 GB OS disk will take less time comparing taking a full clone.
Also, we have got some dedicated NFS datastore which sizes are as scope OS disks size so taking clone and then delete disks from datastore cleanup will be another effort.
Our goal is that we must exclude all data disks before submitting the clone as manually from vSphere client it is possible just wanted to understand what would be the steps from powercli to implement it for bulk.
Ok, I see.
Then you will have to use the API method.
Something like this clones a VM, and only 'Hard disk 1' is cloned along.
The other harddisks are not cloned.
Note: the script assumes that the system disk is labeled "Hard disk 1"
$vmName = 'SourceVM'
$vmCloneName = "$vmName-clone"
$targetFolderName = 'MyFolder'
$targetDatastoreName = 'MyDS'
$vm = Get-VM -Name $vmName
$folder = Get-Folder -Name $targetFolderName
$ds = Get-Datastore -Name $targetDatastoreName
$spec = New-Object -TypeName VMware.Vim.VirtualMachineCloneSpec
$spec.Config = New-Object -TypeName VMware.Vim.VirtualMachineConfigSpec
$spec.Template = $false
$spec.PowerOn = $false
$spec.Location = New-Object -TypeName VMware.Vim.VirtualMachineRelocateSpec
Get-HardDisk -VM $vm |
ForEach-Object -Process {
if ($_.Name -eq 'Hard disk 1') {
$disk = New-Object -TypeName VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$disk.Datastore = $ds.Id
$disk.DiskId = $_.ExtensionData.Key
$disk.DiskBackingInfo = New-Object VMware.Vim.VirtualDiskFlatVer2BackingInfo
$disk.DiskBackingInfo.FileName = ''
$disk.DiskBackingInfo.EagerlyScrub = $_.ExtensionData.Backing.EagerlyScrub
$disk.DiskBackingInfo.ThinProvisioned = $_.ExtensionData.Backing.ThinProvisioned
$disk.DiskBackingInfo.DiskMode = $_.ExtensionData.Backing.DiskMode
$spec.Location.Disk += $disk
}
else {
$dev = New-Object -TypeName VMware.Vim.VirtualDeviceConfigSpec
$dev.FileOperation = [VMware.Vim.VirtualDeviceConfigSpecFileOperation]::destroy
$dev.Operation = [VMware.Vim.VirtualDeviceConfigSpecOperation]::remove
$dev.Device = $_.ExtensionData
$spec.Config.DeviceChange += $dev
}
}
$vm.ExtensionData.CloneVM($folder.Id, $vmCloneName, $spec)
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks, that was really helpful.
Ended up with below, it's working but not picking datastore as it's hardcoded in csv. Any suggestion how can we enforce the storage selection for clone without disturbing parent properties i.e; $vm.ExtensionData.CloneVM($vm.ExtensionData.Parent, $vmdes, $spec)
connect-viserver vc.fqdn
$vms = Import-Csv -Path C:\Users\anjula\Desktop\Clone_VM_UAT.csv
foreach ($vmdet in $vms) {
$vmsrc=$vmdet.Template
$vmdes=$vmsrc+"_imgdrp"
Write-Warning "Creating $($vmdes)"
$vm = Get-VM -Name $vmsrc
$ds = Get-Datastore -Name $vmdet.Datastore
Write-Warning "Creating $($ds.name)"
$spec = New-Object -TypeName VMware.Vim.VirtualMachineCloneSpec
$spec.Config = New-Object -TypeName VMware.Vim.VirtualMachineConfigSpec
$hd=Get-VM -Name $vm | Get-HardDisk |Where-Object {$_.ExtensionData.UnitNumber -ne '0' -and $_.Parent.Extensiondata.Config.Hardware.Device.BusNumber -ne '0'}
foreach ($hds in $hd)
{
$delDisk = New-Object VMware.Vim.VirtualDeviceConfigSpec
$delDisk.Device = $hds.ExtensionData
$delDisk.Operation ="remove"
$spec.Config.DeviceChange += $delDisk
}
$spec.Location = New-Object -TypeName VMware.Vim.VirtualMachineRelocateSpec
$vm.ExtensionData.CloneVM($vm.ExtensionData.Parent, $vmdes, $spec)
}
Since you marked your own reply as the solution I guess you will have no problem answering that as well.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That was mistakenly done...I looked for to revert but couldn't find the option 🙂
I unmarked the Solution.
The allocation of the target datastore for 'Hard disk 1' is done with the line
$disk.Datastore = $ds.Id
If you want to use the datastore defined in the CSV you will have to keep that part from my original reply.
And change the following line accordingly (assuming the CSV contains a column named Datastore).
$ds = Get-Datastore -Name $vmdet.Datastore
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference