xref: /cloud-hypervisor/docs/custom-image.md (revision 7d7bfb2034001d4cb15df2ddc56d2d350c8da30f)
1# How to create a custom Ubuntu image
2
3In the context of adding more utilities to the Ubuntu cloud image being used
4for integration testing, this quick guide details how to achieve the proper
5modification of an official Ubuntu cloud image.
6
7## Create the image
8
9Let's go through the steps on how to extend an official Ubuntu image. These
10steps can be applied to other distributions (with a few changes regarding
11package management).
12
13### Get latest Ubuntu cloud image
14
15```bash
16wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img
17```
18
19### Check the file format is QCOW2
20
21```bash
22file focal-server-cloudimg-amd64.img
23focal-server-cloudimg-amd64.img: QEMU QCOW2 Image (v2), 2361393152 bytes
24```
25
26### Convert QCOW2 into RAW
27
28```bash
29qemu-img convert -p -f qcow2 -O raw focal-server-cloudimg-amd64.img focal-server-cloudimg-amd64.raw
30```
31
32### Identify the Linux partition
33
34The goal is to mount the image rootfs so that it can be modified as needed.
35That's why we need to identify where the Linux filesystem partition is located
36in the image.
37
38```bash
39sudo fdisk -l focal-server-cloudimg-amd64.raw
40Disk focal-server-cloudimg-amd64.raw: 2.2 GiB, 2361393152 bytes, 4612096 sectors
41Units: sectors of 1 * 512 = 512 bytes
42Sector size (logical/physical): 512 bytes / 512 bytes
43I/O size (minimum/optimal): 512 bytes / 512 bytes
44Disklabel type: gpt
45Disk identifier: A1171ABA-2BEA-4218-A467-1B2B607E5953
46
47Device                             Start     End Sectors  Size Type
48focal-server-cloudimg-amd64.raw1  227328 4612062 4384735  2.1G Linux filesystem
49focal-server-cloudimg-amd64.raw14   2048   10239    8192    4M BIOS boot
50focal-server-cloudimg-amd64.raw15  10240  227327  217088  106M EFI System
51
52Partition table entries are not in disk order.
53```
54
55### Mount the Linux partition
56
57```bash
58mkdir -p /mnt
59sudo mount -o loop,offset=$((227328 * 512)) focal-server-cloudimg-amd64.raw /mnt
60```
61
62### Change root directory
63
64Changing the root directory will allow us to install new packages to the rootfs
65contained by the cloud image.
66
67```bash
68sudo chroot /mnt
69mount -t proc proc /proc
70mount -t devpts devpts /dev/pts
71```
72
73### Install needed packages
74
75In the context Cloud Hypervisor's integration tests, we need several utilities.
76Here is the way to install them for a Ubuntu image. This step is specific to
77Ubuntu distributions.
78
79```bash
80apt update
81apt install fio iperf iperf3 socat stress
82```
83
84### Remove counterproductive packages
85
86* snapd:
87
88This prevents snapd from trying to mount squashfs filesystem when the kernel
89might not support it. This might be the case when the image is used with direct
90kernel boot. This step is specific to Ubuntu distributions.
91
92* pollinate:
93
94Remove this package which can fail and lead to the SSH daemon failing to start.
95See #2113 for details.
96
97```bash
98apt remove --purge snapd pollinate
99```
100
101
102### Cleanup the image
103
104Leave no trace in the image before unmounting its content.
105
106```bash
107umount /dev/pts
108umount /proc
109history -c
110exit
111umount /mnt
112```
113
114### Rename the image
115
116Renaming is important to identify this is a modified image.
117
118```bash
119mv focal-server-cloudimg-amd64.raw focal-server-cloudimg-amd64-custom-$(date "+%Y%m%d")-0.raw
120```
121
122The `-0` is the revision and is only necessary to change if multiple images are
123updated on the same day.
124
125### Create QCOW2 from RAW
126
127Last step is to create the QCOW2 image back from the modified image.
128
129```bash
130qemu-img convert -p -f raw -O qcow2 focal-server-cloudimg-amd64-custom-$(date "+%Y%m%d")-0.raw focal-server-cloudimg-amd64-custom-$(date "+%Y%m%d")-0.qcow2
131```
132
133## Switch CI to use the new image
134
135### Upload to Azure storage
136
137The next step is to update both images (QCOW2 and RAW) stored as part of the
138Azure storage account, replacing them with the newly created ones. This will
139make these new images available from the integration tests. This is usually
140achieved through the web interface.
141
142### Update integration tests
143
144Last step is about updating the integration tests to work with this new image.
145The key point is to identify where the Linux filesystem partition is located,
146as we might need to update the direct kernel boot command line, replacing
147`/dev/vda1` with the appropriate partition number.
148
149Update all references to the previous image name to the new one.
150