13

I want turn a physical machine running MS Windows 7 into a VirtualBox virtual machine. This is easy, I have done this before, but this time I needed the virtual size/capacity of the disk to be a fixed and smaller size.

It needs to be fixed because I will install PGP disk encryption on it for compliance reasons. This will expand a dynamic disk to it maximum size.

Aside from this special case there are other reasons for wanting disks to be smaller and fixed. Is my experience. If you run for example a Jenkins build server on a dynamically expanding disk you could see the disk expanding quickly to its maximum size while in the guest OS disk space usage is stable and there is lots of free space.

Using Disk2vhd I have created a vhdx file. This file I converted to vdi format.

vboxmanage clonehd --format VDI MSWIN7.VHDX MSWIN7.vdi

Purportedly with vdi you could decrease virtual size/capacity with commands similar to

vboxmanage modifyhd MSWIN7.vdi --resize 160000

I found that this doesn't work. Even if you try variants you will consistently get error messages like:

Progress state: VBOX_E_NOT_SUPPORTED VBoxManage: error: Resize hard disk operation for this format is not implemented yet!

Below is the disk layout of my vdi disk. I added this to a Ubuntu VM to look at it using Gparted and CloneZilla. Capacity is around 300GB. Unallocated 145GB. Used is around 153GB.

I want to shrink capacity to around 160GB. This should be enough to fit /dev/sdb1 and /dev/sdb2.

BTW, I tried CloneZilla but it also does not seem to like to shrink the capacity to a smaller disk. I tried various settings in CloneZilla but no success.

How can I decrease virtual size/capacity?

enter image description here

onknows
  • 292
  • 1
  • 3
  • 14

6 Answers6

25
  1. Deallocate space at the end of disk in guest OS, where space >= size(source-disk) - size(new-disk). Typically by shrinking last partition.

  2. Turn off virtual machine.

  3. Create new Virtual Box disk with desired size.

  4. Move content from old disk to inside new disk:

     vboxmanage clonemedium disk "source-disk.vmdk" "new-disk.vmdk" --existing
    
  5. Turn on virtual machine.

  6. You may have to resize partition in guest OS to fill the rest of the disk depending of the space deallocated on step 1.

  • 2
    This is the really correct way to convert a dynamic vdi which create use a very large partition to a new vdi (maybe fixed size format for performance reason). I don't know why no one up this answer and prefer the dd way ... – zw963 Mar 26 '17 at 16:37
  • What do you mean by "deallocate space at the end of the disk"? Are you referring to shrinking the vdi file on the host, as of this question: https://superuser.com/questions/529149/how-to-compact-virtualboxs-vdi-file-size – mikezter Sep 08 '17 at 11:21
  • in guest OS, I've clarified the post – Andre Figueiredo Sep 08 '17 at 15:07
  • Perfect! Thank you very much! – Yamakuzure Feb 04 '20 at 17:07
  • 1
    Using `vboxmanage clonehd "source-disk.vdi" "new-disk.vdi" --existing` destroys the partition table on target image. – Mogens TrasherDK Mar 15 '20 at 15:35
  • @Mogens TrasherDK That isn't an issue at all!!! The target image is a new fresh image you just created for the sole purpose of having data replaced. You shouldn't do anything between 3 and 4 steps, and I believe VB doesn't even create a partition table on step 3 as well. – Andre Figueiredo Sep 16 '20 at 18:13
  • 1
    FYI `vboxmanage clonehd` is now `vboxmanage clonemedium disk` (`clonehd` is still accepted for backward compatibility). – Bill_Stewart Nov 29 '20 at 17:48
3

In the end I managed to solve this puzzle in a unexpected easy way using the preinstalled command line utility dd see Disk Cloning. As shown below I now have my 160GB drive in my guest OS stored in a 160GB fixed VirtualBox vdi file.

enter image description here

I solved it using following steps:

  1. Resize the disk using Disk Management in MS Windows to a size equal or better a little smaller than the size of the VDI.
  2. Add source vdi MSWIN7.vdi with MS Windows 7 to a Ubuntu VM as a second disk.
  3. Create a new fixed 160GB vdi and also add this to the Ubuntu VM. Now there are three disks: /dev/sda1 with the running Ubuntu VM, /dev/sdb2 with the source MSWIN7.vdi and /dev/sdc1 with the new vdi.
  4. Create the correct partitioning on /dev/sdc. CloneZilla did this for me. It did not copy data but it did create the partitioning I wanted. Of course you can do this manually.
  5. Copy sdb to sdc with dd command similar to sudo dd if=/dev/sdb of=/dev/sdc. The command ends with a no space left error message, that is expected. This I ignored because this is just unallocated space that it failed to copy.

I think it is possible to run the command for each partition. Maybe it is better and will not show an error message. sudo dd if=/dev/sdb1 of=/dev/sdc1 and sudo dd if=/dev/sdb2 of=/dev/sdc2.

vagrant@devops:~$ sudo dd if=/dev/sdb of=/dev/sdc
dd: writing to ‘/dev/sdc’: No space left on device
335544321+0 records in
335544320+0 records out
171798691840 bytes (172 GB) copied, 6360.3 s, 27.0 MB/s
onknows
  • 292
  • 1
  • 3
  • 14
3

In my case I had a windows VM with 50GB vdi to shrink to 20GB.

I have tried Andre Figueiredo solution but I had a problem with the cloned vdi.

When I apply Andre Figueiredo solution and attach the shrinked vdi to the VM, while booting, Virtualbox stops with I/O error.

Perhaps this is related to my btrfs filesystem (I heard btrfs causes problems with Vritualbox vdi).

My solution:

I tried a different solution in order to shrink the VM disk (vdi), named OVdi, (OVdi has disk size of 50GB, single ntfs partition with 40GB free space).

Let's follow these steps (this is my case, you can adapt/invent different vdi names):

  • stop the VM (poweroff)

  • create a new disk (vdi) with name DVdi of desired size (20GB my case..)

  • attach DVdi to the VM

  • boot VM and install the utility EaseUS Backup Free

  • Execute EasyUS and use the EasyUS Clone function (it clones OVdi MBR, and the ntfs partition of OVdi by shrinking to new disk DVdi)

  • Poweroff the VM

  • Detach OVdi from VM

  • Check if DVdi is the first boot device for the VM

  • reboot the VM

  • Have fun

Don't forget to delete the OVdi volume.

Following these steps I successfully reduced the VM disk size from 50GB to 20GB

2

I believe this solution is extremely dangerous! It relies upon all the files being in the first 153 GB of the original 300 GB partition. The dd command does not copy files. It simply copies ALL blocks in sequence. Thus, if you were unfortunate enough to have important files AFTER the 160 GB cutoff, dd will not know to copy them.

The typical solution I have seen in many, many posts is to power up the Windows VM and use some combination of defrag tools and administrative tools to consolidate all files to the front of the disk - the difficulty is that many defrag tools do not move unmovable Windows system files (I had to turn off System Recovery to delete a 7 GB unmovable chunk of disk), which are somewhere in the middle of the space you are trying to consolidate.

Once you have consolidated files to front of disk (MyDefrag is a freeware tool that provides a display of where on disk your files are), you must reduce the size of your Windows partition. I used the diskpart tool with the shrink option.

At this point, you can use dd to copy the now smaller partition to a new vdi.

I have also used vboxmanage modifymedium win10.vdi --compact, on my Linux host, but I first had to run sdelete.exe within the Windows system to zero out all the unused space first (sdelete -z c:). Using vboxmanage to compact the existing vdi file allows you to do everything in-place (but always have a backup).

  • 1
    What I forgot to mention is that I resized the partition in MS Windows first to right size. This guarantees that the files are in the 153GB part. MS WIndows will move the files/data. Note btw that MS Windows will not resize at times because files cannot be moved. – onknows Sep 02 '16 at 07:00
0

As others have mentioned, Andre Figueiredo's answer is luck based as there is no guarantee that the "first X gb" of space is your space, unless you defrag, in which case it's still risky.

Paul Hursky's answer is much safer. I will list some extra steps I did (note this is for Windows, mine was XP but it should also work for others) :

1) Get the free edition of "MiniTool Partition Wizard Free 12" in this link

2) Install it inside guest OS and resize your drive, leave some breathing room just to be safe (don't pull it all the way back ..). Since you are most likely resizing the current OS's hard drive, it will give you an option to restart and perform the action, do this.

3) Now using the same MiniTool Partition program, select your now unallocated space (under *: ) -> Right Click -> Wipe Partition -> Fill Sectors with Zero (Quick).

4) Now safely shutdown guest OS. Go to the VirtualBox folder where VBoxManage.exe exists, open cmd in this path and run this:

vboxmanage modifymedium C:\PATH_TO_YOUR_VDI\CHANGE_ME.vdi --compact

5) And now it should all magically work. When you next open the guest OS, it will run check disk, LET IT RUN, it finds "orphan files" which looked like system files.

goamn
  • 101
  • 1
  • I believe you are confusing my answer with onknows answer (which was the answer Paul also referring to), that also does not rely on luck. He emphasizes the need of allocating files to the beginning of the disk. Making sure that happens is actually the 1st step of my solution. Windows won't even let you decrease partition size if it can't move files from deallocating space. – Andre Figueiredo Sep 16 '20 at 18:03
0

I did the same as @goamn except I used the free version of NIUBI partition editor inside of my windows VM, which allowed me to shrink the C drive partition and then move the free space to the end. After that, you can right click on the empty partition and have 0's written over it. Once that's complete, run the compaction command and you're good to go.