The woes of too-small partition virtual disks
So far, so good.
It turns out there are two ways to create VMs. One is to install the OS from an ISO image, the other is to use a “VM template”. And the only way to gain hardware virtualization is to use a template. The templates come with already-built virtual disks. These virtual disks are small (4GB), and more space is intended to be added with additional virtual devices.
This is awkward, as it involves coordinating various hunks of virtual disk and keeping them together and in synch, as well as ferreting out all the necessary mount points so nothing overflows the small root filesystem.
Fortunately, I can use resize2fs
to “grow” a filesystem while keeping its contents. Unfortunately, the virtual drive doesn't have room to do so. Fortunately, I can make it bigger by just tacking more space on the end (dd
with the "seek" option can't really do it, so I have to make a sparse file with dd
then concatenate that onto the virtual disk file).
The virtual disk, however, is partitioned. And the partition labels don't describe the additional space. So I attack it with fdisk
and then parted
. I figure I can just move the swap partition (whose contents are ephemeral and don't matter) to the (new) end, and then expand the root partition. Unfortunately, parted
refuses to do this, as it performs the resize operation automatically with the partition expansion, and it complains that the filesystem contains options that are beyond its ability to resize (because Oracle runs SElinux).
So I download the source code to parted
, remove the filesystem resizing bits, recompile it, copy it to my VM server, and grow the partition, leaving the filesystem alone.
Now, how to grow the filesystem? The resize2fs
utility only works on block devices, not a chunk out of a file pretending to be a disk drive. A real partitioned drive actually appears as a set of block devices, but the fake one doesn't. Some research turns up the losetup
utility, which makes a file appear as a block device. Unfortunately, it doesn't support partitions. There's a version that does, if you unload the module and reload it with some options, but that's not the version that comes with OEL.
How about if I bring up the VM? That will make the virtual drive appear as hardware inside the VM, and the usual hardware partitioning support will let me see the partitions as block devices.
No joy, that's the root partition, and it won't let me resize the root file system while it's in use.
So I make another copy of the original small virtual disk, set it as the boot drive, and configure my modified one as an additional drive. Then I reboot, and can resize the filesystem. Shut down, make the new file into the boot drive, reboot, and I'm good to go.
I'm not the only person who's had this issue, the 'net is full of unhappy people fighting versions of it. The offered solutions consist of pulling numbers out of fdisk
or parted
, doing math on them, then abusing losetup
to mount part of a file at the calculated offset. The problems with this are the annoyance and danger of juggling lots of magical numbers, and the fact that losetup
will mount everything from the offset forward, not stopping at the end of the partition.
So I'm going to work from home today, and write a set of utilities to deal with this. They'll be fairly simple, without knowledge of filesystems and such. One will just read a file that contains a partitioned virtual disk, and break it up into individual files that can be operated on separately. Then another utility can assemble a bunch of files into a virtual disk and create the matching partition label.
I'll also make another utility that works like mkfile
, but grows existing files instead of creating new ones.
There are some finicky details like preserving virtual heads, cylinders, and sectors (which is silly, as modern drives aren't orthogonal and it's all fiction, but filesystem drivers and BIOS routines still care deeply about this obsolete arcana), but I can make the splitter emit a header with the old values, and have the file extender use that file to calculate a boundary that's an even number of these pretend cylinders, and the reassembler propagate that information into the new disk label it creates.
Fortunately (and perhaps frighteningly), I have experience writing disk formatters and partitioners.
EDIT: I wrote 'em, but can't do real testing with the 32-bit OEL here at home, so real testing will have to wait until tomorrow.