Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to change disk size of a VM #17

Closed
fkorotkov opened this issue Apr 8, 2022 · 12 comments
Closed

Option to change disk size of a VM #17

fkorotkov opened this issue Apr 8, 2022 · 12 comments

Comments

@fkorotkov
Copy link
Contributor

Need to investigate and option to grew VM's disk size.

@edigaryev
Copy link
Collaborator

Just tried re-sizing the disk.bin image on the host using qemu-img resize and it seems that the primary issue here will be that the partition (with the primary APFS container) that we want to resize is surrounded by a recovery partition:

% gdisk disk.bin  
GPT fdisk (gdisk) version 1.0.8

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): p
Disk disk.bin: 67108864 sectors, 32.0 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): E9264220-02DE-4C85-8A94-0B8AD958F8F0
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 67108830
Partitions will be aligned on 8-sector boundaries
Total free space is 13 sectors (6.5 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              40         1024039   500.0 MiB   FFFF  iBootSystemContainer
   2         1024040        56623143   26.5 GiB    AF0A  Container
   3        56623144        67108823   5.0 GiB     FFFF  RecoveryOSContainer

It's possible to create a second APFS container, but it doesn't seem to be possible to "link" these two together, so that the primary APFS container would re-use free space of the secondary APFS container.

@edigaryev
Copy link
Collaborator

Just to illustrate better, here's a partition table of a disk above, but:

  • qemu-img resize disk.bin +32G
  • GPT backup data structures relocated to the end of the disk (using gdisk's expert command)
  • new partition created that uses the rest of the resized disk
Disk disk.bin: 134217728 sectors, 64.0 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): E9264220-02DE-4C85-8A94-0B8AD958F8F0
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 134217694
Partitions will be aligned on 8-sector boundaries
Total free space is 6 sectors (3.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              40         1024039   500.0 MiB   FFFF  iBootSystemContainer
   2         1024040        56623143   26.5 GiB    AF0A  Container
   3        56623144        67108823   5.0 GiB     FFFF  RecoveryOSContainer
   4        67108824       134217694   32.0 GiB    AF0A  Apple APFS

The RecoveryOSContainer (partition number 3) doesn't allow us to easily resize the partition Container (partition number 2), so we have to create a separate partition (partition number 4) and this will be a separate APFS container too.

@edigaryev
Copy link
Collaborator

Funnily enough, the VM seems to boot just fine with the RecoveryOSContainer partition removed, and finally shows the rest of the space as "Free space", giving the ability to resize the RecoveryOSContainer partition in Disk Utility tool.

The question now is how to automate this.

@edigaryev
Copy link
Collaborator

edigaryev commented Apr 8, 2022

The question now is how to automate this.

diskutil apfs resizeContainer works, but I'm not sure how we're going to call this form Tart. Meaning that we would need to integrate a SSH client into Tart and require SSH credentials in our VM manifests, otherwise we wouldn't know how to interact with the VM.

Also we'll need to implement gdisk's GPT functionality in Tart somehow.

@fkorotkov
Copy link
Contributor Author

Ended up with implementing the disk growing functionality in the Packer plugin. See cirruslabs/packer-plugin-tart#2

@fkorotkov
Copy link
Contributor Author

Closing in favor of the Packer plugin option. One should automate creation of VMs.

@qbx2
Copy link

qbx2 commented Feb 22, 2023

I don't think tart is for only packer, then it should be very helpful if FAQ introduces how to do this using cli. I went through the source code and github to do it.
My answer:

$ truncate ~/.tart/vms/my-vm/disk.img -s 100g

[... tart run and ssh in to vm]

$ diskutil repairDisk disk0

$ diskutil apfs resizeContainer disk0s2 0

$ df -h ~

@iby
Copy link

iby commented Jul 3, 2024

@qbx2 thanks for that info! 🙏 A couple of small remarks for future generations:

Doing this in macOS host:

# Complains in Sonoma 14.5 and prints out command help:
# truncate ~/.tart/vms/my-vm/disk.img -s 100g

# This works:
truncate -s 100g ~/.tart/vms/my-vm/disk.img

Doing this inside macOS VM:

# Not sure if this is macOS 15 Sequoia (Beta 2) (vanilla image) or something else,
# but there's no disk0 for some reason – using disk1 worked perfectly.

# To see all partitions – we want the first one (internal, physical).
diskutil list

diskutil repairDisk disk1
diskutil apfs resizeContainer disk1s2 0
df -h ~

@myxal
Copy link

myxal commented Aug 28, 2024

Hello, I'm somewhat new to tart and also have a few remarks:

  • When using truncate, make sure you're growing the disk - otherwise you WILL lose data, and truncate will not warn you, it's not targeted at disks/images. There's hdiutil resize -imageonly ... which I'd suggest using in a script.
  • The procedure posted by @qbx2 only works if you delete the recovery partition from the VM disk. The disk0s2 refers to the "user" (OS + data) APFS container (the partition on the "physical" disk, as opposed to the APFS container synthesised disk), which is normally sandwiched between the iSCPreboot container and the Recovery container, as is common on Apple-Silicon Macs' internal disks (https://eclecticlight.co/wp-content/uploads/2021/12/bootdiskstructurem1monty.png)
  • If you wish to preserve the recovery partition, dd-copy and a bit of legwork with Rod Smith's gdisk (or a lot of legwork with the builtin gpt) can do that:
$ hdiutil attach -nomount  -readonly ~/.tart/vms/my-vm/disk.img 
...
/dev/disk4s3        	Apple_APFS_Recovery
$ sudo dd if=/dev/disk4s3 bs=2m of=~/.tart/vms/my-vm/recovery.raw
$ diskutil eject disk4
$ hdiutil attach -nomount ~/.tart/vms/my-vm/disk.img 
$ sudo gdisk /dev/disk4
> p (disk details and basic info about partitions)
> i 3 (details about 3rd partition)
> d 3 (delete 3rd partition)
> n... (create partition; number: 3, first sector: last usable on disk minus partition size in previous step, last sector: default, GUID: copy from previous step, 5263...)
> c 3 (change name what was in p output)
> x (expert's menu)
> c 3 (change partition unique GUID to what it was in p-step)
> w (write changes and exit)
$ sudo dd of=/dev/disk4s3 bs=2m if=~/.tart/vms/my-vm/recovery.raw

At this point I thought that I could even run the resizeContainer command from the host, but apparently VMs' Data volume is somehow encrypted ("Encrypted at rest") - I suppose there's no workaround, to acquire the unlock passphrase from within host OS?

@simonbs
Copy link
Contributor

simonbs commented Nov 7, 2024

The following steps worked for me on macOS Ventura 14.5.

From the host machine

  1. Run truncate -s 150g ~/.tart/vms/my-vm/disk.img to increase the disk size to 150 GB. Replace 150 with the size you'd like to resize to. Truncating to a smaller image size may cause data loss.
  2. Run the virtual machine with tart run my-vm.
  3. Obtain the IP address of the virtual machine with tart ip my-vm.
  4. SSH into the virtual machine with ssh runner@{IP_ADDRESS}.
  5. Run diskutil repairDisk disk0 on the virtual machine.
  6. Shut down the virtual machine.
  7. Run the virtual machine in recovery mode with tart run my-vm —-recovery.

In the virtual machine running in recovery mode

  1. Open the Terminal app.
  2. Run diskutil list to identify the identifier of the volume named Apple_APFS_Recovery. We'll assume the identifier is disk0s3.
  3. Erase the recovery volume with diskutil eraseVolume free free disk0s3.
  4. Resize the primary APFS container with diskutil apfs resizeContainer disk0s2 0.
  5. Shut down the virtual machine.

The disk space has now been increased.

@james-rant
Copy link

Be very wary following these steps to resize the VM container. I followed the steps and successfully resized the VM's disk space, but after doing so, I am now unable to update the OS on that VM. When I try I get an error from macOS saying "Unable to personalise the update" and it fails. And then when I tried from the command line, I noticed the actual error:

Failed to find SFR recovery volume

So while this will enable you to increase the disk space, it results in being unable to update the OS.

Is it possible to reinstate the recovery volume? Or will I have to create a new VM?

@iby
Copy link

iby commented Feb 7, 2025

@james-rant unless you've installed macOS from ISPW, the recovery volume would be removed from the start, see #889 (comment). So, this is probably unrelated to resizing the disk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants