30

I have a 150 GB disk file (.vmdk, non pre-allocated) where my virtual machine is stored.

The file is currently 20 GB, but it is growing everyday, even though I'm not storing anything new in the guest file system.

I have been looking for hours for a way to reduce the maximum size of this disk, so that it never gets to 150 GB (I'd like to set the limit to 30 GB, and see what happens when the VM reaches this size).

What I have tried:

  • Converting the disk image with VMware Converter → this does not work, the tool only allows creating a full copy or a 'linked clone'.
  • Creating a new blank virtual machine of the desired size in order to copy the 20GB data onto the new .vmdk → I cannot find a way to perform the copy or even connect the new disk to my existing VM (so that I perform the copy using the guest OS).
  • Looking in the .vmx file to check if the maximum size was not set in plain text (it's not).

Although this task seems technically quite simple (there is no tricky shrinking involved, just a simple change of size limit), I'm really out of ideas here...

Is there a solution at all ?

1
  • 1
    Since the partitions on the virtual disk are most likely created to fill the advertised space, “tricky shrinking” is indeed involved.
    – Daniel B
    Apr 30, 2014 at 8:56

7 Answers 7

28
+25

The usual procedure for reducing the size of a .vmdk disk is to:

  1. Defragment the disk via the guest, choosing a defragmentation mode that consolidates empty space at the end of the disk. For a Windows guest, you should empty the Recycle Bin and turn off hibernation and paging, returning them after the defragmentation is done.

  2. Zero all unused space on the disk.
    For Windows use sdelete : sdelete -z to zero free space.
    For Linux : dd if=/dev/zero of=/mytempfile && rm -f /mytempfile.

  3. Shrink the disk (which may take quite a long time to complete).
    VMware Workstation : Menu VM / Manage / Clean up disks.
    Or use : vmware-vdiskmanager.exe -k [VMDK PATH].
    for ESX : vmkfstools --punchzero [VMDK PATH].

Converting the disk from growable to preallocated could stop its growing. This can be done using vmware-vdiskmanager with the -t parameter whose values are:

0 : single growable virtual disk
1 : growable virtual disk split in 2Gb files
2 : single preallocated virtual disk
3 : preallocated virtual disk split in 2Gb files

The following command will convert the .vmdk from growable to preallocated :

vmware-vdiskmanager -r current_disk_name.vmdk -t 3 new_disk_name.vmdk

If you wish to change the size of the disk, this should be done while the disk is still in growable format (examples here).

For more information see the Virtual Disk Manager User’s Guide.

12
  • 2
    This doesn’t reduce the internally advertised drive size, though.
    – Daniel B
    Apr 30, 2014 at 8:54
  • @DanielB: No, it doesn't reduce the maximal size, just the physical size. Reducing the maximal size can be dangerous, as some OS cannot boot without some free space on the system disk.
    – harrymc
    Apr 30, 2014 at 9:20
  • 4
    This is a useful technique I used to reduce the space occupied by the VMDK. However, this does not completely solve my problem, as if I want to keep the VMDK always under, let's say 30GB, I will have to periodically repeat the operation (which takes a long time indeed).
    – Sébastien
    May 1, 2014 at 11:49
  • If the disk can always be slimmed down to the wanted size, meaning that the procedure above always works to reduce the size, then you could limit the size in the future by converting the disk to fixed-size.
    – harrymc
    May 1, 2014 at 19:17
  • 1
    @harrymc Converting the disk to fixed size would suit my needs. I just did not find a way to do this with VMWare Workstation or Converter.
    – Sébastien
    May 4, 2014 at 21:26
6

The file is currently 20GB, but it is growing everyday, even though I'm not storing anything new in the guest file system.

Because the OS and its application programs temporarily use lots of disk space for temporary files, page files, hibernate file and config files. Once they get deleted depending on the policy of the OS new sectors on disk are used at the next time. The VM allocate storage for the virtual disk from real disk whenever a new sector is used in the virtual disk. As the sector on virtual disk are always not reused by guest OS the VM thinks its a disk usage and give space from real disk and this will lead to growing virtual disk image.

Your question title is less likely to be solved as using such a tool without inspection of image may lead to total disaster. But you can prevent growing of the image beyond 30GB. There are many way to achieve the goal.

A. Use only 30GB partitioned and leave remaining as free space. If you already partitioned more space then you need to shrink/delete it, the create a new partition then dump it with zeros and punch it as described by @harrymc . As the space in unpartitioned area is never used virtual disk will never grow beyond 30GB.

B. Create a snapshot and restore to it after usage. After creating snapshot VM store data into a new image file. If you restore to it, without saving or making new snapshots, all changed data is deleted and thus space is freed.

C. Create a new virtual disk of maximum 30GB, add it as a new disk into your current virtual machine, move all data to the new virtual disk using a backup tool. You may use a live Linux for the cloning.

Recommended option is A

4

The answer of @harrym is pretty good, but it actually does not answer the question. The OP wants to reduce the maximum size. The problem is the hypervisor does not know how much of the presented size (aka maximum size) is indeed used by the OS. The compaction (vmware-vdiskmakager -k) applies to a growable vmdk. It does nothing on preallocated one's.

So the steps to shrink the disk are:

  1. Resize the partition on disk via the OS, or via a suitable live CD
  2. Resize the vmdk device, carefully choosing the boundary not to cut any usable partition space. You can always leave some more space in the imnage than it is actually needed.

The first step involves a procedure from within the VM and varies with guest OS. The second step could be supported by the vmware commands but I haven't found a profound way of doing so. Thus the hacky approach.

Here is a non so quick (due to large data moving involved) and dirty solution that did the trick. We will need to have available space equal to the maximum device size.

WARNING: Remember to backup important data before any operation !!

  1. Find a way to resize the guest partition and leave unallocated space at the end of the device. Two examples:

    From the guest OS: windows 7

    1. You can use the online resizing capability. It's a good idea to first defragment the disk from within the quest OS.
    2. Run diskmgmt.msc, select the partition(volume) on the disk you want to resize, right click->Shrink volume. In the dialog that appears reduce the size as per your requirements. Note that since the partition is in use (if it is the system disk, or heavily fragmented) you might not be able to recover most of your free space. Provision to leave extra free space.
    3. Now we want to know the partitions ending disk sector (or byte). Assuming this is the only partition on the device, we take the size of the volume as displayed on my computer->select disk->right click->properties->Capacity: Note the number in bytes. (e.g. in my example 107371032576 for 99,9GB). Add some hundred megs for safety (+204800) (e.g. 107371237376). To be sure that we do not need to add anything missing, we can use the diskpart cmd line utility to find the partition's offset from the start of the device. run diskpart then: list disk, select disk id, list part, select part id, detail. Example:

    DISKPART> detail part

    Partition 1

    Offset in Bytes: 1048576

    Make sure you add at least this number to the disk size. Now we need convert the bytes to sectors dividing by 512 and rounding upwards (ceiling). E.g. 209709448. Note this number for step 3.

    Via a live cd: SystemResqueCD

    1. Alternatively you can use an resque cd, (SystemResqueCD is my proposal), download bootable ISO, mount it as a virtual cd rom device on you VM, boot from CD (by pressing Esc key on the VMWare boot screen, you might need to try some times as it appears very shortly). When reaching command prompt type: startx, this will hopefully bring you to graphical interface.
    2. Once on the systemresque's desktop, start gparted (e.g. from a terminal). Find the partition to be resized (this must be cleanly unmounted, if in doubt do a scandisk from the guest operating system). Do the resize, carefully planning your space needs.
    3. Again we need to find the ending offset in sectors (or bytes) of the partition. Open terminal and write parted [device], then unit s, print. E.g.

Number Start End Size Type File system Flags

1 2048s 113455103s 113453056s primary ntfs boot

Note the ending sector and add 1. E.g. 113455104. Note this number for step 3.

  1. As the hack works on single file preallocated (type 2) vmdks (haven't tried on multiple file types) we first convert the growable to preallocated. We will temporarily need a partition with physical space as the maximum size of the device. (e.g. 150GB).

    vmware-vdiskmanager.exe -r sourcevmdk -t 2 destvmdk

  2. Now the tricky part, for the preallocated disk there should be 2 vmdks

    disk.vmdk disk-flat.vmdk

    the former being only KB long, and the latter holding the data extends. Open the first (disk.vmdk) while VMWare workstation is off, whith a text editor (Notepad++ being my suggestion). Find the line

    RW 113455104 FLAT "Windows 7_x64-fl-flat.vmdk" 0

    Yes you get the point, the second field is the number of sectors allocated for the device. As a validation multiply by 512 and find the size in bytes, then divide by 1073741824(1024**3) to find size in GB. This should be the previous device's size.

    Now replace that number with the noted number from step one and save the file. WARNING: A mistake here and you could end up trimming actual data used on the filesystem. (But we resized the fs on the beginning of the device and made correct and safe calculations right? )

  3. Until now no data have been touched yet. Do this final step to actually trim the extends. We will use the rename functionality of vmware-vdiskmanager to recreate the vmdk with it's size now trimmed.

    vmware-vdiskmanager.exe -n destvmdk sourcevmdk

2

Why not simply set the size of the disk involved to 30GB from 150GB.

You'll have to set the sum of all partitions to be less than 30GB. You'll have to shrink the sizes of the partitions down as you go. There is a LOT of documentation on this site on how to shrink partitions down so I will not repeat this here AGAIN.

Why did you create a 150GB (thin partition) if you did not have the space to support it at maximum size? Seems like this is just asking for trouble.

3
  • 6
    I did not personally create the VM, this is why.
    – Sébastien
    Jun 29, 2013 at 13:34
  • How do I shrink the disk itself? I have the partitions within the disk shrink down but vdiskmanager.exe -k [VMDK PATH] as suggested in another reply doesn't shrink the drive. Jul 10, 2016 at 8:35
  • The problem which is not documented clearly, is how to resize a vmdk device (After resizing the partition of course). Also @mdpc i think your answer is not constructive. There are many occasions the you need to resize data on an existing vm, so there is no point of pointing the finger that the VM should be created correctly.
    – basos
    Feb 13, 2017 at 11:22
2

There is a roundabout way of using VMWare Converter to create a new VM and smaller VMDK size, then convert the original VMDK to the newly created, smaller VMDK.

Shrink VMDK

Detailed steps here.

Note that any changes to the VMDK size will also need a corresponding update to the partition table.

1
  • 2
    This is a VMWare Workstation VM, and these advanced copy options are not offered by Converter for this type of VM. It just won't let me change the size of the disk.
    – Sébastien
    Jun 29, 2013 at 13:33
2

This work only for sparse VMDK (NON-Pre-allocated) A defragmentation is required before shrinking to ensure that used space is contiguous

Defragmenting within Windows

In a Windows virtual machine, you must first run a disk defragment from within Windows. Defragmenting within Windows ensures that all of the used spaces are contiguous. You can then reduce the size of the virtual disk.

Shrinking the virtual disk

To shrink the virtual disk:

Open the VMware Tools Control Panel / Toolbox:

In Windows:

Double-click the VMware Tools icon in the system tray, or click Start >Control Panel > VMware Tools.

In Linux:

Open the terminal and run this command:

vmware-toolbox

Note: In Workstation 9.x (Windows) and above, shrinking is automatically done while Cleaning up the disk. Therefore, this option is removed from VMware Tools Panel. Go to VM > Manage > Clean up Disks. This is not available in Linux version of VMware Workstation 9.x and later.

Click the Shrink tab. Select the drive you want to shrink. Click Prepare to Shrink, then follow the onscreen instructions. Caution: Do not shut down your virtual machine or the host machine while the disk is shrinking. Also, do not try to cancel the process. Interrupting this process can cause irreparable damage to your virtual disk and you may not be able to start your virtual machine again.

From VMWare Knowledge Base

3
  • Reading existing answers first avoids duplicate answers.
    – harrymc
    May 4, 2014 at 18:23
  • 1
    Sorry, anyway I reposted it with the full procedure and the source. This may help him more May 4, 2014 at 19:02
  • Doesn't answer the op either. OP wants to shrink the maximum limit, not current size.
    – Ryuu
    Mar 18, 2019 at 2:11
0

For a vmware linux guest OS, run:

sudo vmware-toolbox-cmd disk shrinkonly

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .