#!/bin/bash
#
# Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

set -e

SCRIPT_NAME=$(basename $0)
SCRIPT_HOME=$(dirname $0)

# save stdout for later then make fd 1 stderr
exec 3>&1 >&2

function show_options {
    echo "Usage: $SCRIPT_NAME [options] <file>"
    echo
    echo "Load an image into Glance for use with Nova BareMetal driver"
    echo
    echo "Options:"
    echo "      -d            -- delete duplicate images from glance before loading"
    echo "      -h            -- print this help"
    echo
    exit 0
}

function cleanup {
    rm -rf $TMP_IMAGE_DIR
}

function remove_image {
    NAME=$1
    UUIDS=$(glance image-list | awk "/$NAME/ {print \$2}")
    for UUID in $UUIDS; do
        echo "Removing image $1 ($UUID) from glance"
        glance image-delete $UUID
    done
}

function load_image {
    FILE=$(readlink -f $1)
    DIR=$(dirname ${FILE})
    GLANCE_IMAGE_NAME=$(basename ${FILE%.*})
    RAMDISK="${DIR}/${GLANCE_IMAGE_NAME}.initrd"
    KERNEL="${DIR}/${GLANCE_IMAGE_NAME}.vmlinuz"

    if [ ! -e "$FILE" ]; then
        echo "Error: specified file $FILE not found"
        exit 1
    fi

    CURRENT_CHECKSUM=$(nova image-show $GLANCE_IMAGE_NAME 2> /dev/null | awk '/ checksum / {print $4}')
    NEW_CHECKSUM=$(md5sum $FILE | awk '{print $1}')
    if [ "$CURRENT_CHECKSUM" = "$NEW_CHECKSUM" ]; then
        echo "$FILE checksum matches glance checksum, not creating duplicate image."
        nova image-show $GLANCE_IMAGE_NAME | awk '/ id / {print $4}' >&3
        return
    fi

    if [ ! -e "$KERNEL" -o ! -e "$RAMDISK" ] ; then
        DIGK=$(which disk-image-get-kernel || echo $DIB_PATH/bin/disk-image-get-kernel)
        if [ ! -e $DIGK ]; then
            echo "Error: unable to locate disk-image-get-kernel"
            exit 1
        fi

        echo "Warning: Kernel ($KERNEL) or initrd ($RAMDISK) for specified file $FILE not found."
        echo "         Trying to extract them with disk-image-get-kernel now."
        echo "         Please add the \"baremetal\" element to your image-build."
        export TMP_IMAGE_DIR=$(mktemp -t -d --tmpdir=${TMP_DIR:-/tmp} image.XXXXXXXX)
        [ $? -eq 0 ] || die "Failed to create tmp directory"
        trap cleanup EXIT

        $DIGK -d ${TMP_IMAGE_DIR} -o 'tmp' -i $FILE
        KERNEL=$TMP_IMAGE_DIR/tmp-vmlinuz
        RAMDISK=$TMP_IMAGE_DIR/tmp-initrd
    fi

    if [ "$REMOVE_OLD_IMAGES" ]; then
        remove_image "${GLANCE_IMAGE_NAME}-vmlinuz"
        remove_image "${GLANCE_IMAGE_NAME}-initrd"
        remove_image "${GLANCE_IMAGE_NAME}"
    fi

    kernel_id=$(glance image-create \
        --name "${GLANCE_IMAGE_NAME}-vmlinuz" \
        --visibility public \
        --disk-format aki \
        --container-format aki \
        --file "$KERNEL" \
        | grep ' id ' | awk '{print $4}')
    ramdisk_id=$(glance image-create \
        --name "${GLANCE_IMAGE_NAME}-initrd" \
        --visibility public \
        --disk-format ari \
        --container-format ari \
        --file "$RAMDISK" \
        | grep ' id ' | awk '{print $4}')

    # >&3 sends to the original stdout as this is what we are after
    glance image-create --name $GLANCE_IMAGE_NAME \
                        --visibility public \
                        --disk-format qcow2 \
                        --container-format bare \
                        --property kernel_id=$kernel_id \
                        --property ramdisk_id=$ramdisk_id \
                        --file $FILE | awk '/ id / { print $4 }' >&3

    cleanup
    trap EXIT
}


TEMP=`getopt -o hd -n $SCRIPT_NAME -- "$@"`
if [ $? != 0 ]; then
    echo "Terminating..." >&2;
    exit 1;
fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -d) export REMOVE_OLD_IMAGES=1 ; shift ;;
        -h) show_options;;
        --) shift ; break ;;
        *) echo "Error: unsupported option $1." ; exit 1 ;;
    esac
done

for arg; do
    FILES="$FILES $arg";
done

if [ ! "$FILES" ]; then
    show_options
fi

which glance >/dev/null || ( echo "Error: unable to locate glance"; exit 1 )

DIB_PATH=${DIB_PATH:-$SCRIPT_HOME/../../diskimage-builder}

# Attempt to get the OS credentials, or die.
[ -z "$OS_AUTH_URL" ] && [ -z "$OS_USERNAME" ] && [ -z "$OS_PASSWORD" ] && \
    (  ( [ -e ~/stackrc ] && source ~/stackrc ) \
    || ( echo "Error: OS credentials not found. Please save them to ~/stackrc." && exit 1 ) )


# Load the images now
for FILE in $FILES; do
    load_image $FILE
done
