According to Microsoft's best practices for Hyper-V + Linux, the VHDX used for a Linux VM in Hyper-V should have a BlockSize of 1 MiB. However, packer is creating VHDX's with the default BlockSize of 32 MiB. From my own tests, I have confirmed that using the default 32 MiB setting significantly increases the real disk space usage of the dynamic VHDX. (I'm working on a test case to show the difference.)
Packer version: Packer v0.12.2
Host platform: Windows 10 Pro Insider Preview (build 14986.1001), 64 bit
To reproduce:
Create any Linux+Hyper-V base image. (Examples here if you need a template)
Examine the output VHDX in PowerShell:
PS C:\Users\Evan\AppData\Local\Temp\packerhv016796879> Get-VHD .\ubuntu-xenial.vhdx
ComputerName : XYZ
Path : c:\users\evan\appdata\local\temp\packerhv016796879\ubuntu-xenial.vhdx
VhdFormat : VHDX
VhdType : Dynamic
FileSize : 2654994432
Size : 22481469440
MinimumSize : 22480437760
LogicalSectorSize : 512
PhysicalSectorSize : 4096
BlockSize : 33554432
ParentPath :
DiskIdentifier : 78A0D4B6-155C-4621-B947-C6749807581B
FragmentationPercentage : 7
Alignment : 1
Attached : True
DiskNumber :
Number :
Notice that the BlockSize attribute is 33554432 bytes, or 32 MiB.
Compare to a VHDX created with the recommended BlockSize of 1 MiB:
PS C:\Users\Evan\AppData\Local\Temp\packerhv016796879> New-VHD -path ./test.vhdx -SizeBytes 10GB -dynamic -BlockSizeBytes 1MB
ComputerName : XYZ
Path : C:\Users\Evan\AppData\Local\Temp\packerhv016796879\test.vhdx
VhdFormat : VHDX
VhdType : Dynamic
FileSize : 4194304
Size : 10737418240
MinimumSize :
LogicalSectorSize : 512
PhysicalSectorSize : 4096
BlockSize : 1048576
ParentPath :
DiskIdentifier : 598D6DAC-8385-4FCE-84CE-D4D8CDDC25A0
FragmentationPercentage : 0
Alignment : 1
Attached : False
DiskNumber :
Number :
Debug log (only has up to the point where the VM has been booted, but that should be enough)
https://gist.github.com/evancox10/b0982f0c6f9c1b774d5d1bb19de3f2fd
Looking at packer/common/powershell/hyperv/hyperv.go , I see that in func CreateVirtualMachine packer uses the New-VM command to create both the VM and the VHDX in one command. Since New-VM does not support specifying the BlockSizeBytes, this would need to change to two commands:
New-VHD -dynamic -path $vhdPath -SizeBytes $newVHDSizeBytes -BlockSizeBytes 1MB
New-VM -Name $vmName -Path $path -MemoryStartupBytes $memoryStartupBytes -VHDPath $vhdPath -SwitchName $switchName -Generation $generation
(Note that both the Gen1 and Gen2 branch in this function need this change)
Alternatively, it could Virtual Hard Disk creation could be broken out into its own function.
If I have time this weekend, I will try compiling in this change. First have to set up Go and the dev environment.
After some more thought, maybe this should be exposed as a parameter for the user to choose. Doing the change I suggested above would mean that every Hyper-V VM created would get the 1MB BlockSize, which may not be desirable for Windows machines.
@evancox10 this looks like a good feature to add.
@taliesins I've (finally) got a dev environment for Windows packer up and running, and I'd like to give implementing this a shot. I'll be learning go as I go so it may take a week or two.
The parameter will just be called disk_block_size, that sound ok?
sounds good
Hey @taliesins @mwhooker , I've pushed my first attempt at fixing this. here's the branch in my repo: https://github.com/evancox10/packer/tree/hyper-v-fixes
Would one of y'all mind taking a look? Please let me know if there's anything you think I'm missing. (There's still a few comments I need to clean up.)
BTW I had about 240 files modified/added under ./vendor/ , not really sure what I'm supposed to do with these and whether to commit them or not. For now I left them alone and did not commit any anything.
Thanks,
Evan
Also, on my Ubuntu 16.04 test case, going from Block Size of 32 MiB to 1 MiB, the size of the VHDX went from 3.29 GiB to 1.64 GiB. That's a 50% reduction in size!
@taliesins just pinging y'all again on this. I'm not sure if what I did by making it a part of the CreateVM step is ok, or if it needs to be it's own step.
@evancox10 I have left feedback on your commit
Maybe make a pull request. Then I can comment here.
Any progress on this? I would love to have the ability to set this for my Linux VMs if it makes them 50% smaller :)
Hi @pvandervelde , I will put in the pull request ASAP! Sorry, I've been slammed at work.
Hi @evancox10 had a look at your code, looks really good. I would really like to see this in a future release of packer. I've merged your changes with my fork https://github.com/synax/packer/commit/f5b968a87265cb4602781f1c0afea2e904307478. Seems to work great! Can we create a pull request for this?
I took the liberty of creating a pull request for this. @evancox10 I've merged your changes to the current upstream master and implemented the changes required to make the merge happen. Thanks again for implementing this.
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
Hi @pvandervelde , I will put in the pull request ASAP! Sorry, I've been slammed at work.