xref: /cloud-hypervisor/scripts/check-image-compatibility.sh (revision 2b2d00653cf0a31ebc9663875f39ce593f3f9b45)
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