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