#!/bin/sh # Copyright: # (c) 2013-2016, Thomas Goirand # (c) 2015-2016, Bastian Blank # License: Apache 2.0, see LICENSE.txt for details. set -e if [ "$UNSHARED" != true ] ; then exec env UNSHARED=true unshare --mount --pid --fork --mount-proc "$0" "$@" fi LC_ALL=C export LC_ALL # Parse input parameters usage() { echo "Usage: $0 --release|-r [options] Options are: --minimal|-m --azure|-az --boot-manager|-bm (default: grub) --debootstrap-url|-u (default: http://httpredir.debian.org/debian) --sources.list-mirror|-s (default: http://httpredir.debian.org/debian) --extra-packages|-e ,,... --hook-script|-hs --image-size|-is (default: 2G) --automatic-resize|-ar --automatic-resize-space|-ars (default: 50M) --login|-l (default: debian) --password|-p (dangerous option: avoid it if possible) --boot-type|-bt (default: mbr) --architecture|-a (default: amd64) For more info: man $0" exit 1 } EXTRA=yes AZURE=no BOOTMANAGER=grub BOOTTYPE=mbr ARCH=amd64 for i in $@ ; do case "${1}" in "--extra-packages"|"-e") if [ -z "${2}" ] ; then echo "No parameter defining the extra packages" usage fi EXTRA_PACKAGES=${2} shift shift ;; "--debootstrap-url"|"-u") if [ -z "${2}" ] ; then echo "No parameter defining the debootstrap URL" usage fi DEB_MIRROR=${2} shift shift ;; "--minimal"|"-m") EXTRA=no shift ;; "--azure"|"-az") AZURE=yes shift ;; "--boot-manager"|"-bm") if [ "${2}" != "grub" ] && [ "${2}" != "syslinux" ] ; then echo "No recognized parameter defining the boot manager" usage fi BOOTMANAGER=${2} shift shift ;; "--boot-type"|"-bt") if [ "${2}" != "mbr" ] && [ "${2}" != "uefi" ] ; then echo "No recognized parameter defining the boot type" usage fi BOOTTYPE=${2} shift shift ;; "--architecture"|"-a") if [ "${2}" != "amd64" ] && [ "${2}" != "arm64" ] ; then echo "No recognized parameter defining the architecture (currently support amd64 and arm64)" usage fi ARCH=${2} shift shift ;; "--automatic-resize"|"-ar") AUTOMATIC_RESIZE=yes shift ;; "--automatic-resize-space"|"-ars") if [ -z "${2}" ] ; then echo "No parameter defining the suplementary space" usage fi AUTOMATIC_RESIZE_SPACE=${2} shift shift ;; "--image-size"|"-is") if [ -z "${2}" ] ; then echo "No parameter defining the image size" usage fi IMAGE_SIZE=${2} shift shift ;; "--hook-script"|"-hs") if [ -z "${2}" ] ; then echo "No parameter defining the hook script" usage fi if ! [ -x "${2}" ] ; then echo "Hook script not executable" fi HOOK_SCRIPT=${2} shift shift ;; "--sources.list-mirror"|"-s") if [ -z "${2}" ] ; then echo "No parameter defining the hook script" usage fi SOURCE_LIST_MIRROR=${2} shift shift ;; "--release"|"-r") if [ "${2}" = "wheezy" ] || [ "${2}" = "jessie" ] || [ "${2}" = "stretch" ] || [ "${2}" = "buster" ] ; then RELEASE=${2} shift shift else echo "Release not recognized." usage fi ;; "--login"|"-l") if [ -z "${2}" ] ; then echo "No parameter defining the user login" usage fi USER_LOGIN=${2} shift shift ;; "--password"|"-p") if [ -z "${2}" ] ; then echo "No parameter defining the root password" fi ROOT_PASSWORD=${2} shift shift ;; "--output"|"-o") if [ -z "${2}" ] ; then echo "No output file specified" fi OUTPUT=${2} shift shift ;; *) ;; esac done if [ -z "${RELEASE}" ] ; then echo "Release not recognized: please specify the -r parameter." usage fi case "${RELEASE}" in "wheezy") RELEASE_NUM=7 ;; "jessie") RELEASE_NUM=8 ;; "stretch") RELEASE_NUM=9 ;; "buster") RELEASE_NUM=10 ;; esac if [ -z "${DEB_MIRROR}" ] ; then DEB_MIRROR=http://httpredir.debian.org/debian fi if [ -z "${EXTRA_PACKAGES}" ] ; then EXTRA_PACKAGES=bash-completion,joe,most,screen,less,vim,bzip2,nano fi if [ -z "${SOURCE_LIST_MIRROR}" ] ; then SOURCE_LIST_MIRROR=http://httpredir.debian.org/debian fi if [ -z "${IMAGE_SIZE}" ] ; then IMAGE_SIZE=2 fi if [ -z "${AUTOMATIC_RESIZE_SPACE}" ] ; then AUTOMATIC_RESIZE_SPACE=50 fi if [ -z "${USER_LOGIN}" ] ; then USER_LOGIN=debian fi if [ -z "${OUTPUT}" ] ; then OUTPUT=debian-${RELEASE}-$(TZ=UTC date '+%Y%m%d%H%M')-${ARCH} fi if [ "${BOOTTYPE}" = "uefi" ] && [ "${BOOTMANAGER}" != "grub" ] ; then echo "uefi boot type is only compatible with grub" usage fi if [ "${ARCH}" = "arm64" ] ; then if [ "${BOOTMANAGER}" != "grub" ] || [ "${BOOTTYPE}" != "uefi" ] ; then echo "arm64 depends on using grub and uefi" usage fi fi CONSOLE=ttyS0 if [ "${ARCH}" = "arm64" ] ; then CONSOLE=ttyAMA0 fi if [ "${BOOTMANAGER}" = "grub" ] ; then if [ "${BOOTTYPE}" = "uefi" ] ; then BOOT_MGR_PKG="grub-efi-${ARCH}" if [ "${ARCH}" = "arm64" ] ; then GRUB_TARGET="arm64-efi" else GRUB_TARGET="x86_64-efi" fi else BOOT_MGR_PKG="grub-pc" GRUB_TARGET="i386-pc" fi else BOOT_MGR_PKG="extlinux" fi NEEDED_PACKAGES=sudo,adduser,locales,${BOOT_MGR_PKG},openssh-server,euca2ools,file,kbd,aptitude,file if [ "${RELEASE}" = "wheezy" ] ; then # These are needed by cloud-init and friends, and since we don't want backports of them, # but just normal packages from Wheezy, we resolve dependencies by hand, prior to using # apt-get -t wheezy-backports install cloud-init cloud-utils cloud-initramfs-growroot NEEDED_PACKAGES=${NEEDED_PACKAGES},python,python-paramiko,python-argparse,python-cheetah,python-configobj,python-oauth,python-software-properties,python-yaml,python-boto,python-prettytable,initramfs-tools,python-requests,acpid,acpi-support-base,ntp,unscd else NEEDED_PACKAGES=${NEEDED_PACKAGES},cloud-init,cloud-utils,cloud-initramfs-growroot,dbus,ntp,unscd fi # This is a workaround for python3-cryptography failing to install if [ "${RELEASE_NUM}" -ge 9 ] ; then NEEDED_PACKAGES=${NEEDED_PACKAGES},python3-cffi-backend fi if [ ${EXTRA} = "no" ] ; then PKG_LIST=${NEEDED_PACKAGES} else PKG_LIST=${NEEDED_PACKAGES},${EXTRA_PACKAGES} fi if ! [ `whoami` = "root" ] ; then echo "You have to be root to run this script" exit 1 fi FILE_NAME=debian-${RELEASE}-${RELEASE_NUM}.0.0-1-${ARCH} RAW_NAME=${OUTPUT}.raw QCOW2_NAME=${OUTPUT}.qcow2 rm -f ${RAW_NAME} set -x ###################################### ### Prepare the HDD (format, ext.) ### ###################################### PARTED=/sbin/parted rm -f $RAW_NAME qemu-img create ${RAW_NAME} ${IMAGE_SIZE}G if [ "${BOOTTYPE}" = "mbr" ] ; then ${PARTED} -s ${RAW_NAME} mktable msdos ${PARTED} -s -a optimal ${RAW_NAME} mkpart primary ext4 1Mi 100% ${PARTED} -s ${RAW_NAME} set 1 boot on install-mbr --force ${RAW_NAME} RESULT_KPARTX=$(kpartx -asv ${RAW_NAME} 2>&1) if echo "${RESULT_KPARTX}" | grep "^add map" ; then LOOP_DEVICE=$(echo ${RESULT_KPARTX} | cut -d" " -f3) LOOPRAW_DEVICE=${LOOP_DEVICE%p*} echo "kpartx mounted using: ${LOOP_DEVICE} via ${LOOPRAW_DEVICE}" else echo "It seems kpartx didn't mount the image correctly: exiting." exit 1 fi else # uefi ${PARTED} -s ${RAW_NAME} mktable gpt ${PARTED} -s -a optimal ${RAW_NAME} mkpart ESP fat32 1Mi 101Mi ${PARTED} -s -a optimal ${RAW_NAME} -- mkpart ROOT ext4 102Mi -64s ${PARTED} -s ${RAW_NAME} set 1 esp on RESULT_KPARTX=$(kpartx -asv ${RAW_NAME} 2>&1 | tail -1) if echo "${RESULT_KPARTX}" | grep "^add map" ; then LOOP_DEVICE=$(echo ${RESULT_KPARTX} | cut -d" " -f3) LOOPRAW_DEVICE=${LOOP_DEVICE%p*} echo "kpartx mounted using: ${LOOP_DEVICE} via ${LOOPRAW_DEVICE}" else echo "It seems kpartx didn't mount the image correctly: exiting." exit 1 fi LOOP_DEVICE_ESP=$(kpartx -asv ${RAW_NAME} 2>&1 | head -1 | cut -d" " -f3) fi cleanup(){ error=$? [ ! -d "${MOUNT_DIR}" ] && return if [ "$error" -gt 0 ]; then echo echo "Error $error" else echo "Finished." fi set +e sync chroot ${MOUNT_DIR} umount /proc || true chroot ${MOUNT_DIR} umount /sys || true chroot ${MOUNT_DIR} umount /dev || true umount -l ${MOUNT_DIR} rmdir ${MOUNT_DIR} kpartx -d ${RAW_NAME} exit $error } trap "cleanup" EXIT TERM INT mkfs.ext4 /dev/mapper/${LOOP_DEVICE} UUID=$(blkid -o value -s UUID /dev/mapper/${LOOP_DEVICE}) # No fsck because of X days without checks tune2fs -i 0 /dev/mapper/${LOOP_DEVICE} MOUNT_DIR=`mktemp -d -t build-debimg.XXXXXX` mount /dev/mapper/${LOOP_DEVICE} ${MOUNT_DIR} if [ "${BOOTTYPE}" = "uefi" ] ; then mkfs.vfat /dev/mapper/${LOOP_DEVICE_ESP} UUID_ESP=$(blkid -o value -s UUID /dev/mapper/${LOOP_DEVICE_ESP}) mkdir -p ${MOUNT_DIR}/boot/efi mount /dev/mapper/${LOOP_DEVICE_ESP} ${MOUNT_DIR}/boot/efi fi debootstrap --verbose \ --include=${PKG_LIST} \ ${RELEASE} ${MOUNT_DIR} ${DEB_MIRROR} ############################ ### Customize the distro ### ############################ ### Customize: access to the VM ### # # # # # # # # # # # # # # # # # # # Setup default root password to what has been set on the command line if [ -n "${ROOT_PASSWORD}" ] ; then chroot ${MOUNT_DIR} sh -c "echo root:${ROOT_PASSWORD} | chpasswd" fi # Otherwise, we have a huge backdoor, since the root password # is always the same. sed -i "s/PermitRootLogin yes/PermitRootLogin without-password/" ${MOUNT_DIR}/etc/ssh/sshd_config cat >>${MOUNT_DIR}/etc/ssh/sshd_config <${MOUNT_DIR}/etc/sudoers.d/debian-cloud-init chmod 0440 ${MOUNT_DIR}/etc/sudoers.d/debian-cloud-init ### Customize: misc stuff ### # # # # # # # # # # # # # # # # Setup fstab echo "# /etc/fstab: static file system information. UUID=${UUID} / ext4 errors=remount-ro 0 1 " > ${MOUNT_DIR}/etc/fstab if [ "${BOOTTYPE}" = "uefi" ] ; then echo "UUID=${UUID_ESP} /boot/efi vfat errors=remount-ro 0 0" >> ${MOUNT_DIR}/etc/fstab fi mount -t proc proc ${MOUNT_DIR}/proc echo "# disable pc speaker blacklist pcspkr" >${MOUNT_DIR}/etc/modprobe.d/blacklist.conf # Enable bash-completion by default if [ ${EXTRA} = "yes" ] ; then echo "# enable bash completion in interactive shells if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi fi" >>${MOUNT_DIR}/etc/bash.bashrc fi # No clear for the tty1 console if [ "${RELEASE}" = "wheezy" ] ; then sed -i "s#1:2345:respawn:/sbin/getty 38400 tty1#1:2345:respawn:/sbin/getty --noclear 38400 tty1#" ${MOUNT_DIR}/etc/inittab else # XXX: the serial port on Microsoft Azure plattform can't cope with # lots of data, keep this option disabled. #echo ForwardToConsole=yes >> ${MOUNT_DIR}/etc/systemd/journald.conf : fi # We do it *after* the debootstrap, as otherwise it fails with # systemd-shim conflicting with systemd-sysv. chroot ${MOUNT_DIR} apt-get install -y locales-all libpam-systemd # Turn off console blanking which is *very* annoying # and increase KEYBOARD_DELAY because it can be annoying # over network. # Note: /etc/kbd/config is gone away from Stretch, but # we still need to fix it for previous Debian releases. # In stretch and beyond, consoleblank=0 in the kernel # command line should be enough (TODO: check for that fact). if [ -e ${MOUNT_DIR}/etc/kbd/config ] ; then sed -i s/^BLANK_TIME=.*/BLANK_TIME=0/ ${MOUNT_DIR}/etc/kbd/config sed -i s/^POWERDOWN_TIME=.*/POWERDOWN_TIME=0/ ${MOUNT_DIR}/etc/kbd/config sed -i 's/^[ \t#]KEYBOARD_DELAY=.*/KEYBOARD_DELAY=1000/' ${MOUNT_DIR}/etc/kbd/config fi rm -f ${MOUNT_DIR}/etc/ssh/ssh_host_* rm -f ${MOUNT_DIR}/etc/udev/rules.d/70-persistent-net.rules rm -f ${MOUNT_DIR}/lib/udev/write_net_rules # Setup networking (eg: DHCP by default) echo "# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The normal eth0 auto eth0 iface eth0 inet dhcp # Maybe the VM has 2 NICs? allow-hotplug eth1 iface eth1 inet dhcp # Maybe the VM has 3 NICs? allow-hotplug eth2 iface eth2 inet dhcp " > ${MOUNT_DIR}/etc/network/interfaces # FIXME: DHCP RFC3442 is used incorrect in Azure sed -ie 's,rfc3442-classless-static-routes,disabled-\0,' $BODI_CHROOT_PATH/etc/dhcp/dhclient.conf # Setup the default hostname (will be set by cloud-init # at boot time anyway) echo "debian.example.com" >${MOUNT_DIR}/etc/hostname # This should be a correct default everywhere echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE} main deb-src ${SOURCE_LIST_MIRROR} ${RELEASE} main" >${MOUNT_DIR}/etc/apt/sources.list if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "jessie" ] ; then echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE}-updates main deb-src ${SOURCE_LIST_MIRROR} ${RELEASE}-updates main deb http://security.debian.org/ ${RELEASE}/updates main deb-src http://security.debian.org/ ${RELEASE}/updates main " >>${MOUNT_DIR}/etc/apt/sources.list fi if [ "${RELEASE}" = "wheezy" ] ; then echo "deb ${SOURCE_LIST_MIRROR} wheezy-backports main deb-src ${SOURCE_LIST_MIRROR} wheezy-backports main " >>${MOUNT_DIR}/etc/apt/sources.list fi if [ "${RELEASE}" = "jessie" ] && [ "${AZURE}" = "yes" ] ; then echo "deb ${SOURCE_LIST_MIRROR} jessie-backports main deb-src ${SOURCE_LIST_MIRROR} jessie-backports main deb ${SOURCE_LIST_MIRROR}-azure jessie-backports main deb-src ${SOURCE_LIST_MIRROR}-azure jessie-backports main " >>${MOUNT_DIR}/etc/apt/sources.list fi if [ "${AZURE}" = "yes" ] ; then chroot ${MOUNT_DIR} apt-key add - < ${MOUNT_DIR}/etc/apt/preferences.d/linux.pref <${MOUNT_DIR}/etc/cloud/cloud.cfg.d/90_dpkg.cfg else # For OpenStack, we would like to use Ec2 and no other API echo "# to update this file, run dpkg-reconfigure cloud-init datasource_list: [NoCloud, ConfigDrive, Openstack, Ec2]" >${MOUNT_DIR}/etc/cloud/cloud.cfg.d/90_dpkg.cfg fi # Needed to have automatic mounts of /dev/vdb echo "mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']" >>${MOUNT_DIR}/etc/cloud/cloud.cfg echo "manage_etc_hosts: true" >>${MOUNT_DIR}/etc/cloud/cloud.cfg # Set the cloud init default user (required for the keypair to be put in the right home directory) sed -i "s/name: debian/name: ${USER_LOGIN}/" ${MOUNT_DIR}/etc/cloud/cloud.cfg if [ "${AZURE}" = "yes" ] ; then unshare --pid --fork --mount-proc chroot ${MOUNT_DIR} apt-get install -y waagent rm -f ${MOUNT_DIR}/var/log/waagent.log fi # Setting-up initramfs chroot ${MOUNT_DIR} update-initramfs -u rm ${MOUNT_DIR}/var/cache/apt/archives/*.deb # Set console for emergency and rescue shells SYSTEMD_DIR="${MOUNT_DIR}/etc/systemd/system/" for service in emergency.service rescue.service ; do mkdir "${SYSTEMD_DIR}/${service}.d" echo '[Service] ExecStart= ExecStart=-/bin/sh -c "/sbin/sulogin /dev/tty0; /bin/systemctl --fail --no-block default"' > "${SYSTEMD_DIR}/${service}.d/console.conf" done ################################### ### Setting-up extlinux or grub ### ################################### mkdir -p ${MOUNT_DIR}/boot/extlinux if [ "${RELEASE}" = "wheezy" ] ; then append="rootdelay=30" fi KERNEL_PARAMS="biosdevname=0 net.ifnames=0 console=tty0 console=$CONSOLE,115200 earlyprintk=$CONSOLE,115200 consoleblank=0 systemd.show_status=true $append" if [ "${BOOTMANAGER}" = "grub" ] ; then sed -i -e 's|^[ #\t]*GRUB_CMDLINE_LINUX_DEFAULT[ #\t]*=.*|GRUB_CMDLINE_LINUX_DEFAULT="'"${KERNEL_PARAMS}"'"|' ${MOUNT_DIR}/etc/default/grub echo " # openstack-debian-images disables OS prober to avoid # loopback detection which breaks booting GRUB_DISABLE_OS_PROBER=true" >>${MOUNT_DIR}/etc/default/grub # Tell grub about our loopback devices first mkdir -p ${MOUNT_DIR}/boot/grub mount --bind /dev ${MOUNT_DIR}/dev mount --bind /proc ${MOUNT_DIR}/proc mount --bind /sys ${MOUNT_DIR}/sys echo "grub-efi-${ARCH} grub2/force_efi_extra_removable boolean true" | chroot ${MOUNT_DIR} debconf-set-selections chroot ${MOUNT_DIR} grub-mkconfig -o /boot/grub/grub.cfg # Run grub from the chroot, pointing to the bind mounted /dev device. chroot ${MOUNT_DIR} grub-install --target=${GRUB_TARGET} --force-extra-removable --no-floppy --modules="part_msdos part_gpt" --grub-mkdevicemap=/boot/grub/device.map /dev/${LOOPRAW_DEVICE} # Run grub from the host, pointing to the guest installation #grub-install --no-floppy --modules=part_msdos --grub-mkdevicemap=${MOUNT_DIR}/boot/grub/device.map --root-directory=${MOUNT_DIR} /dev/${LOOPRAW_DEVICE} umount ${MOUNT_DIR}/sys umount ${MOUNT_DIR}/dev umount ${MOUNT_DIR}/proc else KERNEL_PARAMS="initrd=/initrd.img root=UUID=${UUID} ${KERNEL_PARAMS} ro" echo "default linux timeout 1 label linux kernel /vmlinuz append ${KERNEL_PARAMS}" > ${MOUNT_DIR}/boot/extlinux/extlinux.conf extlinux --install ${MOUNT_DIR}/boot/extlinux fi ################### ### HOOK SCRIPT ### ################### if [ -x ${HOOK_SCRIPT} ] ; then export BODI_CHROOT_PATH=${MOUNT_DIR} export BODI_RELEASE=${RELEASE} ${HOOK_SCRIPT} fi ########################## ### Unmount everything ### ########################## cleanup(){ # refine cleanup everything was ok echo "Finished." } sync chroot ${MOUNT_DIR} umount /proc || true chroot ${MOUNT_DIR} umount /sys || true chroot ${MOUNT_DIR} umount /boot/efi || true # Defrag the filesystem to allow for better size reduction below e4defrag /dev/mapper/${LOOP_DEVICE} > /dev/null umount ${MOUNT_DIR} # Run FSCK so that resize can work fsck.ext4 -f /dev/mapper/${LOOP_DEVICE} || true if [ "${AUTOMATIC_RESIZE}" = "yes" ] ; then resize2fs -M /dev/mapper/${LOOP_DEVICE} FS_BLOCKS=`tune2fs -l /dev/mapper/${LOOP_DEVICE} | awk '/Block count/{print $3}'` WANTED_SIZE=`expr $FS_BLOCKS '*' 4 '/' 1024 + ${AUTOMATIC_RESIZE_SPACE}` # Add ${AUTOMATIC_RESIZE_SPACE}M resize2fs /dev/mapper/${LOOP_DEVICE} ${WANTED_SIZE}M FINAL_FS_BLOCKS=`tune2fs -l /dev/mapper/${LOOP_DEVICE} | awk '/Block count/{print $3}'` fi sync kpartx -d ${RAW_NAME} rmdir ${MOUNT_DIR} if [ "${AUTOMATIC_RESIZE}" = "yes" ] ; then if [ "${BOOTTYPE}" = "mbr" ] ; then # some blocks for mbr and multiple block size (4k) FINAL_IMG_SIZE=`expr '(' $FINAL_FS_BLOCKS + 258 ')' '*' 4 '/' 1024` # Rebuild a smaller partition table ${PARTED} -s ${RAW_NAME} rm 1 ${PARTED} -s ${RAW_NAME} mkpart primary ext4 1Mi ${FINAL_IMG_SIZE}Mi ${PARTED} -s ${RAW_NAME} set 1 boot on # Add 2M for the 1M at the beginning of the partition and some additional space truncate -s `expr 3 + ${FINAL_IMG_SIZE}`M ${RAW_NAME} install-mbr ${RAW_NAME} else # uefi # Work out the sizes of the new image # 1M for the GPT header, and alignment padding # 100M for the ESP # $FINAL_FS_BLOCKS for the root partition FINAL_IMG_SIZE=$((1 + 100 + $((${FINAL_FS_BLOCKS} * 4 / 1024)) + 1)) # Rebuild a smaller partition table ${PARTED} -s ${RAW_NAME} rm 2 ${PARTED} -s -a optimal ${RAW_NAME} -- mkpart ROOT ext4 102Mi -64s # Add 1M padding truncate -s $((1 + ${FINAL_IMG_SIZE}))M ${RAW_NAME} fi fi if ! [ "${AZURE}" = "yes" ] ; then QEMU_VERSION=`qemu-img --help | head -n 1 | cut -d" " -f3 | cut -d"," -f1` if dpkg --compare-versions ${QEMU_VERSION} gt 1.0 ; then OTHER_QEMU_IMG_OPTIONS=" -o compat=0.10" else OTHER_QEMU_IMG_OPTIONS="" fi qemu-img convert -c -f raw ${RAW_NAME}${OTHER_QEMU_IMG_OPTIONS} -O qcow2 ${QCOW2_NAME} fi