STORAGE=/var/lib/condor-cloud/shared_images
CACHE=/var/lib/condor-cloud/local_cache

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 <image>
#
# 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 <image>
#
# 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 <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 <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 <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
}
