1#!/bin/bash 2# Copyright (C) 2020-2022 Intel Corporation. 3# SPDX-License-Identifier: BSD-3-Clause 4 5build_dir="$PWD/build" 6cloud_image="${build_dir}/jammy-server-cloudimg-amd64.img" 7cloud_image_url=https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img 8hmi_vm_image="${build_dir}/hmi_vm.img" 9rt_vm_image="${build_dir}/rt_vm.img" 10rt_kernel=(linux-libc linux-headers linux-image) 11 12vm_type=$1 13if [[ ${vm_type} != "rt-vm" ]] && [[ ${vm_type} != "hmi-vm" ]]; then 14 cat <<EOT 15Usage: $0 <vm_type> 16This script creates VM images based on Ubuntu cloud images. 17 18VM type options: 19 hmi-vm create a VM with GNOME desktop 20 rt-vm create a VM with a preempt-RT-patched kernel and real-time test utilities 21EOT 22 exit 1 23fi 24 25######################################## 26# Environment checks 27######################################## 28 29if [[ ! -d /etc/schroot/chroot.d ]]; then 30 echo "Package schroot is not installed." 31 exit 1 32fi 33 34if [[ ! -d $(dirname $PWD)/build ]]; then 35 make -C $(dirname $PWD) 36fi 37 38arr=("$PWD/mnt" "$PWD/build") 39for dir in "${arr[@]}"; do 40 if [[ ! -d "$dir" ]]; then 41 mkdir $dir 42 fi 43done 44 45######################################## 46# Helper functions 47######################################## 48 49source logger.sh 50 51######################################## 52# Actions defined as functions 53######################################## 54 55function copy_rt_kernel() { 56 for file in ~/acrn-work/*rtvm*.deb 57 do 58 if [[ ${file} != *"dbg"* ]]; then 59 cp ${file} ${build_dir} 60 fi 61 done 62} 63 64function check_rt_kernel() { 65 for file in ${rt_kernel[@]} 66 do 67 ls ${build_dir}/*.deb | grep ${file} 68 if [ $? -eq 1 ]; then 69 echo "RT VM kernel package ${file} is not found." 70 exit 71 fi 72 done 73} 74 75function download_image() { 76 local dest=$1 77 local url=$2 78 79 if [[ -f ${dest} ]]; then 80 print_info "${dest} already exists. Do not redownload." 81 else 82 wget -O ${dest} ${url} 83 fi 84} 85 86function copy_and_enlarge_image() { 87 local source_image=$1 88 local dest_image=$2 89 local size_modifier=$3 90 91 if [[ -f ${dest_image} ]]; then 92 echo -n "${dest_image} already exists! Regenerate the image? (y/N)> " 93 read answer 94 if [[ $answer =~ ^[Yy]$ ]]; then 95 rm ${dest_image} 96 else 97 exit 1 98 fi 99 fi 100 101 qemu-img convert -f qcow2 -O raw ${source_image} ${dest_image} && \ 102 qemu-img resize -f raw ${dest_image} ${size_modifier} && \ 103 LANG=C growpart ${dest_image} 1 104} 105 106function dump_proxy() { 107 local temp_file=$(mktemp /tmp/proxy.XXXX) 108 109 sudo apt-config dump | grep -i proxy > ${temp_file} 2>&1 110 sudo mv ${temp_file} proxy.conf 111 112 echo "$(env | grep -Ei _proxy | sed -e 's/^/export /')" > bashrc 113} 114 115function resizing_guest_root() { 116 local part_file=$1 117 118 sudo e2fsck -f ${part_file} && \ 119 sudo resize2fs ${part_file} 120} 121 122function mount_filesystem() { 123 local part_file=$1 124 local mount_point=$2 125 126 # The symlink /etc/resolv.conf in a fresh cloud image is broken, which will 127 # prevent schroot from working. Touch that linked file to work it around. 128 mkdir -p ${mount_point} && \ 129 sudo mount ${part_file} ${mount_point} && \ 130 sudo mkdir -p ${mount_point}/run/systemd/resolve/ && \ 131 sudo touch ${mount_point}/run/systemd/resolve/stub-resolv.conf 132} 133 134function create_schroot_config() { 135 local mount_point=$1 136 local temp_file=$(mktemp /tmp/acrn-guest.XXXX) 137 138 cat << EOF > ${temp_file} 139[acrn-guest] 140description=Contains ACRN guest root file system. 141type=directory 142directory=${mount_point} 143users=root 144root-groups=root 145profile=desktop 146personality=linux 147preserve-environment=true 148EOF 149 150 sudo sed -ie "/passwd/d;/shadow/d;/group/d;/gshadow/d" \ 151 /etc/schroot/desktop/nssdatabases && \ 152 sudo mv ${temp_file} /etc/schroot/chroot.d/acrn-guest && \ 153 sudo chown root:root /etc/schroot/chroot.d/acrn-guest 154} 155 156function create_uio_config() { 157 local mount_point=$1 158 local temp_file=$(mktemp /tmp/rc.local.XXXX) 159 160 cat << EOF > ${temp_file} 161#!/bin/bash 162modprobe uio 163modprobe uio_pci_generic 164 165for i in {0..2} 166do 167bash -c 'echo "1af4 1110" > /sys/bus/pci/drivers/uio_pci_generic/new_id' 168if [ $? -eq 0 ]; then 169 echo "uio setting result" $? 170 break 171fi 172echo "uio setting result" $? "try again" 173sleep 1 174done 175EOF 176 177 sudo mv ${temp_file} $mount_point/etc/rc.local && \ 178 sudo chown root:root $mount_point/etc/rc.local && \ 179 sudo chmod 755 $mount_point/etc/rc.local 180} 181 182function setup_hmi_vm_rootfs() { 183 local mount_point=$1 184 185 sudo cp setup_hmi_vm.sh logger.sh ${mount_point}/ && \ 186 sudo cp $(dirname $PWD)/build/userApp $(dirname $PWD)/build/histapp.py ${mount_point}/root && \ 187 sudo cp proxy.conf ${mount_point}/etc/apt/apt.conf.d/proxy.conf && \ 188 sudo cp bashrc ${mount_point}/root/.bashrc && \ 189 sudo schroot -c acrn-guest bash /setup_hmi_vm.sh && \ 190 sudo rm ${mount_point}/setup_hmi_vm.sh ${mount_point}/logger.sh && \ 191 sudo rm bashrc proxy.conf 192} 193 194function setup_rt_vm_rootfs() { 195 local mount_point=$1 196 197 sudo mv ${build_dir}/*rtvm*.deb ${mount_point}/root && \ 198 sudo cp $(dirname $PWD)/build/rtApp ${mount_point}/root && \ 199 sudo mkdir ${mount_point}/root/scripts && \ 200 sudo cp proxy.conf ${mount_point}/etc/apt/apt.conf.d/proxy.conf && \ 201 sudo cp bashrc ${mount_point}/root/.bashrc && \ 202 sudo cp configRTcores.sh ${mount_point}/root/scripts/ && \ 203 sudo cp setup_rt_vm.sh logger.sh ${mount_point}/ && \ 204 sudo schroot -c acrn-guest bash /setup_rt_vm.sh && \ 205 sudo rm ${mount_point}/setup_rt_vm.sh ${mount_point}/logger.sh && \ 206 sudo rm bashrc proxy.conf 207} 208 209function cleanup() { 210 local mount_point=$1 211 local loop_dev=$2 212 213 sudo umount ${mount_point} 214 sudo rmdir ${mount_point} 215 sudo kpartx -vd /dev/${loop_dev} 216 sudo losetup -vd /dev/${loop_dev} 217 if [[ ${has_error} != 0 ]]; then 218 sudo rm ${target_image} 219 fi 220 true 221} 222 223######################################## 224# Do it! 225######################################## 226 227mount_point=$(pwd)/mnt 228if [[ ${vm_type} == "hmi-vm" ]]; then 229 target_image=${hmi_vm_image} 230 size_modifier="+7G" 231elif [[ ${vm_type} == "rt-vm" ]]; then 232 target_image=${rt_vm_image} 233 size_modifier="+1G" 234else 235 echo "Internal error: undefined VM type '${vm_type}'" 236 exit 1 237fi 238 239try_step "Download Ubuntu cloud image" download_image ${cloud_image} ${cloud_image_url} 240if [[ ${vm_type} == "rt-vm" ]]; then 241 try_step "Copy the RT kernel to build directory" copy_rt_kernel 242 try_step "Check availability of RT kernel image" check_rt_kernel 243fi 244try_step "Creating an enlarged copy of ${cloud_image}" copy_and_enlarge_image ${cloud_image} ${target_image} ${size_modifier} 245 246loop_dev=$(sudo kpartx -va ${target_image} 2>&1 | egrep -o -m 1 "loop[0-9]+") 247print_info "Guest image loop-mounted at /dev/${loop_dev}" 248 249try_step "Resizing guest root file system" resizing_guest_root /dev/mapper/${loop_dev}p1 250try_step "Mounting guest root file system at ${mount_point}" mount_filesystem /dev/mapper/${loop_dev}p1 ${mount_point} 251try_step "Preparing schroot configuration" create_schroot_config ${mount_point} 252try_step "Preparing uio configuration" create_uio_config ${mount_point} 253try_step "Extracting network proxy configurations" dump_proxy 254 255if [[ ${vm_type} == "hmi-vm" ]]; then 256 try_step "Initializing guest root file system for HMI VM" setup_hmi_vm_rootfs ${mount_point} 257else 258 try_step "Initializing guest root file system for RT VM" setup_rt_vm_rootfs ${mount_point} 259fi 260 261do_step "Cleaning up" cleanup ${mount_point} ${loop_dev} 262print_info "VM image created at ${target_image}." 263 264