1#!/bin/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 80#get file extension and image type 81extension="${file_name##*.}" 82filename="${file_name%.*}" 83dest_file=${working_dir}/${filename}.raw 84image_type=$(qemu-img info ${file_abs_path} | grep 'file format:' | awk '{ print $3 }') 85echo "Image type detected as ${image_type}" 86 87 88if [[ "${image_type}" == "raw" ]]; then 89 dest_file=${file_abs_path} 90elif [[ "$image_type" == "qcow2" ]]; then 91 if lsmod | grep "nbd" &> /dev/null ; then 92 echo "Module nbd is loaded!" 93 else 94 echo "Module nbd is not loaded. Trying to load the module" 95 modprobe nbd max_part=8 96 if [ $? != 0 ]; then 97 echo "failed to load nbd module. Exiting" 98 exit 1 99 fi 100 fi 101 check_command qemu-img 102 dest_file=/dev/nbd0 103 qemu-nbd --connect=${dest_file} ${file_abs_path} --read-only 104fi 105 106check_command blkid 107#get part info 108part_type=$(blkid -o value -s PTTYPE ${dest_file}) 109 110check_command partx 111nr_partitions=`partx -g ${dest_file} | wc -l` 112 113check_command fdisk 114out=`fdisk -l ${dest_file} --bytes | grep -i -A ${nr_partitions} 'Device' | tail -n +2` 115 116IFS=' 117' 118i=0 119declare -A liness 120for x in $out ; do 121 lines[$i]=$x 122 i=$((i+1)) 123done 124 125declare -A partitions 126IFS=' ' 127i=0 128ROWS=${#lines[@]} 129 130for line in "${lines[@]}"; 131do 132 j=0 133 read -a str_arr <<< "$line" 134 for val in "${str_arr[@]}"; 135 do 136 if [[ "$val" != "*" ]]; then 137 partitions[$i,$j]=$val 138 j=$((j+1)) 139 fi 140 done 141 i=$((i+1)) 142done 143 144COLUMNS=$j 145COUNT=${#partitions[@]} 146START_ADDRESS_INDEX=1 147FILE_SYS_INDEX2=$((COLUMNS-1)) 148FILE_SYS_INDEX1=$((COLUMNS-2)) 149DEVICE_INDEX=0 150# Here we have all the partition info now lets mount and analyze the contents 151for ((i=0;i<ROWS;i++)) do 152 if [[ "$part_type" == "gpt" && "${partitions[$i,${FILE_SYS_INDEX1}]}" == "Linux" && "${partitions[$i,${FILE_SYS_INDEX2}]}" == "filesystem" ]]; then 153 echo "The image has GPT partitions" 154 MOUNT_ROW=$i 155 break 156 elif [[ "$part_type" == "dos" && "${partitions[$i,${FILE_SYS_INDEX1}]}" == "Linux" && "${partitions[$i,${FILE_SYS_INDEX2}]}" == "" ]]; then 157 echo "The image has DOS partitions" 158 MOUNT_ROW=$i 159 break 160 fi 161done 162 163start_address=${partitions[${MOUNT_ROW},${START_ADDRESS_INDEX}]} 164offset=$((start_address*512)) 165 166MOUNT_DIR=/mnt/clh-img-check/ 167rm -rf ${MOUNT_DIR} 168mkdir ${MOUNT_DIR} 169if [[ "${image_type}" == "raw" ]]; then 170 mount -o ro,loop,offset=$offset ${dest_file} ${MOUNT_DIR} 171elif [[ "${image_type}" == "qcow2" ]]; then 172 mount -o ro ${partitions[${MOUNT_ROW},${DEVICE_INDEX}]} ${MOUNT_DIR} 173fi 174 175CONFIG_DIR=${MOUNT_DIR}boot/ 176if [[ "$part_type" == "dos" ]]; then 177 CONFIG_DIR=${MOUNT_DIR} 178fi 179 180#check VIRTIO 181HAS_VIRTIO=1 182for conf_file in ${CONFIG_DIR}config*; do 183 out=`grep -E "CONFIG_VIRTIO=y|CONFIG_VIRTIO_BLK=y|CONFIG_VIRTIO_BLK=m" ${conf_file} | wc -l` 184 if [[ "$out" != "2" ]]; then 185 echo "VIRTIO not found" 186 HAS_VIRTIO=0 187 fi 188done 189 190#clean up 191umount ${MOUNT_DIR} 192 193if [[ "${tmp_created}" == "1" ]]; then 194 rm -rf ${working_dir} 195fi 196 197if [[ "${image_type}" == "qcow2" ]];then 198 qemu-nbd --disconnect ${dest_file} > /dev/null 199fi 200 201result="" 202if [[ "${part_type}" == "dos" ]]; then 203 result="dos mode not supported" 204fi 205if [[ "${HAS_VIRTIO}" == "0" ]]; then 206 if [[ "$result" != "" ]]; then 207 result="${result}," 208 fi 209 result="$result VirtIO module not found in the image" 210fi 211if [[ "$result" == "" ]];then 212 echo "No incompatibilities found" 213else 214 echo "$result" 215fi 216