#!/bin/sh

# author : Nicolas Chipaux <aegiap@gandi.net> for GANDI
# all rights reserved.

# legacy without partitions
swap_device=/dev/xvda2
# GPT
if [ -b /dev/disk/by-partlabel/gandiswap ]; then
    full_device=/dev/xvdz
    swap_device=/dev/disk/by-partlabel/gandiswap
elif [ -b /dev/disk/by-label/swap ]; then
    full_device=/dev/xvdz
    swap_device=/dev/disk/by-label/swap
elif [ -b /dev/xvdz1 ]; then
    full_device=/dev/xvdz
    swap_device=/dev/xvdz1
elif [ -b /dev/xvdz ]; then
    swap_device=/dev/xvdz
# freebsd
elif [ -b /dev/da1 ]; then
    swap_device=/dev/da1
# legacy with partitions
elif [ ! -d /proc/xen ]; then
    swap_device=/dev/sdb
fi

[ -e "${full_device}" ] || full_device="${swap_device}"

# We load the default functions and configuration for gandi-config 
[ -f /etc/gandi/plugins-lib ] && . /etc/gandi/plugins-lib || exit 1
load_config

# params: $1 is swap device
ensure_safe() {
    ## Try to avoid calling mkswap on non blank disks
    md5=$(dd if=${1} bs=4k count=128 2>/dev/null | md5sum)
    if [ "$md5" != "59071590099d21dd439896592338bf95  -" ]; then
        echo "Disk ${1} does not seem empty, skipping" 1>&2
        echo "Disk ${1} does not seem empty, skipping" | logger
        return 1
    fi

    return 0
}

# params: $1 is swap device
create_swap() {
    mkswap -L swap -v1 -f "$1" > /dev/null || \
      mkswap -L swap -v1 "$1" > /dev/null
}

# params: $1 is swap device, optional $2 is type
enable_swap() {
    info="$2"
    if [ -z "$2" ]; then
        info=$(/sbin/blkid -s TYPE -o value "$1")
    fi
    if expr match "swap|SWAP|Swap" "${info}" > /dev/null ; then
        swapon "$1" 2>&1 | logger
    else
        msg='Undefined error during swap creation.'
        echo "${msg}" | logger
        echo "${msg}." >&2
    fi
}

# params: $1 is swap device
detect_blkid() {
    ## Detection of GPT disk
    # cannot use the ensure_safe method as the GPT UUID
    # change at each boot, therefor the MD5 sum changes
    info=$(/sbin/blkid -s PARTLABEL -o value "$1")
    if [ ! -z "${info}" -a 'gandiswap' = "${info}" ]; then
        create_swap "$1"
        enable_swap "$1"
        return 0
    fi

    info=$(/sbin/blkid -s PTTYPE -o value "$1")
    if [ ! -z "${info}" -a 'gpt' = "${info}" ]; then
        create_swap "$1"
        enable_swap "$1"
        return 0
    fi

    info=$(/sbin/blkid -s TYPE -o value "$swap_device")
    if [ 'swap' != "${info}" ]; then
        if ensure_safe "$1"; then
            create_swap "$1"
            enable_swap "$1"
        fi
    else
        enable_swap "$1"
    fi
}

# params: $1 is swap device
detect_vol_id() {
    info=$(/lib/udev/vol_id --type "$1")
    ## vol_id returns 4 when volume type is unknown
    ret=$?
    if [ $ret -eq 4 ]; then
        ensure_safe "$1" && create_swap "$1"
    elif [ $ret -eq 0 ]; then
        enable_swap "$1" "${info}"
    fi
}

# params: $1 is swap device, $2 is full device
setup_in_swap() {
    dd if="$2" bs=4k skip=128 2> /dev/null | tar -C / -x -f -
    [ $? -eq 0 ] || return

    gdir='/gandi/'
    keep_ro=0

    if [ ! -w / ]; then
        keep_ro=1
        mount -o remount,rw /
    fi

    # 2. GNU/Linux kernel modules
    if [ -w /lib/modules ]; then
        if [ -L /lib ]; then
            baserep='/usr'
        else
            baserep='/'
        fi

        kernel_ver=$(uname -r)
        taropts=''
        fileext=''
        install=0

        if [ -f "${gdir}/${kernel_ver}-modules.tar.gz" ]; then
            taropts='-z'
            fileext='gz'
            install=1
        fi

        if [ -f "${gdir}/${kernel_ver}-modules.tar.bz2" ]; then
            taropts='-j'
            fileext='bz2'
            install=1
        fi

        if [ $install -eq 1 ]; then
            cd $baserep
            tar -x $taropts -f "${gdir}/${kernel_ver}-modules.tar.$fileext"
            rm -f "${gdir}/${kernel_ver}-modules.tar.$fileext"
            if [ '/' != "$baserep" ]; then
                mv -f $baserep/boot/* /boot/
                rmdir $baserep/boot
            fi
            depmod "$kernel_ver"

            modules_uid=$(stat -t "$baserep/lib/modules/$kernel_ver" -c %u)
            if [ 0 -ne "$modules_uid" ]; then
                    chown -R root:root $baserep/lib/modules/$kernel_ver
            fi
        fi
    fi

    # 3. setup script - configuration is available in /gandi/config
    # in JSON format
    if [ -x $gdir/init ]; then
         pbin=/usr/bin/python3
         [ -x $pbin ] || pbin=/usr/bin/python2
         [ -x $pbin ] || pbin=/usr/bin/python
         $pbin $gdir/init
    fi

    if [ 1 -eq $keep_ro ]; then
         mount -o remount,ro /
         unset keep_ro
    fi

    # then
    create_swap "$1"
}

# check if devices exists and not if already enable as swap
[ -e "${swap_device}" ] || exit 0

# if the swap device is already activated, we stop there
/sbin/swapon -s | grep -q "^$swap_device " && exit 0

# We read the files for the configuration from the disk and not
# the swap partition.
# If a valid tar archive extracts with no error at offset 4k*128,
# use it. Otherwise continue with swap creation logic.
if dd if="${full_device}" bs=4k skip=128 2> /dev/null | tar t gandi 2> /dev/null > /dev/null; then
    setup_in_swap "${swap_device}" "${full_device}"
else
    msg='Cannot find tarball and info in the swap space. Continue formatting.'
    echo "$msg" | logger -t gandi
    echo "$msg"
fi

if [ -x /sbin/blkid ]; then
    detect_blkid "$swap_device"
elif [ -x /lib/udev/vol_id ]; then
    detect_vol_id "$swap_device"
else
    echo "No method is available for device detection." | logger -t gandi
fi

exit 0
