source /etc/sysconfig/condor-cloud ERROR_MSG= MISSING_DEPS= which qemu-img > /dev/null 2>&1 if [ $? -ne 0 ]; then MISSING_DEPS="$MISSING_DEPS qemu-img" return 1 fi # # image_exists_global # # Test to see if the given image is in the global image store. 0 is # returned if the image is present, 1 otherwise. # # This implementation uses the filesystem path $STORAGE as the global # store. # function image_exists_global { IMAGE=$1 test -e $STORAGE/$IMAGE } # # image_exists_local # # Test to see if the given image is in the local image store. 0 is # returned if the image is present, 1 otherwise. # # This implementation uses the filesystem path $CACHE as the local # store. # function image_exists_local { IMAGE=$1 test -e $CACHE/$IMAGE } # # put_image # # Put the image passed as the first argument, into the global image # store. Return 0 on success and 1 on any failure. # # This implementation uses the filesystem path $STORAGE as the global # store. # function put_image { IMAGE=$1 IMAGE_NAME=$(basename $IMAGE) LOCK="$STORAGE/$IMAGE_NAME.lock" CAT=cat; which pv > /dev/null 2>&1 && CAT=pv while ! ( set -o noclobber; echo "$$" > $LOCK ) 2> /dev/null; do echo "$LOCK held by $(cat $LOCK)" >2 sleep $((RANDOM % 29)) done trap 'rm -f $LOCK; exit $?' INT TERM EXIT RC=0 if ! image_exists_global $IMAGE_NAME; then trap 'rm -f $LOCK; rm -f $STORAGE/$IMAGE_NAME; exit $?' INT TERM EXIT ERROR_MSG=$($CAT $IMAGE > $STORAGE/$IMAGE_NAME) if [ $? -eq 0 ]; then # Permissions on the image are entirely open chmod a=r $STORAGE/$IMAGE_NAME else RC=1 fi fi rm -f $LOCK; trap - INT TERM EXIT return $RC } # # get_image # # Get an image from the global image store and make a copy locally for # use by guest VMs. Return 0 on success and 1 on any failure. # # This implementation uses the filesystem path $STORAGE as the global # store and $CACHE as the local. # function get_image { IMAGE=$1 LOCK="$CACHE/$IMAGE.lock" if ! image_exists_global $IMAGE; then ERROR_MSG="$STORAGE/$IMAGE not found" return 1 fi while ! ( set -o noclobber; echo "$$" > $LOCK ) 2> /dev/null; do echo "$LOCK held by $(cat $LOCK)" >2 sleep $((RANDOM % 29)) done trap 'rm -f $LOCK; exit $?' INT TERM EXIT if ! image_exists_local $IMAGE; then trap 'rm -f $LOCK; rm -f $CACHE/$IMAGE; exit $?' INT TERM EXIT ERROR_MSG=$(cp $STORAGE/$IMAGE $CACHE/$IMAGE) if [ $? -ne 0 ]; then return 1 fi # libvirt chowns the qcow2 image to qemu.qemu so that qemu can # read/write it. The base image is not chowned, so we must make sure # it is readable by qemu. If this is not done, a common VMGahpLog # error will be: # Failed to create libvirt domain: monitor socket did not show up.: # No such file or directory # Other than readable, no one should ever write to the file, so write # perms are removed. chmod a+r $CACHE/$IMAGE fi rm -f $LOCK trap - INT TERM EXIT return 0 } # # make_image # # Create a qcow2 image based off the given image and place it in the # local image store. The qcow2 image is echo'd to stdout. The return # value has no meaning. # # This implementation uses the filesystem path $CACHE as the local # store. # function make_image { BASE_IMAGE=$1 LOCATION=$2 LOCK="$CACHE/$BASE_IMAGE.lock" if ! image_exists_local $BASE_IMAGE; then ERROR_MSG="$BASE_IMAGE not found" return 1 fi # # Use the $LOCK as a barrier in case the image is concurrently # being added to the $CACHE. Granted, that is a case that should # never happen. Unfortunately, the existence of the $LOCK cannot be # used as an assertion condition because a concurrent get_image # will briefly create $LOCK even when the $BASE_IMAGE is already in # the $CACHE. # while ! ( set -o noclobber; echo "$$" > $LOCK ) 2> /dev/null; do echo "$LOCK held by $(cat $LOCK)" >2 sleep $((RANDOM % 29)) done trap 'rm -f $LOCK; exit $?' INT TERM EXIT IMAGE=$LOCATION/$BASE_IMAGE.qcow2 qemu-img create -f qcow2 -b $CACHE/$BASE_IMAGE $IMAGE > /dev/null 2>&1 # XXX: test for success, give return value meaning rm -f $LOCK echo $IMAGE return 0 }