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 cmd/snap-image
.
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.
Dependencies
The tool has no library dependencies and can be used as a standalone binary. There are however dependencies on external tools:
mkfs.ext4
mkfs.vfat
sfdisk
-
mtools
(specificallymcopy
)
Workflow
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
Commands
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 position-volume
:
$ snap-image position-volume <prepared-image-dir> <volume-name>
Example:
$ 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 writable
with 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 writable
structures.
Compare the sfdisk dump output of images for:
PC
- image created by
ubuntu-image
$ 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
snap-image
:
$ 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"
RPi3
- image created by
ubuntu-image
$ 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
snap-image
:
$ 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
Current status
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:
ubuntu-core-18-amd64
ubuntu-core-18-pi3
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.