While working on Automatic gadget asset updates snapd has learned to understand the volume and its structures defined in
gadget.yaml. As part of the gadget assets update, snapd can deploy structure on a disk, either by writing raw image data at a specific location or by manipulating the files and directories in a mounted filesystem.
It is a natural step to extend the functionality to and have a tool that can create Ubuntu Cure images from scratch, like
ubuntu-image does, but with fewer dependencies and as a part of snapd tools suite.
For the lack of better ideas, I have named the work-in-progress version of the tool
snap-image and it lives in the snapd tree under
Most of the support code has already landed, except for a single PR. Once it lands, I will be albe to start opening pull requests with the actual tool. For now, the tool is only available in my snapd fork https://github.com/bboozzoo/snapd/tree/bboozzoo/gadget-update-wip/cmd/snap-image. Feel free to clone the repo and built it yourself.
The name and subcommands are only proposals, although very much functional right now. I did not want to make this another
snap subcomand, because we already have a plenty of those, and the tool feels specialized enough to keep it standalone.
The tool has no library dependencies and can be used as a standalone binary. There are however dependencies on external tools:
The workflow is simple and is based on what we already have.
Step 1 is to prepare an image using
snap prepare-image command:
$ snap prepare-image pc-18.model $PWD/image-root-pc --channel edge
Step 2 is building the actual image:
$ snap-image prepare-volume $PWD/image-root-pc pc image written to: /tmp/snap-image-099515175/output.img
Volumes are built using
prepare-volume subcommand, like shown above. For the reference:
$ snap-image prepare-volume <prepared-image-dir> <volume-name>
Since I found working with
ubuntu-image output a bit frustrating, I have added a command to display the layout information. It is my believe that this makes the debugging & image building process better controlled. The subcommand is
$ snap-image position-volume <prepared-image-dir> <volume-name>
$ snap-image position-volume $HOME/work/canonical/image/image-root-pc pc volume: sector-size: 512 size: 499033088 # 974674 sectors (475 MB) schema: gpt structures: #0 ("mbr"): type: mbr size: 440 # 0 sectors + 440 bytes (unaligned) start-offset: 0 # 0 sectors effective-role: mbr content: - image: pc-boot.img size: 440 # 0 sectors + 440 bytes (unaligned) start-offset: 0 # 0 sectors #1 ("BIOS Boot"): type: DA,21686148-6449-6E6F-744E-656564454649 size: 1048576 # 2048 sectors (1 MB) start-offset: 1048576 # 2048 sectors effective-role: <none> content: - image: pc-core.img size: 182881 # 357 sectors + 97 bytes (unaligned) start-offset: 1048576 # 2048 sectors #2 ("EFI System"): type: EF,C12A7328-F81F-11D2-BA4B-00A0C93EC93B size: 52428800 # 102400 sectors (50 MB) start-offset: 2097152 # 4096 sectors effective-role: system-boot filesystem: vfat filesystem-label: system-boot #3 ("writable"): type: size: 444489728 # 868144 sectors (423 MB) start-offset: 54525952 # 106496 sectors effective-role: system-data filesystem: ext4 filesystem-label: writable
Compatibilty with ubuntu-image
The partition/structure layout code is compatible with layouts produced by
ubuntu-image and preserves its properties, such as assuming 512 byte block size and starting the first non MBR structure at 1MB offset by default.
A structure labeled
system-data role is automatically added to the volume. Its size is estimated using the same
du -s -B1 command followed by 1.5 * measured size + 8MB overhead. Because the staged filesystem is not mangled before calculating its size,
snap-image creates slightly larger
Compare the sfdisk dump output of images for:
- image created by
$ sfdisk --dump image-home/pc.img label: gpt label-id: 7E3F472C-BE32-4F7B-B937-852B59B9C143 device: image-home/pc.img unit: sectors first-lba: 34 last-lba: 943932 image-home/pc.img1 : start= 2048, size= 2048, type=21686148-6449-6E6F-744E-656564454649, uuid=CECCDF1F-5C15-4408-884D-E0A94180822A, name="BIOS Boot" image-home/pc.img2 : start= 4096, size= 102400, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=55191A67-A0BB-4E56-A27A-6D5CDCCA4B73, name="EFI System" image-home/pc.img3 : start= 106496, size= 837436, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=72E689BD-CD3C-4F00-95E8-2085DEB59EA3, name="writable"
- image created with
$ sfdisk --dump output.img label: gpt label-id: 9EED333F-088D-7A4D-883A-6B74A45D23BF device: output.img unit: sectors first-lba: 34 last-lba: 974640 output.img1 : start= 2048, size= 2048, type=21686148-6449-6E6F-744E-656564454649, uuid=91488627-5959-A248-9DA4-1B983193C5BF, name="BIOS Boot" output.img2 : start= 4096, size= 102400, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=D02309C4-3B07-2E4F-A119-7345916A05D0, name="EFI System" output.img3 : start= 106496, size= 868144, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=CAB2F72D-951B-7941-B78D-B147639C645F, name="writable"
- image created by
$ sfdisk --dump image-home/pi.img label: dos label-id: 0x73d36f65 device: image-home/pi.img unit: sectors image-home/pi.img1 : start= 2048, size= 262144, type=c, bootable image-home/pi.img2 : start= 264192, size= 739000, type=83
- image created with
$ sfdisk --dump output.img label: dos label-id: 0x918bf533 device: output.img unit: sectors output.img1 : start= 2048, size= 262144, type=c, bootable output.img2 : start= 264192, size= 768496, type=83
The subcommands are already implemented and usable as shown above.
At this point the tool was used to generate bootable images for the following models:
I have not attempted building any Core 16 images.
There is a known problem that
mkfs.ext4 shipped with Ubuntu 16.04 does not support
-d switch. Given that the tool is a standalone Go binary, we could deliver it as a
core18 snap and make the problem go away.