#!/bin/sh
# Copyright (c) Intel.  All rights reserved.
# license gpl2
#
#         Dominig ar Foll, Intel Open Source <dominig.arfoll@fridu.net> 2019 
#
# 
#
### BEGIN INIT INFO
# Provides:       lvm disck structure for StartlingX installation
# Requires:       lvm2
# Description:    Creates a suitable structure on a disk to run StartlingX
### END INIT INFO

############# VARIABLES and CONFIGURATION #############
FILE_SYSTEM_TYPE=btrfs

# sizen in % of total available space to be used by various logical volumes
# on cgst (total must be < 100%)
SCRATCH_LV=3           
LOG_LV=3               
EXTENSION_LV=1       
PGSQL_LV=20             
DOCKER_LV=15
KUBELET_LV=4
ETCD_LV=2
BACKUP_LV=25
DOCKERDISTRIBUTION_LV=8
RABBIT_LV=1
PLATFORM_LV=4
CEPH_MON_LV=10 
# ON NOVA_LOCAL
INSTANCES_LV=100 

# Logging routines
WARNINGS=0
ERRORS=0
CLEAR="$(tput sgr0)"
INFO="$(tput bold)"
RED="$(tput setaf 1)$(tput bold)"
GREEN="$(tput setaf 2)$(tput bold)"
YELLOW="$(tput setaf 3)$(tput bold)"
info() {
        echo "${INFO}$1${CLEAR}"
}
error() {
        ERRORS=$((ERRORS+1))
        echo "${RED}$1${CLEAR}"
}
warn() {
        WARNINGS=$((WARNINGS+1))
        echo "${YELLOW}$1${CLEAR}"
}
success() {
        echo "${GREEN}$1${CLEAR}"
}
die() {
        error "$1"
        exit 1
}
debug() {
        if [ $DEBUG -eq 1 ]; then
                echo "$1"
        fi
}

usage() {
        echo "Creates multiple Logical Volume as required by StartlinX project"
        echo "WARNING: it will wipe out ALL devices pointed by the command"
        echo ""
        echo "Usage: $(basename $0) [-v] [-f] [-t fstype] -c Device1[,Device2] -n DeviceA[,DeviceB]"
        echo "       -v: Verbose debug"
        echo "       -f: Format logical vomumes after creation"
        echo "       -t fstype change the default fstype from btrfs"
        echo "       -c harddrive device comma seprated list (no space) to be used for cgts logical drive"
        echo "       -n harddrive device comma seprated list (no space) to be used for nova logical drive" 
        echo "NOTE: Requires to be run as root and all targetted devices to be unmounted"
        echo "ex:"
        echo "   sudo sh create-lvm.sh -v -c /dev/sda1 -n /dev/sda3"
        echo "   sudo sh create-lvm.sh -f -t ext4 -c /dev/sda1,/dev/sda2 -n /dev/sda3,/dev/sda4"
        echo ""
        exit 1
}
isDevMounted () {
        grep -q -F -w $1 /proc/mounts
        exit_code=$?
        return $exit_code
}

device_details() {
        DEV=$1
        info "Device details"
        echo "  device: $DEV"
        echo    `df -h --output=size $DEV`
        echo ""
}

options_check() {
        debug "Start option and context validation"

        if [[ $EUID -ne 0 ]]; then
            die "This script must be run as root"
        fi
        [ ! -x `sudo which pvcreate` ] && die "pvcreate from lvm2 not available in PATH"
        [ ! -x `sudo which vgcreate` ] && die "vgcreate from lvm2 not available in PATH"
        [ ! -x `sudo which lvcreate` ] && die "lvcreate from lvm2 not available in PATH"
        
        # check that disl space does not go over 100%
        let SUM_SIZE=${SCRATCH_LV}+${LOG_LV}+${EXTENSION_LV}+${PGSQL_LV}+${DOCKER_LV}+${KUBELET_LV}+${ETCD_LV}+${BACKUP_LV}+${DOCKERDISTRIBUTION_LV}+${RABBIT_LV}+${PLATFORM_LV}+${CEPH_MON_LV}
        debug "cgst size adds to $SUM_SIZE of cgst volumes"
        if (( $SUM_SIZE > "100" )); then
           die "Logical volume size allocation for cgst is over 100% : $SUM_SIZE" 
        fi
        debug "nova size adds to $INSTANCES_LV of nova volumes"
        if (($INSTANCES_LV > "100")); then
            die "Logical volume size allocation for nova is over 100% : $INSTANCES_LV " 
        fi
       
        
        if [ -z "$CGTS_DRIVE_LIST" ]; then 
            echo "-c and a minimum of 1 CGTS device is required"
            usage
        fi
        if [ -z "$NOVA_DRIVE_LIST" ]; then
            echo "-n and a minimum of 1 NOVA device is required"
            usage
        fi
        IFS=',' read -r -a CGTS_DRIVES <<< "$CGTS_DRIVE_LIST"
        debug "CGTS_DRIVES=${CGTS_DRIVES[*]}"
        IFS=',' read -r -a NOVA_DRIVES <<< "$NOVA_DRIVE_LIST"
        debug "NOVA_DRIVES=${NOVA_DRIVES[*]}"
        
        for CGTS_DRIVE in "${CGTS_DRIVES[@]}"
          do
            if isDevMounted "$CGTS_DRIVE"; then
               die "CGTS_DRIVE $CGTS_DRIVE is in use -mounted"
            fi
            if [ ! -e "$CGTS_DRIVE" ] ; then
                die "Device for CGTS_DRIVE $CGTS_DRIVE cannot be found"
            fi

          done
        for NOVA_DRIVE in "${NOVA_DRIVES[@]}"
          do
            if isDevMounted "$NOVA_DRIVE"; then 
               die "NOVA_DRIVE $NOVA_DRIVE is in use - mounted"
            fi
            if [ ! -e "$NOVA_DRIVE" ] ; then
                die "Device for NOVA_DRIVE $NOVA_DRIVE cannot be found"
            fi
        done
}

initial_warning() {
        warn "You are about to reformat the ALL following devices"
        for CGTS_DRIVE in "${CGTS_DRIVES[@]}"
          do
            device_details "$CGTS_DRIVE"
          done
        for NOVA_DRIVE in "${NOVA_DRIVES[@]}"
          do
            device_details "$CGTS_DRIVE"
        done
        if FORMAT_LV=1; then
          warn "Formating logical volumes after creation as $FILE_SYSTEM_TYPE is activated"
        fi
        warn "Do you really want ot proceeed ?"
        echo -n "${INFO}Prepare StartlingX image on ${CGTS_DRIVES[*]} ${NOVA_DRIVES[*]} [y/N]?${CLEAR} "
        read RESPONSE
        if [ "$RESPONSE" != "y" ]; then
            die "StartlingX Image creation aborted"
        fi
}

# script entry point
DEBUG=0
FOMRAT_LV=0
# parse argument
while getopts ":h?vft:c:n:" opt; do
    case "$opt" in
    h|\?)
        usage
        ;;
    v)  DEBUG=1
        ;;
    f)  FORMAT_LV=1
        debug "Formating logical volume requested default fstype=$FILE_SYSTEM_TYPE"
        ;;
    t)  FILE_SYSTEM_TYPE=$OPTARG
        FORMAT_LV=1
        debug "FILE_SYSTEM_TYPE changed to $OPTARG, formating LV requested"
        ;;
    c)  CGTS_DRIVE_LIST=$OPTARG
        debug "CGTS_DRIVE_LIST=$OPTARG"
        ;;
    n)  NOVA_DRIVE_LIST=$OPTARG
        debug "NOVA_DRIVE_LIST=$OPTARG"
        ;;

    *)
       echo "syntaxt error -$OPTARG" >&2
       usage
       ;;
    esac
done

options_check
initial_warning

# initial lvm physical volumes (will silently erase any exsiting volume on the devices)
pvcreate -ff -y ${CGTS_DRIVES[*]} ${NOVA_DRIVES[*]}

# create cgts_vg and nova_local logical pool
vgremove -fqy cgts-vg
vgcreate -fq cgts-vg ${CGTS_DRIVES[*]}
vgremove -fqy nova-local
vgcreate -fq nova-local ${NOVA_DRIVES[*]}

# creation des volumes logiques
info "Startting logical volumes creation"
# cgts-vg
debug "lvcreate -q -l ${SCRATCH_LV}%VG -n  scratch-lv cgts-vg"
lvcreate -q -y -l ${SCRATCH_LV}%VG -n  scratch-lv cgts-vg

debug "lvcreate -q -l ${LOG_LV}%VG -n  log-lv cgts-vg"
lvcreate -q -y -l ${LOG_LV}%VG -n  log-lv cgts-vg

debug "lvcreate -q -l ${EXTENSION_LV}%VG -n  extension-lv cgts-vg"
lvcreate -q -y -l ${EXTENSION_LV}%VG -n  extension-lv cgts-vg

debug "lvcreate -q -l ${PGSQL_LV}%VG -n  pgsql-lv cgts-vg"
lvcreate -q -y -l ${PGSQL_LV}%VG -n  pgsql-lv cgts-vg

debug "lvcreate -q -l ${DOCKER_LV}%VG -n  docker-lv cgts-vg"
lvcreate -q -y -l ${DOCKER_LV}%VG -n  docker-lv cgts-vg

debug "lvcreate -q -l ${KUBELET_LV}%VG -n  kubelet-lv cgts-vg"
lvcreate -q -y -l ${KUBELET_LV}%VG -n  kubelet-lv cgts-vg

debug "lvcreate -q -l ${ETCD_LV}%VG -n  etcd-lv cgts-vg"
lvcreate -q -y -l ${ETCD_LV}%VG -n  etcd-lv cgts-vg

debug "lvcreate -q -l ${BACKUP-LV}%VG -n  backup-lv cgts-vg"
lvcreate -q -y -l ${BACKUP-LV}%VG -n  backup-lv cgts-vg

debug "lvcreate -q -l ${DOCKERDISTRIBUTION_LV}%VG -n  dockerdistribution-lv cgts-vg"
lvcreate -q -y -l ${DOCKERDISTRIBUTION_LV}%VG -n  dockerdistribution-lv cgts-vg

debug "lvcreate -q -l ${RABBIT_LV}%VG -n  rabbit-lv cgts-vg"
lvcreate -q -y -l ${RABBIT_LV}%VG -n  rabbit-lv cgts-vg

debug "lvcreate -q -l ${PLATFORM_LV}%VG -n  platform-lv cgts-vg"
lvcreate -q -y -l ${PLATFORM_LV}%VG -n  platform-lv cgts-vg

debug "lvcreate -q -l ${CEPH_MON_LV}%VG -n  ceph-mon-lv cgts-vg"
lvcreate -q -y -l ${CEPH_MON_LV}%VG -n  ceph-mon-lv cgts-vg

#nova-loca
debug "lvcreate -q -l ${INSTANCES_LV}%VG -n  instances_lv nova-local"
lvcreate -q -y -l ${INSTANCES_LV}%VG -n  instances-lv nova-local

if FORMAT_LV=1; then
  info "Starting formating locical volumes"
  for I in `ls /dev/mapper/cgts*`
    do
      debug "mkfs -t $FILE_SYSTEM_TYPE $I"
      mkfs -t $FILE_SYSTEM_TYPE $I
    done
  for I in `ls /dev/mapper/nova*`
    do
      debug "mkfs -t $FILE_SYSTEM_TYPE $I"
      mkfs -t $FILE_SYSTEM_TYPE $I
    done
fi

info "logical volumes created"
vgs -o +lv_size,lv_name


