How to find disk usage of a thin provisioned virtual disk?


I have a virtual machine having a thin provisioned virtual disk. The disk's allocated size is 8 GB but used size is around 2 GB.

I am interested in knowing is there a why of finding out the used size of disk programmatically like we can see in the

vSphere Client GUI's datastore browser. I have already tried to query the datastore using the "HostDatastoreBrowser" but

it also returns the size of disk as 8GB. Any ideas in this direction will be appreciated. Thanks.

0 Kudos
8 Replies
Community Manager
Community Manager

Take a look at this script -

Basically with vSphere 4 API, there is a new storageInfo property with a given VM storageInfo and it contains an array of the datastores in which a particular VM's VMDK are stored and provides attributes such as committed, uncommitted and shared.


William Lam

VMware vExpert 2009

VMware ESX/ESXi scripts and resources at:

Twitter: @lamw

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

0 Kudos

Hi William Lam

Thanks a lot of reply. Your reply was helpful but I was looking for more granular information i.e. down to each thin provisioned virtual disk

of the virtual machine. Right now we have the information at the virtual machine level only and not for individual disks.

0 Kudos
Community Manager
Community Manager

Unfortunately that information is not exposed at the VMDK level, if you had a single VMDK on a single datstore, then you can use the information exposed at the datastore level, but if you have multiple disks, then you won't be able to correlate.


William Lam

VMware vExpert 2009

VMware ESX/ESXi scripts and resources at:

Twitter: @lamw

VMware Code Central - Scripts/Sample code for Developers and Administrators

VMware Developer Community

If you find this information useful, please award points for "correct" or "helpful".

0 Kudos

Is this still true?  It's impossible to get thin provisioning info on a per virtual disk level?


0 Kudos
Community Manager
Community Manager

Yes I believe that is still true today, you don't get the actual "used" value when querying from the datastore and afaik, there is no property on a per VMDK that tells you how much has been consumed, part of this requires some guest data since you could be doing thin provisioned but if you created a file and then deleted it, the block has already been updated unless you have zeroed it out again which needs data feed back to vSphere ....

The best you can do is on a per VM basis or per Datastore basis on the amount of thin provisioning savings, check this script out for some details - http://communities.vmware.com/docs/DOC-10777

0 Kudos

there is a way now to find out about thin provisioned disks

Get-VM | select Name,VmHost,UsedSpaceGB,ProvisionedSpaceGb | Sort-Object {$_.name} | format-list

I am working on this and if someone would like to carry on it would be agreat help. I would like to go through my entire enterprise and group my vm's by hosts the only information I need is the information above.

I figure I will have to use var to store the above information then group it by host name and output it to a table.

Thanks hope some of my code helps.


0 Kudos

I've been playing around with this today and it is possible to identify how much space EACH virtual disk is consuming on the datastore when it is thin provisioned (regardless of how many virtual disks are on the same datastore).

I was able to achieve this using the datastore browser. Attached is a script that allows you to query a VM's virtual disk usage (for every disk it has).


./guest_disk_usage.pl --server <ESXi Host or vCenter Server> --username <username> --password <password> --guest <vm to query>


Hard disk 1 (scsi0:0) on 'RAID1 (0)(7)'

Provisioning: Thin

Total Size: 200.5 GB

Size On Datastore: 24.6 GB

Free Space: 175.9 GB

Hard disk 2 (scsi0:1) on 'RAID1 (0)(7)'

Provisioning: Thin

Total Size: 700.5 GB

Size On Datastore: 355.4 GB

Free Space: 345.1 GB

Hard disk 3 (scsi0:2) on 'RAID1 (0)(7)'

Provisioning: Thin

Total Size: 701.5 GB

Size On Datastore: 419.6 GB

Free Space: 281.9 GB

Hard disk 4 (scsi0:3) on 'RAID1 (1)(3)'

Provisioning: Thin

Total Size: 702.5 GB

Size On Datastore: 656.4 GB

Free Space: 46.1 GB

Here is the script:

#!/usr/bin/perl -w

# ------------------------------------------------------------------------------

# guest_disk_usage.pl

# Copyright (C) 2014  Troy Lea AKA Box293

# Original Author: Troy Lea <troy@box293.com> Twitter: @Box293

# See all my Nagios Projects on the Nagios Exchange:

#    http://exchange.nagios.org/directory/Owner/Box293/1


# This program is free software: you can redistribute it and/or modify it under

# the terms of the GNU General Public License as published by the Free Software

# Foundation, either version 3 of the License, or (at your option) any later

# version.


# This program is distributed in the hope that it will be useful, but

# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for

# more details.


# You should have received a copy of the GNU General Public License along with

# this program.  If not, see <http://www.gnu.org/licenses/>.


# Version 2014-01-30

use strict;

use VMware::VIRuntime;

# Define Options

my %opts = (

    guest => {

        type => '=s',

        help => 'The name of the virtual machine you want to generate disk usage information.',

        required => 1,

        }, # End 'guest' => {

    ); # End my %opts = (

# Read/Validate options and connect to the server


# Check and validate the options



# Connect to vCenter or ESX(i) Host


my $target_guest_view;

my $target_guest_option;

# Need to make sure the --guest argument has been provided

if (!Opts::option_is_set('guest')) {

    # The --guest argument was not provided, abort

    die "The --guest argument was not provided, aborting!\n";

    } # End if (!Opts::option_is_set('guest')) {

else {

    $target_guest_option = Opts::get_option('guest');

    $target_guest_view = Vim::find_entity_view (

        view_type => 'VirtualMachine',

        filter => {

            name => $target_guest_option


        ); # End $target_guest_view = Vim::find_entity_view (

    } # End else {

# Make sure we were able to find the guest

if (!$target_guest_view) {

    # Guest was not found, aborting

    die "Guest \'" . $target_guest_option . "\' not found\n";

    } # End if (!$target_guest_view) {

# Get the host this guest is currently running on

my $target_host_view = Vim::get_view (

    mo_ref => $target_guest_view->summary->runtime->host

    ); # End $target_host_view = Vim::get_view (

# Get all the virtual disks in the guest

my $guest_disks;

my $guest_controllers;

my $guest_disk_counter = 0;

# Loop through all the devices in the guest

foreach my $device (@{$target_guest_view->config->hardware->device}) {

    # Check for a VirtualDisk

    if (ref($device) eq 'VirtualDisk') {

        # Add this VirtualDisk to $guest_disks

        $guest_disks->{$guest_disk_counter} = $device;


        } # End if (ref($device) eq 'VirtualDisk') {


    # Check for a VirtualSCSIController

    if (ref($device)->isa('VirtualSCSIController')) {

        # Add this VirtualSCSIController to $guest_controllers

        $guest_controllers->{$device->key} = $device;

        } # End if (ref($device)->isa('VirtualSCSIController')) {


    # Check for a VirtualIDEController

    if (ref($device)->isa('VirtualIDEController')) {

        # Add this VirtualIDEController to $guest_controllers

        $guest_controllers->{$device->key} = $device;

        } # End if (ref($device)->isa('VirtualIDEController')) {

    } # End foreach my $device (@{$target_guest_view->config->hardware->device}) {

# Make sure the guest has virtual disks

if (defined($guest_disks)) {

    # Loop through all the virtual disks

    for (my $current_disk = 0; $current_disk < scalar(keys %$guest_disks); $current_disk++) {

        # Get the datastore this virtual disk resides on

        my $target_datastore_view = Vim::get_view (

            mo_ref => $guest_disks->{$current_disk}->backing->datastore

            ); # End $target_host_view = Vim::get_view (


        my $datastore_name = $target_datastore_view->summary->name;

        my $disk_name = $guest_disks->{$current_disk}->deviceInfo->label ;


        my $disk_id;

        my $controller_label = $guest_controllers->{$guest_disks->{$current_disk}->controllerKey}->deviceInfo->label;

        if ($controller_label =~ /^(SCSI)/) {

            $disk_id = "scsi" . $guest_controllers->{$guest_disks->{$current_disk}->controllerKey}->busNumber . ":" . $guest_disks->{$current_disk}->unitNumber;

            } # End if ($controller_label =~ /^(SCSI)/) {

        elsif ($controller_label =~ /^(IDE)/) {

            $disk_id = "ide" . $guest_controllers->{$guest_disks->{$current_disk}->controllerKey}->busNumber . ":" . $guest_disks->{$current_disk}->unitNumber;

            } # End elsif ($controller_label =~ /^(IDE)/) {


        my $disk_capacity = $guest_disks->{$current_disk}->capacityInKB / 1048576;


        my $disk_provision_type;

        my $disk_size_on_datastore;

        # Determine the thin provisioning type and disk size on datastore

        if ($guest_disks->{$current_disk}->backing->thinProvisioned) {

            $disk_provision_type = 'Thin';

            # Because it's a thin disk, get the size it is consuming on the datastore


            # Get the $current_disk_file_name

            my $current_disk_file_name = (split(/\//, $guest_disks->{$current_disk}->backing->fileName))[1];


            # Get the datastore browser

            my $target_datastore_browser = Vim::get_view(mo_ref => $target_datastore_view->browser);


            # Create the SearchSpec for browsing the datastore

            my $file_search_spec = HostDatastoreBrowserSearchSpec->new(

                details            =>    FileQueryFlags->new(

                    fileOwner        => 1,

                    fileSize        => 1,

                    fileType        => 1,

                    modification    => 1


                matchPattern    => [$current_disk_file_name]

                ); # End my $file_search_spec = HostDatastoreBrowserSearchSpec->new(


            # Perform the search of the datastore

            my $target_datastore_browser_results = $target_datastore_browser->SearchDatastoreSubFolders(

                datastorePath    =>    '[' . $datastore_name . ']',

                searchSpec        => $file_search_spec,

                ); # End my $target_datastore_browser_results = $target_datastore_browser->SearchDatastoreSubFolders(


            # Now loop through the search results to get the items we are after

            foreach my $datastore_item (@$target_datastore_browser_results) {

                foreach my $array_item (@{$datastore_item->file}) {

                    # Define $disk_size_on_datastore

                    $disk_size_on_datastore = sprintf("%.1f", $array_item->fileSize / 1073741824);

                    } # End foreach my $array_item (@{$datastore_item->file}) {

                } # End foreach my $datastore_item (@$target_datastore_browser_results) {

            } # End if ($device->backing->thinProvisioned) {

        elsif ($guest_disks->{$current_disk}->backing->eagerlyScrub) {

            $disk_provision_type = 'Thick (Eager)';

            # Define $disk_size_on_datastore (because it's thick it's the same as the capacity)

            $disk_size_on_datastore = $disk_capacity;

            } # End elsif ($device->backing->eagerlyScrub) {

        else {

            $disk_provision_type = 'Thick (Lazy)';

            # Define $disk_size_on_datastore (because it's thick it's the same as the capacity)

            $disk_size_on_datastore = $disk_capacity;

            } # End else {


        print "$disk_name ($disk_id) on \'$datastore_name\' \n";

        print "Provisioning: $disk_provision_type \n";

        print "Total Size: $disk_capacity GB \n";

        print "Size On Datastore: $disk_size_on_datastore GB \n";

        if ($disk_provision_type eq 'Thin') {

            # Get the remaining free space in the thin disk

            my $disk_space_remaining = $disk_capacity - $disk_size_on_datastore;

            print "Free Space: $disk_space_remaining GB \n";

            } # End if ($disk_provision_type eq 'Thin') {

        print "\n"

        } # End for (my $current_disk = 0; $current_disk < scalar(keys %$guest_disks); $current_disk++) {

    } # End if (defined($guest_disks)) {

else {

    # There are no virtual disks, abort

    die "This guest has NO virtual disks, aborting!";

    } # End else {

# Disconnect from the vCenter Server / ESX(i) Host




VCP3 & VCP4 32846 VSP4 VTSP4
0 Kudos

This doesn't work.   The fileSize and capacity of the vmdk file are always the same.

0 Kudos