VMware Cloud Community
vin01
Expert
Expert
Jump to solution

How to find Linked clone VMs

I need to find the VM's which are created by linked clones from vCloud Director. Is there any automate way to get these vms?

I need to do storage migration/replacement of 60TB Luns in a storage cluster but the vcenter is mapped to vcloud director.

The Org VMs which resides on this storage contains linked clone VM's. Here is the problem I can't directly do svmotion as linked clones will break. So i need to identify either the linked clone VM or the .vmdk file of parent VM.

If i do grep  vmdk file then chain of delta disks will be identified. so anyway to automate this process to do cat the vmdk files.

Or any best way to find the linked cloned vms or the parent vm which contains linked clones either from vcenter or from vCloud using powershell

Regards Vineeth.K
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Reply
0 Kudos
13 Replies
LucD
Leadership
Leadership
Jump to solution

Does this help?
Listing all linked clones on your vCenter Server


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

Reply
0 Kudos
vin01
Expert
Expert
Jump to solution

Hi LucD,

I just got the results as below but when I try to export its not showing up in csv file. Can you please help

Sample output:

pastedImage_0.png

pastedImage_1.png

Regards Vineeth.K
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The BaseDisks property is an array, hence the way Export-Csv displays this.
You can put them all in 1 cell as 1 string, like this

Get-LinkedClone |

Select Name,@{N='BaseDisks';E={$_.BaseDisks -join '|'}} |

Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture


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

vin01
Expert
Expert
Jump to solution

Thanks. Now I Can export the output.

Regards Vineeth.K
Reply
0 Kudos
WJPConway
Contributor
Contributor
Jump to solution

Hey Luc,

I am having a bit of trouble with this - I am running against a vCenter 6.5 - but i'd imagine the problem is probably on my side rather than the versions.

I dont fully understand the function side - in particular the input of $vms  - there is an else without an if - or am i missing something - i'm not a scriptor so apologies if i am missing something obvious - can you provide some guidance - also if i wanted to limit to a cluster can i just pipe | Get-Cluster 'Example' before the Get-View?

This is what i am trying to run - which runs without error but outputs nothing to the csv

function Get-LinkedClone {

 

      $vms = Get-View -ViewType VirtualMachine -Property Name,Summary,Config.Hardware.Device {

   } else {

      $vms = Get-View -ViewType VirtualMachine -Property Name,Summary,Config.Hardware.Device -Filter @{Name = $args[0]}

   }

   $linkedClones = @()

   foreach ($vm in $vms) {

      $unshared = $vm.Summary.Storage.Unshared

      $committed = $vm.Summary.Storage.Committed

      $ftInfo = $vm.Summary.Config.FtInfo

      if ( ($unshared -ne $committed) -and (($ftInfo -eq $null) -or ($ftInfo.InstanceUuids.Length -le 1)) ){

         # then $vm is a linked clone.

         # Find $vm's base disks.          $baseDisks = @()

         foreach ($d in $vm.Config.Hardware.Device) {

            $backing = $d.backing

            if ($backing -is [VMware.Vim.VirtualDeviceFileBackingInfo] -and $backing.parent -ne $null) {

               do {

                  $backing = $backing.parent

               } until ($backing.parent -eq $null)

               $baseDisks += $backing.fileName

            }

         }

         $linkedClone = new-object PSObject

         $linkedClone | add-member -type NoteProperty -Name Name -Value $vm.name

         $linkedClone | add-member -type NoteProperty -Name BaseDisks -Value $baseDisks

         $linkedClones += $linkedClone

      }

      #else { do nothing for VMs that are not linked clones }    }

   $linkedClones | sort BaseDisks, Name

}

Get-LinkedClone |

Select Name,@{N='BaseDisks';E={$_.BaseDisks -join '|'}} |

Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture

}

Am I calling the function correctly at the end of the script? should there be any other inputs?

Reply
0 Kudos
WJPConway
Contributor
Contributor
Jump to solution

Have this mainly working now - changed to below - was missing a line -

Does anyone know how i could limit the search to a folder - reason i ask is out vCenter has more than 6000 vms - if i can search by folder i could limit the search to an ovdc/pvdc by inputting a folder

Another nice to have would be to display the vm folder in the output (this would link vm to vapp in vCD)

For reference I am using this to track shadow vms in vCD -

vCD doesnt automatically delete shadows if there is no vapp linked - it only deletes when the template is deleted as a result it is common for us to end up with orphan shadows taking up a lot of space - and if we can verify that nothing is linked to the orphan shadow we can safely delete

function Get-LinkedClone {

if( $args[0] -eq $null ) {

      $vms = Get-View -ViewType VirtualMachine -Property Name,Summary,Config.Hardware.Device

   } else {

      $vms = Get-View -ViewType VirtualMachine -Property Name,Summary,Config.Hardware.Device -Filter @{Name = $args[0]}

   }

 

   $linkedClones = @()

   foreach ($vm in $vms) {

Write-host "Processing " $vm.Name  

      $unshared = $vm.Summary.Storage.Unshared

      $committed = $vm.Summary.Storage.Committed

      $ftInfo = $vm.Summary.Config.FtInfo

 

      if ( ($unshared -ne $committed) -and (($ftInfo -eq $null) -or ($ftInfo.InstanceUuids.Length -le 1)) ){

         # then $vm is a linked clone. 

         # Find $vm's base disks.          $baseDisks = @()

         foreach ($d in $vm.Config.Hardware.Device) {

            $backing = $d.backing

            if ($backing -is [VMware.Vim.VirtualDeviceFileBackingInfo] -and $backing.parent -ne $null) {

               do {

                  $backing = $backing.parent

               } until ($backing.parent -eq $null)

               $baseDisks += $backing.fileName

 

            }

         }

 

         $linkedClone = new-object PSObject

         $linkedClone | add-member -type NoteProperty -Name Name -Value $vm.name

         $linkedClone | add-member -type NoteProperty -Name BaseDisks -Value $baseDisks

         $linkedClones += $linkedClone

      }

      #else { do nothing for VMs that are not linked clones }    }

 

   $linkedClones | sort BaseDisks, Name

}

}

Get-LinkedClone | Select Name,@{N='BaseDisks';E={$_.BaseDisks -join '|'}} | Export-Csv -Path .\reportLink.csv -NoTypeInformation -UseCulture

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can use the SearchRoot parameter.

Something like this

$folder = Get-Folder -Name MyFolder

$vms = Get-View -ViewType VirtualMachine -SearchRoot $folder.ExtensionData.MoRef -Property Name,Summary,Config.Hardware.Device


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

Reply
0 Kudos
WJPConway
Contributor
Contributor
Jump to solution

This has limited the search to the folder - but the output file seems to be broken and have repeated entries -

So with a folder that has 24 vm's - I would expect a csv with 24 lines but i am getting 301  -

See an attached output file reportLinkperfolder.csv

This was run on a folder that has the 24 vms listed below  - any idea why i am getting the duplicates - and also it seems as if the basedisk column is is not clearing after a vm - so when you do vm1 - base disk info = vm1 - when you do vm2 - base disk info is vm1 and vm2 and so on so forth

vesxi010 (64397097-2e73-4017-b132-43cb2eb2b154)

vESXi014 (12741155-0f97-45f4-84db-9ff91262b958)

DD-Datastore1 (77e1275a-add8-48f8-9fd2-3ffcdd45b644)

vESXi037 (af1a5862-ea2b-45f2-bdcc-716d5f2a8afe)

vESXi038 (cb6dc566-8db4-4ceb-8f86-1bbc1f79de9d)

vESXi015 (06ed4e79-df5e-42d5-8160-2110a1e1f7d1)

vESXi033 (a26feebf-9c59-4ec8-a99e-6f4429495662)

vESXi016 (f594704e-6e32-4690-8ad5-ca0f66355231)

vESXi017 (c27e74ee-2735-461c-8367-d9610f0ebcac)

vESXi011 (48b63cba-23e7-46e0-8f94-e15502f1220a)

vESXi035 (1d9d88fc-2cbb-4f76-8733-6eb9736ab7ea)

LP (31d6ed9f-a176-4ff9-8e8b-c06a10b23ae5)

DC01 (40e8d857-0e68-443d-b64e-e59bfbf8ee6c)

vESXi032 (b0db4e5a-ae1c-4aeb-bbe1-7552499983e0)

vESXi013 (7da837bb-0b22-4a10-ab2b-8f5ba1da87d1)

vESXi036 (17a8ee3e-2fab-481b-8ed3-472ed3452060)

Router (b2f81952-f88d-40d7-b41c-e63fa60a1f1c)

SMTP-NTP (156baeaa-18a7-43df-a648-78527f145654)

vESXi031 (ee0dc0a6-86d5-4a40-82ce-1894c88b378e)

vesxi009 (714ddcac-79f4-43fe-a880-e9f25181eea1)

vESXi012 (c3673260-96b3-4fa6-a5fd-ef977d57bb40)

vESXi034 (083994e0-0615-4223-bd91-80c28730b5af)

vESXi018 (c40e34ba-9aac-4952-80be-0bb716ab4625)

sysops-agent01 (902531f9-bfdd-47c7-bf75-d9ee287a4aa0)

I assume my loop is wrong - but cant spot where

$folder = Get-Folder 'TestvApp'

function Get-LinkedClone {

if( $args[0] -eq $null ) {

      $vms = Get-View -ViewType VirtualMachine  -SearchRoot $folder.ExtensionData.MoRef -Property Name,Summary,Config.Hardware.Device

   } else {

      $vms = Get-View -ViewType VirtualMachine  -SearchRoot $folder.ExtensionData.MoRef -Property Name,Summary,Config.Hardware.Device -Filter @{Name = $args[0]}

   }

 

   $linkedClones = @()

   foreach ($vm in $vms) {

Write-host "Processing " $vm.Name  

      $unshared = $vm.Summary.Storage.Unshared

      $committed = $vm.Summary.Storage.Committed

      $ftInfo = $vm.Summary.Config.FtInfo

 

      if ( ($unshared -ne $committed) -and (($ftInfo -eq $null) -or ($ftInfo.InstanceUuids.Length -le 1)) ){

         # then $vm is a linked clone. 

         # Find $vm's base disks.          $baseDisks = @()

         foreach ($d in $vm.Config.Hardware.Device) {

            $backing = $d.backing

            if ($backing -is [VMware.Vim.VirtualDeviceFileBackingInfo] -and $backing.parent -ne $null) {

               do {

                  $backing = $backing.parent

               } until ($backing.parent -eq $null)

               $baseDisks += $backing.fileName

 

            }

         }

 

         $linkedClone = new-object PSObject

         $linkedClone | add-member -type NoteProperty -Name Name -Value $vm.name

         $linkedClone | add-member -type NoteProperty -Name BaseDisks -Value $baseDisks

         $linkedClones += $linkedClone

      }

      #else { do nothing for VMs that are not linked clones }    }

 

   $linkedClones | sort BaseDisks, Name

}

}

Get-LinkedClone | Select Name,@{N='BaseDisks';E={$_.BaseDisks -join '|'}} | Export-Csv -Path .\reportLinkperfolder.csv -NoTypeInformation -UseCulture

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Are you sure you have only 1 connectiion open?
What is in $global:defaultVIServers?


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

Reply
0 Kudos
WJPConway
Contributor
Contributor
Jump to solution

It has just one connection -

Part of the problem is fixed - I had accidentally commented out where it clears the BaseDisks array -

So the below is basically what I had - of course $baseDisks = @() was seen as a comment

         # Find $vm's base disks.      $baseDisks = @()

So now its

         # Find $vm's base disks.

          $baseDisks = @()

This has fixed the contents of the base disks column.

I am looking at the duplicates results and think these are not actually duplicates but possible just different vmdks - so i need to do a different test to see - I'll create a basic vApp with 3 vms - 1 with 1 disk - 1 with 2 disks and 1 with 3 disks - and see what my results are.

Reply
0 Kudos
WJPConway
Contributor
Contributor
Jump to solution

So the second part seems to be the placing of a bracket incorrectly on my side - again probably a copy and paste issue

   $linkedClones | sort Folder, Name, BaseDisks

}

Still testing but once confirmed ill post final script

Reply
0 Kudos
WJPConway
Contributor
Contributor
Jump to solution

Ok this is now working for me - Thanks Luc for providing assistance -  I think the ability to track LinkedClones is very useful for any vCloud Director admin. I changed around a few things including adding the Fodler column to the output and a loop through sub folder but the basic script is the same.

Get-Module -Name VMware* -ListAvailable | Import-Module

# vCenter Login Info

$vCUser="LAB\user"

$vCPass="Password"

$vCenterIP = "vCenterIP"

#Report Name

$filename = ".\PANA_LinkedClone.csv"

#Beginning of Folder Tree for script

$folderroot = 'OVDC-HPOD (6bb47beb-0712-4cd7-b87f-094062954179)'

# $folderroot = 'OVDC Cloud (e3c37cf2-6b73-41bb-88f9-c5b6628e2509)'

# $folderroot = 'OVDC (0f9ff3fc-7369-4ac7-8efb-8a7ba6a61143) = Sysops/Baldr'

Connect-VIServer $vCenterIP -User $vCUser -Password $vCPass -port 443

function Get-LinkedClone {

Write-Host "Processing Folder" $folder -ForegroundColor Green

if( $args[0] -eq $null ) {

      $vms = Get-View -ViewType VirtualMachine  -SearchRoot $folder.ExtensionData.MoRef -Property Name,Summary,Config.Hardware.Device

   } else {

      $vms = Get-View -ViewType VirtualMachine  -SearchRoot $folder.ExtensionData.MoRef -Property Name,Summary,Config.Hardware.Device -Filter @{Name = $args[0]}

   }

 

   $linkedClones = @()

   foreach ($vm in $vms) {

Write-host "Processing VM " $vm.Name  

      $unshared = $vm.Summary.Storage.Unshared

      $committed = $vm.Summary.Storage.Committed

      $ftInfo = $vm.Summary.Config.FtInfo

 

      if ( ($unshared -ne $committed) -and (($ftInfo -eq $null) -or ($ftInfo.InstanceUuids.Length -le 1)) ){

         # then $vm is a linked clone. 

         # Find $vm's base disks.         

$baseDisks = @()

         foreach ($d in $vm.Config.Hardware.Device) {

            $backing = $d.backing

            if ($backing -is [VMware.Vim.VirtualDeviceFileBackingInfo] -and $backing.parent -ne $null) {

               do {

                  $backing = $backing.parent

               } until ($backing.parent -eq $null)

               $baseDisks += $backing.fileName

 

            }

         }

 

         $linkedClone = new-object PSObject

         $linkedClone | add-member -type NoteProperty -Name Folder -Value $folder

         $linkedClone | add-member -type NoteProperty -Name VMName -Value $vm.name

         $linkedClone | add-member -type NoteProperty -Name BaseDisks -Value $baseDisks

         $linkedClones += $linkedClone

      }

      #else { do nothing for VMs that are not linked clones }    }

   $linkedClones | sort Folder, VMName, BaseDisks

}

foreach ($folder in Get-Folder -Location $folderroot){

Get-LinkedClone | Select Folder,VMName,@{N='BaseDisks';E={$_.BaseDisks -join '|'}} | Export-Csv -Path $filename -NoTypeInformation -UseCulture -Append

}

Write-Host "Report completed - see " $filename -ForegroundColor Yellow

Reply
0 Kudos
CPenn621
Contributor
Contributor
Jump to solution

This did not work for me, but was close enough to modify to make it work.  I did the following changes to part of the code....

Note - I had to add some special code to handle some situations.  VMWare can truncate disk naming to no longer match vm names.  My other case is if you renamed the VM after creation (also won't match).  That and vCenter appliance seems to always get found.  So I put in some special matches to knock these out and only show the true backing cases.

if ( ($unshared -ne $committed) -and (($ftInfo -eq $null) -or ($ftInfo.InstanceUuids.Length -le 1)) ){

# then $vm is a linked clone.

# Find $vm's base disks.

$baseDisks = @()
$backingfnd = 0

foreach ($d in $vm.Config.Hardware.Device) {

$backing = $d.backing

if ($backing -is [VMware.Vim.VirtualDeviceFileBackingInfo] -and $backing.parent -ne $null) {

$backingfnd = 1
do {

$backing = $backing.parent

} until ($backing.parent -eq $null)

$baseDisk = New-Object PSObject
$baseDisk | add-member -type NoteProperty -Name DiskName -Value $backing.fileName
$baseDisks += $baseDisk

}
}

If ($backingfnd = 1)
{
foreach ($bd in $baseDisks)
{
# knock outs - renamed VMs and names that don't match (vCenter)
$firstPart = $vm.Name.substring(0,4)
if (($bd.DiskName.Contains($vm.Name)) -or ($bd.DiskName.Contains("vCenter")) -or ($bd.DiskName.Contains($firstPart)))
{
# Do nothing
}
else
{
$linkedClone = new-object PSObject
$linkedClone | add-member -type NoteProperty -Name Folder -Value $folder
$linkedClone | add-member -type NoteProperty -Name VMName -Value $vm.name
$linkedClone | add-member -type NoteProperty -Name BaseDisks -Value $bd.DiskName
$linkedClones += $linkedClone

}
}
}


# $linkedClone = new-object PSObject

# $linkedClone | add-member -type NoteProperty -Name Folder -Value $folder

# $linkedClone | add-member -type NoteProperty -Name VMName -Value $vm.name

# $linkedClone | add-member -type NoteProperty -Name BaseDisks -Value $baseDisks

# $linkedClones += $linkedClone

}

#else { do nothing for VMs that are not linked clones } }

Reply
0 Kudos