anjul-a
Contributor
Contributor

Clone VM without data disks for list of VMs.

we have requirement to keep clone the VMs with os disks only, is it doable with powercli?

0 Kudos
7 Replies
LucD
Leadership
Leadership

Clone the VM then remove the non-system VMDK


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

0 Kudos
anjul-a
Contributor
Contributor

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.

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
anjul-a
Contributor
Contributor

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

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos
anjul-a
Contributor
Contributor

That was mistakenly done...I looked for to revert but couldn't find the option 🙂

0 Kudos
LucD
Leadership
Leadership

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

0 Kudos