#@file    ogfunctions.lib
#@brief   Librería o clase para la generación del 1erFS 
#@class   client
#@brief   Funciones para la generación del primers sistema (initrd)
#@version 0.91
#@warning License: GNU GPLv3+




ogExportKernelParameters ()
{
	GLOBAL="cat /proc/cmdline"
	for i in `${GLOBAL}`
	do
		echo $i | grep "=" > /dev/null && export $i
	done
return 0
}

ogExportVarEnvironment ()
{
	export CFGINITRD="/tmp/initrd.cfg"
	echo "puntos de accesos al servidor ogprotocol=nfs" >> $CFGINITRD
	export NFSROOTBOOT="/var/lib/tftpboot" && echo "NFSROOTBOOT=$NFSROOTBOOT" >> $CFGINITRD	
	export NFSCLIENTDIR="/opt/opengnsys/client" && echo "NFSCLIENDIR=$NFSCLIENTDIR" >> $CFGINITRD	
	export NFSLOGDIR="/opt/opengnsys/log/clients" && echo "NFSLOGDIR=$NFSLOGDIR" >> $CFGINITRD	
	export NFSIMGDIR="/opt/opengnsys/images" && echo "NFSIMGDIR=$NFSIMGDIR" >> $CFGINITRD	
	echo "puntos de accesos al servidor ogprotocol=smb" >> $CFGINITRD
	export SMBROOTBOOT="tftpboot"  && echo "SMBROOTBOOT=$SMBROOTBOOT" >> $CFGINITRD	
	export SMBCLIENTDIR="ogclient" && echo "SMBCLIENTDIR=$SMBCLIENTDIR" >> $CFGINITRD
	export SMBLOGDIR="oglog" && echo "SMBLOGDIR=$SMBLOGDIR" >> $CFGINITRD
	export SMBIMGDIR="ogimages" && echo "SMBIMGDIR=$SMBIMGDIR" >> $CFGINITRD

	echo "puntos de montaje local para los contenedores" >> $CFGINITRD
	export LOCALROOTBOOT="/opt/og2fs/tftpboot"	&& echo "LOCALROOTBOOT=$LOCALROOTBOOT" >> $CFGINITRD
	export LOCALCLIENTDIR="/opt/opengnsys" && echo "LOCALCLIENTDIR=$LOCALCLIENTDIR" >> $CFGINITRD		
	export LOCALLOGDIR="/opt/opengnsys/log" && echo "LOCALLOGDIR=$LOCALLOGDIR" >> $CFGINITRD
	export LOCALIMGDIR="/opt/opengnsys/images" && echo "LOCALIMGDIR=$LOCALIMGDIR" >> $CFGINITRD
	
	echo "puntos de montajes para realizar la integración unionfs entre el initrd y el sistema root" >> $CFGINITRD
	#punto de montaje donde se accede al 2nd FS mediante loop
	export LOCALROOTIMG="/opt/og2fs/2ndfs"	&& echo "LOCALROOTIMG=$LOCALROOTIMG" >> $CFGINITRD		
	#punto de montaje para unionfs 
	export LOCALROOTRAM="/opt/og2fs/1stfs" && echo "LOCALROOTRAM=$LOCALROOTRAM" >> $CFGINITRD				
	#punto de union entreo LOCALROOTIMG y LOCALROOTRAM
	export LOCALROOTUNION="/opt/og2fs/unionfs" && echo "LOCALROOTUNION=$LOCALROOTUNION" >> $CFGINITRD			
	##INFORMACION DE OTRAS VARIABLES OBTENDIAS EN OTRAS FUNCIONES.
	#ogGetROOTSERVER()  ip del servidor pxe, valor obtenido automaticamente desde dhcpd.
	#IPV4DDR
	#IPV4BROADCAST
	#IPV4NETMASK
	#IPV4GATEWAY
	#DNS0 	DNS1
	#HOSTNAME
	#ROOTSERVER  #ip del servidor pxe que ha servido el kernel
	#REPOSERVER=ogrepo  -> ogConectROOTSERVER() ip del servidor de images para separar serviicios.
	return 0
}

ogConfigureRamfs ()
{
	mkdir -p $LOCALROOTBOOT
	mkdir -p $LOCALROOTIMG
	mkdir -p $LOCALROOTRAM   			 
	mkdir -p $LOCALROOTUNION 
}

ogLoadNetModule ()
{
	#cargando netmodule
	if [ -n "$ognetmodule" ]
	then
   		echo "Cargando modulo de red $netmodule"
   		insmod `find /lib/modules/ -name ${netmodule}*`
	fi
}


ogPostConfigureFS()
{
	# configuramos el /etc/hostname.
	echo $HOSTNAME > /etc/hostname
	
	#configuramos el /etc/hosts
	echo "127.0.0.1 localhost" > /etc/hosts
	echo "$IPV4ADDR $HOSTNAME" >> /etc/hosts
	
	#configuramos el host.conf
	echo "order hosts,bind" > /etc/host.conf
	echo "multi on" >> /etc/host.conf
	
	# configuramos el /etc/networks
	#read -e NETIP NETDEFAULT <<<$(route -n | grep eth0 | awk -F" " '{print $1}')
	NETIP=$(route -n | grep eth0 | awk -F" " '{print $1}') && NETIP=$(echo $NETIP | cut -f1 -d" ")
	echo "default 0.0.0.0" > /etc/networks
	echo "loopback 127.0.0.0" >> /etc/networks
	echo "link-local 169.254.0.0" >> /etc/networks
	echo "localnet $NETIP" >> /etc/networks
	#route

	#enlace si iniciamos desde ogprotocolo=local { cdrom, usb, cache } .
    # monta el raiz del dispositivo local en /opt/og2fs/tftpboot  - acceso al fichero .sqfs
    # y monta el sistema root sqfs en /opt/og2fs/2ndfs
	[ "$LOCALMEDIA" == "CACHE" ] && ln -s /opt/og2fs/tftpboot /opt/opengnsys/cache
	[ "$ogprotocol" == "local" ] &&  ln -s /opt/og2fs/2ndfs/opt/opengnsys/* /opt/opengnsys/


}




ogGetROOTSERVER ()
{
	# get nfs root from dhcp
	if [ "x${NFSROOT}" = "xauto" ]; then
		# check if server ip is part of dhcp root-path
		if [ "${ROOTPATH#*:}" = "${ROOTPATH}" ]; then
			NFSROOT=${ROOTSERVER}:${ROOTPATH}
		else
			NFSROOT=${ROOTPATH}
		fi

	# nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
	elif [ -n "${NFSROOT}" ]; then
		# nfs options are an optional arg
		if [ "${NFSROOT#*,}" != "${NFSROOT}" ]; then
			NFSOPTS="-o ${NFSROOT#*,}"
		fi
		NFSROOT=${NFSROOT%%,*}
		if [ "${NFSROOT#*:}" = "$NFSROOT" ]; then
			NFSROOT=${ROOTSERVER}:${NFSROOT}
		fi
	fi
	export ROOTSERVER
	echo "ROOTSERVER=$ROOTSERVER" >> $CFGINITRD
return 0
}	

ogConectROOTSERVER ()
{
local OPTIONS
#params a detectar
if [ $ogrepo ]
then
	# Validar si la ip es correcta
	ROOTREPO=$ogrepo
else
	ROOTREPO=$ROOTSERVER
fi

case "$ogprotocol" in
	local)
		echo  "Montar imagen del sistema root desde dispositivo local"
		for i in $(blkid /dev/s* | grep ogClient | awk -F: '{print $2}' | tr -d \"); do export $i; done
		mount -t $TYPE LABEL=$LABEL $LOCALROOTBOOT
		if [ $? != 0 ]
		then
			mount -t reiserfs LABEL=CACHE $LOCALROOTBOOT
			export LOCALMEDIA=CACHE
		fi
		;;    
	httfs)
		echo "protocolo httfs aun no soportado"
		;;
	sshfs)
		echo "protocolo sshfs aun no soportado"
		;;
	smb)    
		echo "Preparando conexión con el Repositorio $ROOTSERVER por $ogprotocol"
		OPTIONS=" -o user=opengnsys,pass=og"
		mount.cifs //${ROOTSERVER}/${SMBCLIENTDIR} $LOCALCLIENTDIR $OPTIONS 
		mount.cifs //${ROOTSERVER}/${SMBLOGDIR} $LOCALLOGDIR $OPTIONS 
		mount.cifs //${ROOTSERVER}/${SMBROOTBOOT} $LOCALROOTBOOT $OPTIONS 
		mount.cifs //${ROOTREPO}/${SMBIMGDIR} $LOCALIMGDIR ${OPTIONS},ro 
		;;
	nfs)
		echo "Preparando conexión con el Repositorio $ROOTSERVER por $ogprotocol"
		nfsmount -o nolock,ro $ROOTSERVER:$NFSCLIENTDIR $LOCALCLIENTDIR
		nfsmount -o nolock $ROOTSERVER:$NFSLOGDIR $LOCALLOGDIR
		nfsmount -o nolock $ROOTSERVER:$NFSROOTBOOT $LOCALROOTBOOT
		nfsmount -o nolock,ro $ROOTREPO:$NFSIMGDIR $LOCALIMGDIR
		;;
esac
}

ogMerge2ndFile()
{
if [ -f $LOCALROOTBOOT/ogclient/ogclient.sqfs ]
then	
	cat /proc/mounts > /tmp/mtab.preunion
	if [ "$og2nd" == "img" ]
	then
		#para acceder al img
		losetup /dev/loop0 $LOCALROOTBOOT/ogclient/ogclient.img -o 32256
		mount /dev/loop0 $LOCALROOTIMG
	else
		## para acceder al squashfs
		mount $LOCALROOTBOOT/ogclient/ogclient.sqfs $LOCALROOTIMG -t squashfs -o loop
	fi
	for i in etc var lib bin sbin usr root boot; do
		unionmount $i
	done
	cat /tmp/mtab.preunion > /etc/mtab
else
	echo "Fichero imagen del cliente no encontrado"
	return 1
fi
}


unionmount()
{
	tmpdir=/$1		#dir
	FUSE_OPT="-o default_permissions -o allow_other -o use_ino -o nonempty -o suid"
	UNION_OPT="-o cow -o noinitgroups"
	UBIN="unionfs-fuse"
					#UPATH="/unionfs"
					#LOCALROOTIMG="/opt/og2fs/2ndfs"	
					#LOCALROOTRAM="/opt/og2fs/1stfs"		#/unionfs/host	#punto de montaje para unionfs
					#LOCALROOTUNION=/opt/og2fs/unionfs/"	#/unionfs/union	#punto de union entreo LOCALROOTIMG y LOCALROOTRAM
					#mkdir -p $LOCALROOTRAM   			 #/unionfs/host
					#mkdir -p $LOCALROOTUNION 			  #/unionfs/union
	mkdir -p $LOCALROOTRAM$tmpdir
	#mount --bind /$tmpdir $LOCALROOTRAM$tmpdir
	U1STDIR="${LOCALROOTRAM}${tmpdir}=RW"
	U2NDDIR="${LOCALROOTIMG}${tmpdir}=RO"
	UNIONDIR=$LOCALROOTUNION$tmpdir
	mkdir -p $UNIONDIR
	$UBIN $FUSE_OPT $UNION_OPT ${U1STDIR}:${U2NDDIR} $UNIONDIR
	mount --bind  $UNIONDIR $tmpdir
}


unionmountOLD()
{
	FUSE_OPT="-o default_permissions -o allow_other -o use_ino -o nonempty -o suid"
	UNION_OPT="-o cow -o noinitgroups"
	UPATH="/unionfs"
	UBIN="unionfs-fuse"
	mkdir -p /unionfs/host
	mkdir -p /unionfs/union
	dir=$1
	mkdir -p /unionfs/host/$dir
	#mount --bind /$dir /unionfs/host/$dir
	mkdir -p /unionfs/union/$dir
	host="/unionfs/host/${dir}=RW"
	common="/opt/og2fs/${dir}=RO"
	$UBIN $FUSE_OPT $UNION_OPT ${host}:${common} /unionfs/union/$dir
	mount --bind  /unionfs/union/$dir /$dir
}

ogconfigure_lo()
{
# for the portmapper we need localhost
ifconfig lo 127.0.0.1
#/etc/init.d/portmap start
}

ogconfigure_networking()
{
#echo "ogconfigure_networking: Buscando interfaz a configurar DEVICE"
if [ -n "${BOOTIF}" ] 
then
	#echo " variable BOOTIF exportada con pxelinux.0 con valor $BOOTIF"
	IP=$IPOPTS
	temp_mac=${BOOTIF#*-}
	# convert to typical mac address format by replacing "-" with ":"
	bootif_mac=""
	IFS='-'
	for x in $temp_mac ; do
		if [ -z "$bootif_mac" ]; then
        bootif_mac="$x"
        else
        	bootif_mac="$x:$bootif_mac"
        fi
	done
	unset IFS
	# look for devices with matching mac address, and set DEVICE to
	# appropriate value if match is found.
	for device in /sys/class/net/* ; do
		if [ -f "$device/address" ]; then
			current_mac=$(cat "$device/address")
			if [ "$bootif_mac" = "$current_mac" ]; then
				DEVICE=${device##*/}
				break
			fi
		fi
	done
else
	#echo "variable BOOTIF no exportada, intentamos detectar que interfaz se ha iniciado"
	IP=$ip
	#TODO Detectar que interfaz se ha iniciado
	case ${IP} in
		none|off)
           return 0
        ;;
        ""|on|any)
          # Bring up device
          DEVICE=eth0
        ;;
        dhcp|bootp|rarp|both)
          DEVICE=eth0
        ;;
        *)
          DEVICE=`echo $IP | cut -f6 -d:`
        ;;
	esac
fi
if [ -z "${DEVICE}" ]; then
	echo "variable DEVICE con valor $DEVICE no encontrada, llamamos de nuevo a ogconfigure_networking"
	ogconfigure_networking
fi

[ -n "${DEVICE}" ] && [ -e /tmp/net-"${DEVICE}".conf ] && return 0
#if [ -n "${DEVICE}" ] && [ -e /tmp/net-"${DEVICE}".conf ]; then 
#	echo "variable DEVICE con valor $DEVICE  y fichero /tmp/net-$DEVICE encontrados"
#	return 0
#else
#	echo "variable DEVICE con valor $DEVICE encontrada, procedemos a configurala y a crear el fichero /tmp/net-$DEVICE"
#fi

# Activamos la interfaz antes de configurar.
ip address flush $DEVICE
ip link set dev $DEVICE up
# Si no se detecta señal portadora volver a configurar.
sleep 1
CARRIER=$(cat /sys/class/net/${DEVICE}/carrier)
if [ "$CARRIER" != "1" ]
then
	ogconfigure_networking
fi

# support ip options see linux sources
# Documentation/filesystems/nfsroot.txt
# Documentation/frv/booting.txt
for ROUNDTTT in 2 3 4 6 9 16 25 36 64 100; do
	# The NIC is to be configured if this file does not exist.
	# Ip-Config tries to create this file and when it succeds
	# creating the file, ipconfig is not run again.
	if [ -e /tmp/net-"${DEVICE}".conf ]; then
		break;
	fi
	case ${IP} in
		none|off)
			return 0
		;;
		""|on|any)
			# Bring up device
			echo "Setting $DEVICE  with option:on|any and Variable IP= $IP: ipconfig -t ${ROUNDTTT} ${DEVICE} "
			ipconfig -t ${ROUNDTTT} ${DEVICE}
		;;
		dhcp|bootp|rarp|both)
			echo "Setting $DEVICE with option:dhcp|bootp|rarp|both and Variable IP=  $IP: ipconfig -t ${ROUNDTTT} -c ${IP} -d ${DEVICE} "
			ipconfig -t ${ROUNDTTT} -c ${IP} -d ${DEVICE}
		;;
		*)
			echo "Setting $DEVICE with option *  and Variable IP= $IP: ipconfig -t ${ROUNDTTT} -d $IP  "
			ipconfig -t ${ROUNDTTT} -d $IP
			# grab device entry from ip option
			NEW_DEVICE=${IP#*:*:*:*:*:*}
			if [ "${NEW_DEVICE}" != "${IP}" ]; then
				NEW_DEVICE=${NEW_DEVICE%:*}
			else
				# wrong parse, possibly only a partial string
				NEW_DEVICE=
			fi
			if [ -n "${NEW_DEVICE}" ]; then
				DEVICE="${NEW_DEVICE}"
			fi
		;;
	esac
done

# source ipconfig output
if [ -n "${DEVICE}" ]; then	
    . /tmp/net-${DEVICE}.conf
    DEVICECFG="/tmp/net-${DEVICE}"
	export DEVICECFG
	export DEVICE
	echo "DEVICE=$DEVICE" >> $CFGINITRD
	echo "DEVICECFG=$DEVICECFG" >> $CFGINITRD
	echo "exportando variable DEVICE con valor = $DEVICE y el DEVICECFG con valor $DEVICECFG"    
else
    # source any interface as not exaclty specified
    . /tmp/net-*.conf
fi
}

   #####################################################################
# Ask yesno question.
#
# Usage: yesno OPTIONS QUESTION
#
#   Options:
#     --timeout N    Timeout if no input seen in N seconds.
#     --default ANS  Use ANS as the default answer on timeout or
#                    if an empty answer is provided.
#
# Exit status is the answer.  0=yes 1=no

ogYesNo()
{
    local ans
    local ok=0
    local timeout=0
    local default
    local t

    while [[ "$1" ]]
    do
        case "$1" in
        --default)
            shift
            default=$1
            if [[ ! "$default" ]]; then error "Missing default value"; fi
            t=$(echo $default | tr '[:upper:]' '[:lower:]')

            if [[ "$t" != 'y'  &&  "$t" != 'yes'  &&  "$t" != 'n'  &&  "$t" != 'no' ]]; then
                error "Illegal default answer: $default"
            fi
            default=$t
            shift
            ;;

        --timeout)
            shift
            timeout=$1
            if [[ ! "$timeout" ]]; then error "Missing timeout value"; fi
            #if [[ ! "$timeout" =~ ^[0-9][0-9]*$ ]]; then error "Illegal timeout value: $timeout"; fi
            shift
            ;;

        -*)
            error "Unrecognized option: $1"
            ;;

        *)
            break
            ;;
        esac
    done

    if [[ $timeout -ne 0  &&  ! "$default" ]]; then
        error "Non-zero timeout requires a default answer"
    fi

    if [[ ! "$*" ]]; then error "Missing question"; fi

    while [[ $ok -eq 0 ]]
    do
        if [[ $timeout -ne 0 ]]; then
            if ! read -t $timeout -p "$*" ans; then
                ans=$default
            else
                # Turn off timeout if answer entered.
                timeout=0
                if [[ ! "$ans" ]]; then ans=$default; fi
            fi
        else
            read -p "$*" ans
            if [[ ! "$ans" ]]; then
                ans=$default
            else
                ans=$(echo $ans | tr '[:upper:]' '[:lower:]')
            fi 
        fi

        if [[ "$ans" == 'y'  ||  "$ans" == 'yes'  ||  "$ans" == 'n'  ||  "$ans" == 'no' ]]; then
            ok=1
        fi

        if [[ $ok -eq 0 ]]; then warning "Valid answers are: yes y no n"; fi
    done
    [[ "$ans" = "y" || "$ans" == "yes" ]]
}
     

