xmount_binary="xmount" dnbd3_binary="dnbd3-server" image_file_or_directory="" do_cleanup=false container_formats="vmdk,vdi,vhd,qcow2" print_usage() { cat << EOF Converts container images (vmdk,vdi,vhd,qcow2) to raw images (on the fly via xmount). Usage: $0 [options] image_file_or_directory Options: -h --help Shows this help message. -x --xmount Path to xmount. (default: "$xmount_binary"). -d --dnbd3 Path to dnbd3-server. (default: "$dnbd3_binary"). -c --cleanup Cleans up the image directory. Unmounts the images and removes symlinks. EOF } parse_command_line() { while true; do case "$1" in -h|--help) print_usage "$0" exit 0 ;; -x|--xmount) shift xmount_binary="$1" shift ;; -d|--dnbd3) shift dnbd3_binary="$1" shift ;; -c|--cleanup) do_cleanup=true shift ;; '') # no more parameters break ;; *) if [ -z "$image_file_or_directory" ]; then if [ -d "$1" ] || [ -f "$1" ]; then image_file_or_directory="$(realpath "$1")" else echo "ERROR: \"$1\" is not a file or a directory." exit 1 fi shift else echo "ERROR: unsupported argument: \"$1\"" print_usage "$0" return 1 fi esac done } cleanup_image() { local image="$1" local mountpoint="$(image_to_mountpoint "$image")" echo "umounting $mountpoint" if ! umount "$mountpoint";then echo "WARNING: umount failed, try with sudo" return 1 fi rmdir "$mountpoint" local link_name="$(image_to_link_name "$image")" [ -L "$link_name" ] && unlink "$link_name" } cleanup() { if [ -d "$image_file_or_directory" ]; then local image shopt -s nullglob # skip unmatched container formats for image in "${image_file_or_directory}"/*.{$container_formats}.r*; do cleanup_image "$image" done else cleanup_image "$image_file_or_directory" fi } check_binaries() { echo $xmount_binary if ! hash "$xmount_binary" 2>/dev/null; then echo "xmount not found, " \ "install it or try to set the --xmount option" exit 1 fi if ! hash "$dnbd3_binary" 2>/dev/null; then echo "dnbd3-server not found," \ " install it or try to set the --dnbd3 option" exit 1 fi } image_to_mountpoint() { # convert [imagename].[container_type].[revision] to # [imagename].[container_type].[revision].xmount local image="$1" extension="${image#*.}" basepath="${image%.$extension}" echo "${basepath}.${extension}.xmount" } image_to_link_name() { # convert [imagename].[container_type].[revision] to # [imagename].[container_type].xmount.[revision] local image="$1" extension="${image#*.}" basepath="${image%.$extension}" revision="${extension#*.}" container_type="${extension%.*}" echo "${basepath}.${container_type}.xmount.${revision}" } convert_image() { local image="$1" [ -d "$image" ] && return 0 local mountpoint="$(image_to_mountpoint "$image")" local link_name="$(image_to_link_name "$image")" echo "creating mountpoint: \"$mountpoint\"" mkdir "$mountpoint" || return 1 ${xmount_binary} -o nonempty --in qemu "$image" \ --out raw "${mountpoint}" echo "creating link: \"$link_name\"" ln -s --relative "${mountpoint}"/*.dd "$link_name" } convert() { if [ -d "$image_file_or_directory" ]; then local image shopt -s nullglob # skip unmatched container formats for image in "${image_file_or_directory}"/*.{vmdk,vdi,vhd,qcow2}.r*; do convert_image "$image" done else convert_image "$image_file_or_directory" fi } parse_command_line "$@" if $do_cleanup; then cleanup else check_binaries convert fi