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