191fe48d5SPhilipp Schuster#!/usr/bin/env bash 2bbefbe92SMuminul Islam: ' 3bbefbe92SMuminul Islam This script checks if an image is compatible with Cloud Hypervisor. 4bbefbe92SMuminul Islam At first, it detects the image type(raw or qcow2), 5bbefbe92SMuminul Islam partition type whether it is DOS or GPT. 6bbefbe92SMuminul Islam Then it mounts the image and checks if VIRTIO Configs 7bbefbe92SMuminul Islam are enabled in the kernel config. In the end, it provides 8bbefbe92SMuminul Islam a message about the compatibility of the image. 9bbefbe92SMuminul Islam' 10bbefbe92SMuminul Islam 11bbefbe92SMuminul Islamusage="$(basename "$0") [-h] -f -w -- program to check Cloud Hypervisor compatible image 12bbefbe92SMuminul Islam 13bbefbe92SMuminul Islamwhere: 14bbefbe92SMuminul Islam -h show this help text 15bbefbe92SMuminul Islam -f image file location 16bbefbe92SMuminul Islam -w directory to be used for temporary files" 17bbefbe92SMuminul Islam 18bbefbe92SMuminul Islamfunction check_command { 19*2b2d0065SRuslan Mstoi if ! command -v "$1" &>/dev/null; then 20bbefbe92SMuminul Islam echo "Command $1 could not be found" 21bbefbe92SMuminul Islam exit 1 22bbefbe92SMuminul Islam fi 23318caeb9SRuslan Mstoi} 24bbefbe92SMuminul Islam 25bbefbe92SMuminul Islamfunction check_if_root { 26bbefbe92SMuminul Islam if [ "$EUID" -ne 0 ]; then 27bbefbe92SMuminul Islam echo "Please run as root" 28bbefbe92SMuminul Islam exit 1 29bbefbe92SMuminul Islam fi 30bbefbe92SMuminul Islam 31318caeb9SRuslan Mstoi} 32bbefbe92SMuminul Islam 33bbefbe92SMuminul Islamcheck_if_root 34bbefbe92SMuminul Islamworking_dir="" 35bbefbe92SMuminul Islamwhile getopts ':hf:w:' option; do 36bbefbe92SMuminul Islam case "$option" in 37318caeb9SRuslan Mstoi h) 38318caeb9SRuslan Mstoi echo "$usage" 39bbefbe92SMuminul Islam exit 40bbefbe92SMuminul Islam ;; 41318caeb9SRuslan Mstoi f) 42318caeb9SRuslan Mstoi file_name=$OPTARG 43bbefbe92SMuminul Islam ;; 44318caeb9SRuslan Mstoi w) 45318caeb9SRuslan Mstoi working_dir=$OPTARG 46bbefbe92SMuminul Islam ;; 47318caeb9SRuslan Mstoi :) 48318caeb9SRuslan Mstoi printf "missing argument for -%s\n" "$OPTARG" >&2 49bbefbe92SMuminul Islam echo "$usage" >&2 50bbefbe92SMuminul Islam exit 1 51bbefbe92SMuminul Islam ;; 52318caeb9SRuslan Mstoi \?) 53318caeb9SRuslan Mstoi printf "illegal option: -%s\n" "$OPTARG" >&2 54bbefbe92SMuminul Islam echo "$usage" >&2 55bbefbe92SMuminul Islam exit 1 56bbefbe92SMuminul Islam ;; 57bbefbe92SMuminul Islam esac 58bbefbe92SMuminul Islamdone 59bbefbe92SMuminul Islam 60bbefbe92SMuminul Islamshift $((OPTIND - 1)) 61bbefbe92SMuminul Islam 62bbefbe92SMuminul Islamif [ -z "${file_name}" ]; then 63bbefbe92SMuminul Islam echo "You must provide the image file name" 64bbefbe92SMuminul Islam exit 1 65bbefbe92SMuminul Islamfi 66bbefbe92SMuminul Islamif [[ ! -f ${file_name} ]]; then 67bbefbe92SMuminul Islam echo "File ${file_name} does not exist" 68bbefbe92SMuminul Islam exit 1 69bbefbe92SMuminul Islamfi 70bbefbe92SMuminul Islam 71*2b2d0065SRuslan Mstoifile_abs_path=$(readlink -m "${file_name}") 72bbefbe92SMuminul Islamif [[ "${working_dir}" != "" && ! -d "${working_dir}" ]]; then 73bbefbe92SMuminul Islam echo "Directory ${working_dir} does not exist" 74bbefbe92SMuminul Islam exit 1 75bbefbe92SMuminul Islamelif [[ "${working_dir}" == "" ]]; then 76318caeb9SRuslan Mstoi working_dir=$(mktemp -d) 77bbefbe92SMuminul Islam tmp_created=1 78bbefbe92SMuminul Islamelse 79*2b2d0065SRuslan Mstoi working_dir=$(readlink -m "${working_dir}") 80bbefbe92SMuminul Islamfi 81bbefbe92SMuminul Islam 82bbefbe92SMuminul Islamfilename="${file_name%.*}" 83bbefbe92SMuminul Islamdest_file=${working_dir}/${filename}.raw 84*2b2d0065SRuslan Mstoiimage_type=$(qemu-img info "${file_abs_path}" | grep 'file format:' | awk '{ print $3 }') 85bbefbe92SMuminul Islamecho "Image type detected as ${image_type}" 86bbefbe92SMuminul Islam 87bbefbe92SMuminul Islamif [[ "${image_type}" == "raw" ]]; then 88bbefbe92SMuminul Islam dest_file=${file_abs_path} 89bbefbe92SMuminul Islamelif [[ "$image_type" == "qcow2" ]]; then 90bbefbe92SMuminul Islam if lsmod | grep "nbd" &>/dev/null; then 91bbefbe92SMuminul Islam echo "Module nbd is loaded!" 92bbefbe92SMuminul Islam else 93bbefbe92SMuminul Islam echo "Module nbd is not loaded. Trying to load the module" 94*2b2d0065SRuslan Mstoi 95*2b2d0065SRuslan Mstoi if ! modprobe nbd max_part=8; then 96bbefbe92SMuminul Islam echo "failed to load nbd module. Exiting" 97bbefbe92SMuminul Islam exit 1 98bbefbe92SMuminul Islam fi 99bbefbe92SMuminul Islam fi 100bbefbe92SMuminul Islam check_command qemu-img 101bbefbe92SMuminul Islam dest_file=/dev/nbd0 102*2b2d0065SRuslan Mstoi qemu-nbd --connect=${dest_file} "${file_abs_path}" --read-only 103bbefbe92SMuminul Islamfi 104bbefbe92SMuminul Islam 105bbefbe92SMuminul Islamcheck_command blkid 106bbefbe92SMuminul Islam#get part info 107*2b2d0065SRuslan Mstoipart_type=$(blkid -o value -s PTTYPE "${dest_file}") 108bbefbe92SMuminul Islam 109bbefbe92SMuminul Islamcheck_command partx 110*2b2d0065SRuslan Mstoinr_partitions=$(partx -g "${dest_file}" | wc -l) 111bbefbe92SMuminul Islam 112bbefbe92SMuminul Islamcheck_command fdisk 113*2b2d0065SRuslan Mstoiout=$(fdisk -l "${dest_file}" --bytes | grep -i -A "${nr_partitions}" 'Device' | tail -n +2) 114bbefbe92SMuminul Islam 115bbefbe92SMuminul IslamIFS=' 116bbefbe92SMuminul Islam' 117bbefbe92SMuminul Islami=0 11882cac6f6SRuslan Mstoideclare -A lines 119bbefbe92SMuminul Islamfor x in $out; do 120bbefbe92SMuminul Islam lines[$i]=$x 121bbefbe92SMuminul Islam i=$((i + 1)) 122bbefbe92SMuminul Islamdone 123bbefbe92SMuminul Islam 124bbefbe92SMuminul Islamdeclare -A partitions 125bbefbe92SMuminul IslamIFS=' ' 126bbefbe92SMuminul Islami=0 127bbefbe92SMuminul IslamROWS=${#lines[@]} 128bbefbe92SMuminul Islam 129318caeb9SRuslan Mstoifor line in "${lines[@]}"; do 130bbefbe92SMuminul Islam j=0 131*2b2d0065SRuslan Mstoi read -a -r str_arr <<<"$line" 132318caeb9SRuslan Mstoi for val in "${str_arr[@]}"; do 133bbefbe92SMuminul Islam if [[ "$val" != "*" ]]; then 134bbefbe92SMuminul Islam partitions[$i, $j]=$val 135bbefbe92SMuminul Islam j=$((j + 1)) 136bbefbe92SMuminul Islam fi 137bbefbe92SMuminul Islam done 138bbefbe92SMuminul Islam i=$((i + 1)) 139bbefbe92SMuminul Islamdone 140bbefbe92SMuminul Islam 141bbefbe92SMuminul IslamCOLUMNS=$j 142bbefbe92SMuminul IslamSTART_ADDRESS_INDEX=1 143bbefbe92SMuminul IslamFILE_SYS_INDEX2=$((COLUMNS - 1)) 144bbefbe92SMuminul IslamFILE_SYS_INDEX1=$((COLUMNS - 2)) 145bbefbe92SMuminul IslamDEVICE_INDEX=0 146bbefbe92SMuminul Islam# Here we have all the partition info now lets mount and analyze the contents 147318caeb9SRuslan Mstoifor ((i = 0; i < ROWS; i++)); do 148bbefbe92SMuminul Islam if [[ "$part_type" == "gpt" && "${partitions[$i, ${FILE_SYS_INDEX1}]}" == "Linux" && "${partitions[$i, ${FILE_SYS_INDEX2}]}" == "filesystem" ]]; then 149bbefbe92SMuminul Islam echo "The image has GPT partitions" 150bbefbe92SMuminul Islam MOUNT_ROW=$i 151bbefbe92SMuminul Islam break 152bbefbe92SMuminul Islam elif [[ "$part_type" == "dos" && "${partitions[$i, ${FILE_SYS_INDEX1}]}" == "Linux" && "${partitions[$i, ${FILE_SYS_INDEX2}]}" == "" ]]; then 153bbefbe92SMuminul Islam echo "The image has DOS partitions" 154bbefbe92SMuminul Islam MOUNT_ROW=$i 155bbefbe92SMuminul Islam break 156bbefbe92SMuminul Islam fi 157bbefbe92SMuminul Islamdone 158bbefbe92SMuminul Islam 159bbefbe92SMuminul Islamstart_address=${partitions[${MOUNT_ROW}, ${START_ADDRESS_INDEX}]} 160bbefbe92SMuminul Islamoffset=$((start_address * 512)) 161bbefbe92SMuminul Islam 162bbefbe92SMuminul IslamMOUNT_DIR=/mnt/clh-img-check/ 163bbefbe92SMuminul Islamrm -rf ${MOUNT_DIR} 164bbefbe92SMuminul Islammkdir ${MOUNT_DIR} 165bbefbe92SMuminul Islamif [[ "${image_type}" == "raw" ]]; then 166*2b2d0065SRuslan Mstoi mount -o ro,loop,offset=$offset "${dest_file}" ${MOUNT_DIR} 167bbefbe92SMuminul Islamelif [[ "${image_type}" == "qcow2" ]]; then 168*2b2d0065SRuslan Mstoi mount -o ro "${partitions[${MOUNT_ROW}, ${DEVICE_INDEX}]}" ${MOUNT_DIR} 169bbefbe92SMuminul Islamfi 170bbefbe92SMuminul Islam 171bbefbe92SMuminul IslamCONFIG_DIR=${MOUNT_DIR}boot/ 172bbefbe92SMuminul Islamif [[ "$part_type" == "dos" ]]; then 173bbefbe92SMuminul Islam CONFIG_DIR=${MOUNT_DIR} 174bbefbe92SMuminul Islamfi 175bbefbe92SMuminul Islam 176bbefbe92SMuminul Islam#check VIRTIO 177bbefbe92SMuminul IslamHAS_VIRTIO=1 178*2b2d0065SRuslan Mstoifor conf_file in "${CONFIG_DIR}"config*; do 179*2b2d0065SRuslan Mstoi out=$(grep -cE "CONFIG_VIRTIO=y|CONFIG_VIRTIO_BLK=y|CONFIG_VIRTIO_BLK=m" "${conf_file}") 180bbefbe92SMuminul Islam if [[ "$out" != "2" ]]; then 181bbefbe92SMuminul Islam echo "VIRTIO not found" 182bbefbe92SMuminul Islam HAS_VIRTIO=0 183bbefbe92SMuminul Islam fi 184bbefbe92SMuminul Islamdone 185bbefbe92SMuminul Islam 186bbefbe92SMuminul Islam#clean up 187bbefbe92SMuminul Islamumount ${MOUNT_DIR} 188bbefbe92SMuminul Islam 189bbefbe92SMuminul Islamif [[ "${tmp_created}" == "1" ]]; then 190*2b2d0065SRuslan Mstoi rm -rf "${working_dir}" 191bbefbe92SMuminul Islamfi 192bbefbe92SMuminul Islam 193bbefbe92SMuminul Islamif [[ "${image_type}" == "qcow2" ]]; then 194*2b2d0065SRuslan Mstoi qemu-nbd --disconnect "${dest_file}" >/dev/null 195bbefbe92SMuminul Islamfi 196bbefbe92SMuminul Islam 197bbefbe92SMuminul Islamresult="" 198bbefbe92SMuminul Islamif [[ "${part_type}" == "dos" ]]; then 199bbefbe92SMuminul Islam result="dos mode not supported" 200bbefbe92SMuminul Islamfi 201bbefbe92SMuminul Islamif [[ "${HAS_VIRTIO}" == "0" ]]; then 202bbefbe92SMuminul Islam if [[ "$result" != "" ]]; then 203bbefbe92SMuminul Islam result="${result}," 204bbefbe92SMuminul Islam fi 205bbefbe92SMuminul Islam result="$result VirtIO module not found in the image" 206bbefbe92SMuminul Islamfi 207bbefbe92SMuminul Islamif [[ "$result" == "" ]]; then 208bbefbe92SMuminul Islam echo "No incompatibilities found" 209bbefbe92SMuminul Islamelse 210bbefbe92SMuminul Islam echo "$result" 211bbefbe92SMuminul Islamfi 212