#!/bin/bash
#
# suma_tool
#
# SUSE Manager Tool by torsten.hallmann@suse.com
# (c) 2012 SUSE Linux GmbH, Germany.
# GNU Public License. No warranty.
#
# Version: 2013-06-03
#
# Documentation
# 
# This script is a tool to easily and quickly provision a SUSE Manager
# installation with basic data. As user you can control the behaviour
# by using the user setting variables below:
# -> SPCMD_USER set the user to interact with the SUSE Manager API.
#    The user needs SUSE Manager Admin permissions for this script to
#    work successfully.
# -> X8664_ONLY set with "Y" creates x86_64 software channels only
# -> SMT_FQDN if set with the FQDN of your SMT uses the SMT for fueling
#    the software channels. Otherwise it's connecting to nu.novell.com.
# -> ISO_DIR defines where the script is searching for SUSE LINUX
#    Enterprise ISO images to be able to create distributions within
#    SUSE Manager incl. corresponding activation keys.
# -> INST_DIR sets the path prefix where the ISO images are
#    loop mounted and added into the FSTAB 

EXE="$0"
CFG="/etc/spock/suma-tool"

# User setting variables
SPCMD_USER="admin"
SPCMD_PASS="suse1234"
SMT_FQDN="smt.test.lab"
X8664_ONLY="Y"
ISO_DIR="/srv/inst/iso"
INST_DIR="/srv/inst/media"
# TODO: SPACE_DIR="/var/spacewalk for all
# TODO: /var/lib/spacewalk/gpgdir $SPACE_DIR/gpgdir 

# Default variables
FSTAB="/etc/fstab"
SYNC_CMD="/usr/bin/spacewalk-repo-sync"
SPACE_CMD="/usr/bin/spacecmd"
SM_NCC_CH_LIST="/var/cache/rhn/suse_manager_ncc_channel_list"
SM_CH_RELATION="/usr/share/susemanager/channels.xml"
SUBSCR_NAP="2"
CHANL_SIZE="15"
#
# TODO: put channels in separate file, to allow updating of current SP.
CHANNELS_SLES10_I586="sles10-sp3-pool-i586 sles10-sp3-updates-i586 sle10-sp3-suse-manager-tools-i586 sles10-sp4-pool-i586 sles10-sp4-updates-i586 sle10-sp4-suse-manager-tools-i586" 
CHANNELS_SLES10_X8664="sles10-sp3-pool-x86_64 sles10-sp3-updates-x86_64 sle10-sp3-suse-manager-tools-x86_64 sles10-sp4-pool-x86_64 sles10-sp4-updates-x86_64 sle10-sp4-suse-manager-tools-x86_64"
#
CHANNELS_SLES11_I586="sles11-sp1-pool-i586 sles11-sp1-updates-i586 sles11-sp1-suse-manager-tools-i586 sles11-sp2-core-i586 sles11-sp2-updates-i586 sles11-sp2-suse-manager-tools-i586"
CHANNELS_SLES11_X8664="sles11-sp1-pool-x86_64 sles11-sp1-updates-x86_64 sles11-sp1-suse-manager-tools-x86_64 sles11-sp2-core-x86_64 sles11-sp2-updates-x86_64 sles11-sp2-suse-manager-tools-x86_64"
#
CHANNELS_SAP_X8664="sle11-sp1-sap-aio-pool-x86_64 sle11-hae-sp1-pool-x86_64-sap-aio sle11-hae-sp1-updates-x86_64-sap-aio sle11-sp1-sap-aio-updates-x86_64 sles11-sp1-pool-x86_64-sap-aio sles11-sp1-suse-manager-tools-x86_64-sap-aio sles11-sp1-updates-x86_64-sap-aio"
#
CHANNELS_VMWARE_I586="sles11-sp1-vmware-pool-i586 sles11-sp1-vmware-updates-i586 sles11-sp1-suse-manager-tools-i586-vmware sles11-sp2-vmware-core-i586 sles11-sp2-vmware-updates-i586 sles11-sp2-suse-manager-tools-i586-vmware"
CHANNELS_VMWARE_X8664="sles11-sp1-vmware-pool-x86_64 sles11-sp1-vmware-updates-x86_64 sles11-sp1-suse-manager-tools-x86_64-vmware sles11-sp2-vmware-core-x86_64 sles11-sp2-vmware-updates-x86_64 sles11-sp2-suse-manager-tools-x86_64-vmware"
#
CHANNELS_SUMAPO_X8664="suse-manager-proxy-1.7-pool-x86_64 sles11-sp1-pool-x86_64-proxy-1.7 sles11-sp1-updates-x86_64-proxy-1.7 sles11-sp2-core-x86_64-proxy-1.7 sles11-sp2-updates-x86_64-proxy-1.7 suse-manager-proxy-1.7-updates-x86_64"
#
CHANNELS_RES4_I586="rhel-i386-as-4 res4-as-i386 res4-as-suse-manager-tools-i386 rhel-i386-es-4 res4-es-i386 res4-es-suse-manager-tools-i386"
CHANNELS_RES4_X8664="rhel-x86_64-as-4 res4-as-suse-manager-tools-x86_64 res4-as-x86_64 rhel-x86_64-es-4 res4-es-suse-manager-tools-x86_64 res4-es-x86_64"
CHANNELS_RES5_I586="rhel-i386-server-5 res5-i386 res5-suse-manager-tools-i386"
CHANNELS_RES5_X8664="rhel-x86_64-server-5 res5-suse-manager-tools-x86_64 res5-x86_64"
CHANNELS_RES6_I586="rhel-i386-server-6 res6-i386 res6-suse-manager-tools-i386"
CHANNELS_RES6_X8664="rhel-x86_64-server-6 res6-suse-manager-tools-x86_64 res6-x86_64"

test -s $CFG && source $CFG


# Define functions

#TODO: add logger to core functions

function write_ncc_output() {
	echo "INFO: start $EXE $FUNCNAME"
	# TODO: check if older than 24h, if so create new?
	mgr-ncc-sync -q -l > $SM_NCC_CH_LIST
	echo "INFO: end $EXE $FUNCNAME"
}


function select_base_channels() {
	# TODO: interactive selection for base channels
	echo "INFO: start $EXE $FUNCNAME"
	echo "Here is the list of available base channels:"
	echo
	cat $SM_NCC_CH_LIST | grep -v '^ ' | awk '{ print $2 }'
	echo
	read -p "Which base channel you would like to work with?: " SM_BASE_CH
	SM_CHILD_CH=`grep parent\=\"$SM_BASE_CH\" $SM_CH_RELATION | grep -o label.* | awk -F \" '{ printf $2 }'`
	SM_CH_PROCEED="$SM_BASE_CH $SM_CHILD_CH"
	echo
	echo "Channels to create: $SM_CH_PROCEED"
	echo "INFO: end $EXE $FUNCNAME"
	exit 1
}


function fueling_with_ncc() {
	echo "INFO: start $EXE $FUNCNAME"
	for channel in $CHANNELS_TO_CREATE; do
		mgr-ncc-sync -c $channel
	done
	echo "INFO: end $EXE $FUNCNAME"
}


function create_channel_tree() {
	echo "INFO: start $EXE $FUNCNAME"
	echo "Creating channel tree without syncing packages:"
	echo
	for channel in $CHANNELS_TO_CREATE; do
  	# TODO: enhance check to search for exact word (vmware)
  	# sles11-sp1-vmware-pool-x86_64 or sle11-hae-sp1-pool-x86_64-vmware
		rc=0
		echo "$CHANNELS_CREATED" | tr " " "\n" |\
			grep -e "^${channel}$"; rc=$?
		if [ $rc -eq 0 ] ; then
			echo "Channel $channel already exists. Skipping..."
  		else
    			echo "Channel $channel ..."
    			mgr-ncc-sync -q -c $channel
    			sleep $SUBSCR_NAP
    			killall -q spacewalk-repo-sync
  		fi
	done
	echo
	echo "Created channel tree."
	rm -rf /var/lib/spacewalk/gpgdir
	echo "INFO: end $EXE $FUNCNAME"
}


function fueling_with_smt() {
	# TODO: make external suma-channel-fueling work as internal fueling_with_smt
	echo "INFO: start $EXE $FUNCNAME"
	echo
	echo "Fueling channels from SMT:"
	echo
	# TODO: ERROR: attempting to run more than one instance of spacewalk-repo-sync Exiting. Check here or in calling function? 
	for channel in $CHANNELS_TO_CREATE; do
	# TODO: check_channel_smt as separate function 
	# TODO: check_channel_ncc as separate function 
  	SMT_URL=$(grep label\=\"$channel\" $SM_CH_RELATION |\
		grep -o source_url.* | awk -F \" '{ print $2 }' |\
	 	sed 's/https/http/' | sed "s/nu.novell.com/$SMT_FQDN/" |\
	 	sed 's/$RCE/%24RCE/')
  	wget --quiet --spider $SMT_URL
  	if [ $? = 1 ]; then
		echo "The source channel $SMT_URL is not available/reachable. Skipping channel $channel ..."
  	else
		echo "Channel $channel ..."
		$SYNC_CMD -q -c $channel -u $SMT_URL
 		# TODO: check if sync_cmd was successfull
  	fi
	done
	echo
	echo "INFO: end $EXE $FUNCNAME"
}


function create_distributions() {
	echo "INFO: start $EXE $FUNCNAME"
	/usr/bin/suma-create-dists
	echo "INFO: end $EXE $FUNCNAME"
}


function version() {
	echo -n "$(basename $EXE) "
	head -11 $EXE | grep "^# Version: "
}


function list_created_channels() {
	CHANNELS_CREATED=$($SPACE_CMD -q -u $SPCMD_USER -p $SPCMD_PASS softwarechannel_list; rc=$?)
	return $rc
}


function check_prereq() {
  echo "INFO: start $EXE $FUNCNAME"
  echo
  version
  echo
  for C in $*; do
    shift
    case $C in
    adm)
  	if [ -z $SPCMD_USER ]; then
		echo "No user for spacecmd defined. Exiting..."
		exit 1
  	else
		echo "User for spacecmd ($SPCMD_USER):	OK"
		if [ -z $SPCMD_PASS ]; then
			echo "No password defined for $SPCMD_USER. Exiting..."
			exit 1
  		fi
		echo "Password for spacecmd:	OK"
  	fi
  	ROLES=$($SPACE_CMD -q -u $SPCMD_USER -p $SPCMD_PASS user_details ${SPCMD_USER} | grep -A 10 Roles | sed 1,+1d)
  	if [[ $ROLES != *org_admin* ]]; then
		echo "User $SPCMD_USER does not have org admin rights. Exiting..."
		exit 1
  	fi
  	echo "Org admin rights for spacecmd:	OK"
	# TODO: existing reg keys
    ;;
    net)
  	rc=0
  	list_created_channels
  	if [ $rc -eq 0 ]; then
		echo "Channels for spacecmd:	OK"
  	fi
  	# TODO: ncc as variable
  	rc=0
  	ping -c2 nu.novell.com >/dev/null; rc=$? 
  	if [ $rc -gt 0 ]; then
		echo "Ping ncc failed."
  	else
		echo "Ping ncc (nu.novell.com):	OK"
  	fi
  	ping -c2 $SMT_FQDN >/dev/null; rc=$? 
  	if [ $rc -gt 0 ]; then
		echo "Ping smt failed."
  	else
		echo "Ping smt ($SMT_FQDN): OK"
  	fi
  	echo
  	# TODO: wget smt, see above 
  	# TODO: ntp
    ;;
    sys)
#	cd /tmp
#	SAM=$(/usr/bin/sam --no-rpm-verify --no-header-sig-check --no-rpm-verify-md5 \
#		--skip-unmatched-prod --no-strict-repo-description --no-log-timestamp \
#		-o /tmp/sam) 
#	cd $OLDPWD
#	P=$(echo $SAM | grep "Product:")
#	echo "Installed product: $P"
	# TODO: susemanager-1.7.16-0.5.4
	# TODO: susemanager-schema-1.7.56.14-0.5.1
	# TODO: spacecmd-1.7.7.7-0.5.1
	# TODO: spacewalk-base-1.7.28.9-0.5.1
	# TODO: spacewalk-postgresql-1.7.3.2-0.5.7
	# TODO: postgresql91-server-9.1.4-0.4.14.1
	# TODO: kernel-default-base-3.0.34-0.7.9
	# TODO: glibc-2.11.3-17.39.1
	# TODO: smdba-1.0-0.23.1
	# TODO: sm-ncc-sync-data-1.7.4-0.5.1
    ;;
    disk)
	# TODO: read default disk needs from cfg file?
	list_created_channels
	# TODO: use available channels instead of already created 
	C=$(echo $CHANNELS_CREATED | tr " " "\n" | grep pool | wc -l)
	DSK_PKG=$[ $C * $CHANL_SIZE ]
	# TODO: database size ?
	DSK_DBS=5
	# TODO: iso size? 3.5 GB per base channel?
	DSK_ISO=$[ $C * 3 ]
	# TODO: variables for dirs
	echo "Need for packages (/var/spacewalk/packages): $DSK_PKG GB"	
	#echo "Need for database (): $DSK_DBS GB"	
	echo "Need for isos ($ISO_DIR): $DSK_ISO GB"	
  	# TODO: df /srv/inst /var/spacewalk /srv/www/htdocs/repo
	# TODO: Oracle, postgres, mrepo ?
	# TODO /var/spacewalk/packages/ 15GB per base channel?
    ;;
    log)
	# TODO: errors ?
    ;;
    esac
  done
  echo "INFO: end $EXE $FUNCNAME"
}


function run_fueling_job() {
case "$1" in
 sles)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_SLES10_X8664 $CHANNELS_SLES11_X8664 $CHANNEL_SAP_X8664
	else
	CHANNELS_TO_CREATE=$CHANNELS_SLES10_I586 $CHANNELS_SLES10_X8664 $CHANNELS_SLES11_I586 $CHANNELS_SLES11_X8664 $CHANNELS_SAP_X8664
	fi
	if [ -z $SMT_FQDN ]; then
		fueling_with_ncc
	else
		echo "Not fully implemented. Exiting..."
		exit 1
	fi
 ;;
 sles10)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_SLES10_X8664
	else
		CHANNELS_TO_CREATE=$CHANNELS_SLES10_I586 $CHANNELS_SLES10_X8664
 	fi
 	if [ -z $SMT_FQDN ]; then
 		fueling_with_ncc
	else
		create_channel_tree
		fueling_with_smt
	fi
 ;;
 sles11)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_SLES11_X8664
	else
		CHANNELS_TO_CREATE=$CHANNELS_SLES11_I586 $CHANNELS_SLES11_X8664
	fi
 	if [ -z $SMT_FQDN ]; then
		fueling_with_ncc
	else
		create_channel_tree
		fueling_with_smt
 	fi
 ;;
 sap)
	CHANNELS_TO_CREATE=$CHANNELS_SAP_X8664
	if [ -z $SMT_FQDN ]; then
		fueling_with_ncc
	else
		echo "Not fully implemented. Exiting..."
		exit 1
 	fi
 ;;
 vmware)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_VMWARE_X8664
	else
		CHANNELS_TO_CREATE=$CHANNELS_VMWARE_I586 $CHANNELS_VMWARE_X8664
	fi
	if [ -z $SMT_FQDN ]; then
		fueling_with_ncc
	else
		create_channel_tree
		fueling_with_smt
	fi
 ;;
 proxy)
	CHANNELS_TO_CREATE=$CHANNELS_SUMAPO_X8664
	if [ -z $SMT_FQDN ]; then
		fueling_with_ncc
	else
		echo "Not fully implemented. Exiting..."
		exit 1
	fi
 ;;
 distributions)
	create_distributions
 ;;
esac
}


function run_init_job() {
case "$1" in
 sles)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_SLES10_X8664 $CHANNELS_SLES11_X8664 $CHANNEL_SAP_X8664
	else
	CHANNELS_TO_CREATE=$CHANNELS_SLES10_I586 $CHANNELS_SLES10_X8664 $CHANNELS_SLES11_I586 $CHANNELS_SLES11_X8664 $CHANNELS_SAP_X8664
	fi
	create_channel_tree
 ;;
 sles10)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_SLES10_X8664
	else
		CHANNELS_TO_CREATE=$CHANNELS_SLES10_I586 $CHANNELS_SLES10_X8664
 	fi
	create_channel_tree
 ;;
 sles11)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_SLES11_X8664
	else
		CHANNELS_TO_CREATE=$CHANNELS_SLES11_I586 $CHANNELS_SLES11_X8664
	fi
	create_channel_tree
 ;;
 sap)
	CHANNELS_TO_CREATE=$CHANNELS_SAP_X8664
	create_channel_tree
 ;;
 vmware)
	if [ $X8664_ONLY = "Y" ]; then
		CHANNELS_TO_CREATE=$CHANNELS_VMWARE_X8664
	else
		CHANNELS_TO_CREATE=$CHANNELS_VMWARE_I586 $CHANNELS_VMWARE_X8664
	fi
	create_channel_tree
 ;;
 proxy)
	CHANNELS_TO_CREATE=$CHANNELS_SUMAPO_X8664
	create_channel_tree
 ;;
 distributions)
	echo "Not implemented: distributions. Exiting..."
	exit 1
 ;;
esac
}


function help() {
	echo "usage:    $(basename $0) [OPTION]"
	echo "usage:    $(basename $0) [--fuel | --init]  channel1 ..."
	echo
	echo " --help		show help"
	echo " --version	show version"
	echo " --check	check pre-requisites"
	echo " --init ...	initialise channels, no sync, no key"
	echo " --fuel ...	fuel with channels, create keys"
	echo
	echo " known channels are:"
	grep -e "^ [[:alnum:]].*)" $EXE | sort -u | tr -d ")"
	echo
	echo " distributions means all base distributions"
}


# main()
# Code
case "$1" in
 sles)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 sles10)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 sles11)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 sap)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 vmware)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 proxy)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 distributions)
	CHN=$1
	check_prereq adm
 	list_created_channels
	run_fueling_job $CHN
 ;;
 -v|--version)
	version
 ;;
 -c|--check|-s|--show)
	check_prereq adm net sys disk
 ;; 
 -t|--test)
	#check_prereq adm net sys disk
	check_prereq disk
 ;;
 -i|--init)
	shift
	check_prereq adm
	for CHN in $*; do
  		list_created_channels
		run_init_job $CHN
	done
 ;;
 -f|--fuel|--full|--fill)
	shift
	check_prereq adm
	for CHN in $*; do
  		list_created_channels
		run_fueling_job $CHN
	done
 ;;
 *)
	help
	exit 1
 ;;
esac
#
