Listing all linked clones on your vCenter Server

To list linked clones on your vCenter 4.0 Server, grouped (in most cases) by the base disks that they are sharing:

function Get-LinkedClone {
   #The following line is a fast replacement for:  $vms = get-vm args[0] | get-view
   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) {
      $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 $
         $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

Read the rest of this entry »

Tags: , ,

Improving the performance of Get-View, Get-VM, and Get-VMHost

If your PowerCLI script is slow and you are piping the output of Get-VM, Get-VMHost, Get-Datastore, or some other such Get-(vSphereManagedObject) cmdlet into Get-View, then you may be able to improve its performance dramatically with a few simple modifications. See an example of the below changes in practice.
Read the rest of this entry »


Creating many linked clones, a few at a time

Even if your ESX hosts can run a large number of VMs, they may not be able to power them all on simultaneously. Boot storming your virtual infrastructure can cause problems — among other things, if your VMs’ guest OS boots too slowly, errors can occur in the guest (e.g. Windows services can fail).

When creating linked clones, you can set cloneSpec.powerOn to true in order for linked clones to be powered on immediately upon creation, but if you issue too large a number of linked clone tasks at the same time using CloneVM_Task, you may experience such issues. You should therefore throttle the rapid creation of linked clones.

To limit the concurrency of linked clone creation, you can use CloneVM_Task to create a small batch of clones and then wait on those tasks to finish before continuing. You can use the wait-task cmdlet to wait until a set of tasks is complete. The following example creates 20 clones, 5 at a time, from the VM named “source_vm”. The linked clones are named “linked_clone_1” to “linked_clone_20”. You can write something similar if you are just interested in powering on existing VMs in batches.

$vm = Get-VM "source_vm" | Get-View
$clonePrefix = "linked_clone_"
$numClones = 20
$concurrentClones = 5

$cloneFolder = $vm.parent

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
$cloneSpec.Snapshot = $vm.Snapshot.CurrentSnapshot

$cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec
$cloneSpec.Location.DiskMoveType = [Vmware.Vim.VirtualMachineRelocateDiskMoveOptions]::createNewChildDiskBacking

#To power on each clone immediately after it is created:
#$cloneSpec.powerOn = $true

$i = 1
while ($i -le $numClones) {
   $taskViewArray = @()
   foreach ($j in 1..$concurrentClones) {
      $taskViewArray += $vm.CloneVM_Task( $cloneFolder, $clonePrefix+$i, $cloneSpec )
   $taskArray = $taskViewArray | Get-VIObjectByVIView
   Wait-Task $taskArray

Tags: , ,

Creating linked clones with the Virtualization EcoShell

Eric Sloof has adapted Hal Rottenberg’s linked clone script into a script action for the Virtualization EcoShell: Creating linked clones with the Virtualization EcoShell

Tags: , ,

Determining VM creation times from vCenter events

In order to get a sense of what VMs are the oldest, you can find the earliest event stored for each VM and use that as the “creation” time of the VM. Note that this is not a very reliable approach to determining the creation date of a VM, because vCenter events can expire. However, this can at least give you a time by which the VM was created (i.e. it might have been created on that date or earlier).

The following will provide a list of VMs sorted by their creation time.

function Get-VMCreationTimes {
   $vms = get-vm
   $vmevts = @()
   $vmevt = new-object PSObject
   foreach ($vm in $vms) {
      #Progress bar:
      $foundString = "       Found: "+$"   "+$vmevt.createdTime+"   "+$vmevt.IPAddress+"   "+$vmevt.createdBy
      $searchString = "Searching: "+$
      $percentComplete = $vmevts.count / $vms.count * 100
      write-progress -activity $foundString -status $searchString -percentcomplete $percentComplete

      $evt = get-vievent $vm | sort createdTime | select -first 1
      $vmevt = new-object PSObject
      $vmevt | add-member -type NoteProperty -Name createdTime -Value $evt.createdTime
      $vmevt | add-member -type NoteProperty -Name name -Value $
      $vmevt | add-member -type NoteProperty -Name IPAddress -Value $vm.Guest.IPAddress
      $vmevt | add-member -type NoteProperty -Name createdBy -Value $evt.UserName
      #uncomment the following lines to retrieve the datastore(s) that each VM is stored on
      #$datastore = get-datastore -VM $vm
      #$datastore = $vm.HardDisks[0].Filename | sed 's/\[\(.*\)\].*/\1/' #faster than get-datastore
      #$vmevt | add-member -type NoteProperty -Name Datastore -Value $datastore
      $vmevts += $vmevt
      #$vmevt #uncomment this to print out results line by line
   $vmevts | sort createdTime

This can be useful in identifying your oldest VMs. This will give output that looks like this:

createdTime                    name             IPAddress          createdBy
-----------                    ----             ---------          ---------
9/10/2009 10:21:05 PM          vm1              {}          Administrator
11/11/2009 6:00:22 PM          vm6              {}          user1
12/1/2009 5:26:39 PM           vm3              {}                 user2
1/8/2010 12:51:33 PM           vm10             {}          user1
...                            ...              ...                ...

For an alternative script that saves the creation time and user as custom fields on each VM (so it should be faster for repeated runs), see Alan Renouf’s script here:

Tags: ,

Finding items in your inventory by chaining get commands

getvmhost hostname | getvm             #list all VMs on a host
getvm vmname | getvmhost               #find the host that a VM is on
getvm vmname | getvmhost | % {$} #display just the name field from the above command
getcluster clustername | getvm         #list VMs in a cluster
getcluster | where {$_.DrsEnabled -and $_.HAEnabled } | getvm #list VMs in a DRS/HA cluster
getdatastore datastorename | getvm #list VMs registered in this vCenter that have a disk (vmdk or iso) on a given datastore*

*Thanks to correction by Sebastian.


Using the vSphere CloneVM API to create linked clones, clones from snapshots, and every other kind of clone

There are many options for cloning VMs that are not available through vSphere Client. The vSphere API CloneVM is available to users of vCenter Server and allows you to specify:

  • Whether the clone should be a fully-cloned VM or a linked clone (usually created very quickly, because it shares the disk of the source VM instead of copying it)
  • Whether to clone from a snapshot point (an earlier, saved state of the VM) or from the current state of the VM
  • Whether all the delta disks in the VM should be collapsed in into a single disk in the clone or should be copied as separate disks (if a VM has snapshots, and therefore a delta disk tree)
  • Whether the clone’s root/parent disk will be thick or thin provisioned (if creating a full clone)
  • Whether the clone should be powered on after being created
  • Whether the clone should be marked as a template
  • The folder, datastore, cluster, resource pool, and host where the clone should be created

For a non-PowerShell-based explanation, see the “Linked Virtual Machines” Technical Note from VMware.

The CloneVM API appears as a method of a VirtualMachine and takes three parameters:

$vm.CloneVM_Task( $cloneFolder, $cloneName, $cloneSpec )

Read the rest of this entry »

Tags: , ,

Finding a VM from its IP address, or listing all VM IP addresses

To find a VM with a specific IP address or prefix, you can use grep or the PowerShell “where” cmdlet:

GetVM | select name, {$_.Guest.IPAddress} | grep "1.2.3"
GetVM | where { $_.Guest.IPAddress -eq "" }

To list all VMs with their IP Addresses, sorted by VM Name or IP Address:

GetVM | select name, @{ Name = "IPAddress"; Expression = { $_.Guest.IPAddress }} | sort Name
GetVM | select name, @{ Name = "IPAddress"; Expression = { $_.Guest.IPAddress }} | sort IPAddress


Determining the ESX host version and build number with PowerCLI

To get a list of the version and build number of all ESX hosts on a vCenter Server from PowerShell, you can use the following two commands.

getview ViewType HostSystem -Property Name,Config.Product | select Name,{$_.Config.Product.FullName}
getview ViewType HostSystem -Property Name,Config.Product | foreach {$_.Name, $_.Config.Product}

The first command produces output like this:

Name                                 $_.Config.Product.FullName
----                                 --------------------------
host1                                VMware ESX 4.0.0 build-164009
host2                                VMware ESX 4.0.0 build-164009
...                                  ...

Read the rest of this entry »

Tags: ,

Creating a linked clone from a snapshot point in PowerCLI

The following PowerShell code uses VMware vSphere’s CloneVM API to create a linked clone from a source VM’s current snapshot point. The clone will be located on the same host, datastore, and folder as the source VM. It requires a snapshot to exist on the source VM, and it requires vCenter Server.

connect-viserver "vCenter_hostname"
$sourceVM = Get-VM "source_vm_name" | Get-View
$cloneName = "linked_clone_name"
$cloneFolder = $sourceVM.parent

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
$cloneSpec.Snapshot = $sourceVM.Snapshot.CurrentSnapshot

$cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec
$cloneSpec.Location.DiskMoveType = [Vmware.Vim.VirtualMachineRelocateDiskMoveOptions]::createNewChildDiskBacking

$sourceVM.CloneVM_Task( $cloneFolder, $cloneName, $cloneSpec )

-Keshav Attrey

Tags: , ,