#!/bin/bash
#
# Script for automated cloning and renaming of FUSS 10 and 12 client
# computers using mac-address as unique identifier.
#
# Copyright (C) 2005-2023 FUSS Project <info@fuss.bz.it>
#
# Authors:
#   Donato Florio <>
#   Marco Marinello <mmarinello@fuss.bz.it
#   Paolo Dongilli <dongilli@fuss.bz.it>
#   Elena Grandi <elena@truelite.it>
#   Simone Piccardi <piccardi@truelite.it>
#   Claudio Cavalli <ccavalli@fuss.bz.it>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#
# PRT 1 ---------------------------

service ssh start

getNetStuff(){
    if [ $1 -eq 1 ];then
	ls /sys/class/net/ -1 | grep -v lo | grep -v "^w"
    else
	cat /sys/class/net/$(getNetStuff 1)/address
    fi
}

getDisk(){
    # lsblk -d -l -o NAME,SIZE,MODEL,TYPE,RM
    # I campi sono: $1=NAME, $2=SIZE, $3..$NF-2=MODEL, $NF-1=TYPE, $NF=RM
    deviceSize=$(
        lsblk -d -l -o NAME,SIZE,MODEL,TYPE,RM | awk '
            # Filtro: Solo dischi fissi (TYPE e RM)
            $NF == 0 && $(NF-1) == "disk" {            
                name = $1
                size = sprintf("%-7s", $2) 
                
                # Ricostruisce il MODEL gestendo gli spazi al suo interno
                model = ""
                for (i = 3; i <= NF-2; i++) {
                    model = model $i (i == NF-2 ? "" : " ")
                }
                
                # Unisce SIZE e MODEL, sostituendo gli spazi con '_' per dialog
                description_clean = gensub(/ /, "_", "g", size " " model)
                
                # Stampa nel formato richiesto da dialog: KEY "DESCRIPTION"
                print name, description_clean
            }'
    )
    
    # installDevice contiene tutti i nomi dei dischi (KEYS) che sono stati trovati
    installDevice="$(awk '{print $1}' <<< "$deviceSize")"
}

getDisk

if [ -z "$installDevice" ]; then
    echo "WARNING! This computer appears to have no disk!"
    echo ""
    sleep 2
    poweroff
elif [ $(echo $installDevice | wc -w) -gt 1 ]; then
    echo "WARNING! This computer appears to have more than one disk!"
    echo ""
    sleep 2
    terminated=false
    while ! $terminated; do
        diskVar=$(dialog --title "FUSS FUCC" --output-fd 1 --menu $'Choose the disk where you want to install FUSS\n\n\n' 10 60 4 $deviceSize)
        if [ $? -eq 0 ]; then
	    terminated=true
	else
	    reboot
	fi
    done
else
    diskVar="$(echo $installDevice | tr -d [:blank:])"
fi

getRootPartitionFuss(){
    for i in $(lsblk -lp | grep part | grep -iv swap | awk '{print $1}')
    do
	mount $i /mnt
	if [ -d "/mnt/etc/fuss-client" ];then
	    fussDir="$i"
	fi
	umount /mnt
    done
    echo "$fussDir"
}

getImages(){
    for i in $(ls /home/partimag)
    do
	list="$(ls /home/partimag/$i/clonezilla-img 2>/dev/null | cut -d "/" -f 4) $list"
    done

    for j in $list
    do
        nrList="$j - $nrList"
    done

    echo $nrList
}

# Function that returns True if the string does not belong to any list element
string_not_belongs() {
    string="$1"
    list=("join" "standalone" "light" "locale" "keyboard" "wifi")

    for i in "${list[@]}"; do
        if [[ "$i" == "$string" ]]; then
            return 1  # Return False if the string belongs to at least one element in the list
        fi
    done

    return 0  # Return True if the string does not belong to any list element
}


mountPoint="/mnt"
computerList="/home/partimag/computerList.txt"
wificonf="/home/partimag/clientScripts/wireless_conf"
macAddress=$(getNetStuff 2)

# Make a local copy of /etc/clusters
scp -o IdentityFile=/home/clonezilla/.ssh/id_rsa -o StrictHostKeyChecking=no clonezilla@proxy:/etc/clusters /tmp/clusters

# Count the number of occurrences of macAddress in computerList.
number_occurrence=$(grep -c "$macAddress" $computerList)

# Check if there are more than one occurrences and delete all occurrences
if [ $number_occurrence -gt 1 ]; then
    sed -Ei "s/.*\s*${macAddress}\s+.*//g" $computerList && sed -i "/^$/d" $computerList
fi

if ! grep $macAddress $computerList; then
    dialog --title "FUSS FUCC" --msgbox "Hi,\nunfortunatley, there is no valid configuration to setup this computer. Please go through the next few steps
to configure how to install this PC.\nPlease make sure that the file /home/clonezilla/computerList.txt is owned and writable by clonezilla, otherwise we'll not be able to save the information you're going to enter." 13 70
    finished=false
    while ! $finished; do
        host_exists=0
        hostname=$(dialog --title "FUSS FUCC" --inputbox "Please, pick a HOSTNAME for this PC" --output-fd 1 10 70)
        if [ $? -eq 0 ]; then
	    if [ "$hostname" != "" ]; then
                grep -rw /tmp/clusters -e $hostname
                if [ $? -eq 0 ]; then
                    host_exists=1
                    cont=0
                    if dialog --title "FUSS FUCC" --defaultno --yesno "This hostname is already present in /etc/clusters \nDo you want to continue?" 13 70; then
                        cont=1
                    fi
                fi
                if [ $host_exists -eq 0 ] || ( [ $host_exists -eq 1 ] && [ $cont -eq  1 ] ); then
                finished=true
	        fi
            fi
        else
	    reboot
        fi
    done

    terminated=false
    while ! $terminated; do
        img=$(dialog --title "FUSS FUCC" --output-fd 1 --menu "Choose an image to be installed" 15 50 4 $(getImages))
        if [ $? -eq 0 ]; then
	    if [ "$img" != "" ]; then
	        terminated=true
	    fi
	else
	    reboot
	fi
    done

    if dialog --title "FUSS FUCC" --yesno "Join this client to the FUSS domain?" 13 70; then
        join="join "
	join_="yes"

        completed=false
        while ! $completed; do

            # Execute the dialog command to create the radiolist cluster dialog
            COUNTER=2
            RADIOLIST="New_cluster 1 \n"  # variable where we will keep the list entries for radiolist dialog
            for i in $(cat /tmp/clusters | cut -d " " -f 1 ) ; do
                RADIOLIST="$RADIOLIST $i $COUNTER \n"
                let COUNTER=COUNTER+1
            done

            selected=$(dialog --backtitle "Select Cluster PC" \
            --radiolist "You can use the UP/DOWN arrow keys or the \nfirst letter of the choice as a hot key. \
            \n\nPress SPACE to toggle an option on/off. \n " \
            0 0 $COUNTER $RADIOLIST \
            2>&1 >/dev/tty)

            if [ $? -eq 0 ]; then
                # Check the exit status of the dialog command
	        echo "You selected: $selected"
	    else
	        reboot
	    fi
            if [ "$selected" != "" ] ; then
	        if [ "$selected" == "New_cluster" ]; then
                    cluster=$(dialog --title "FUSS FUCC" --inputbox "Please, pick a CLUSTER for this PC" --output-fd 1 10 70) 
                    cluster="$cluster "
		    if [ "$cluster" != "" ]; then
                        completed=true
                    fi
		else
                    cluster=$selected
		    cluster="$cluster "
	            completed=true
                fi
            else
                dialog --title "FUSS FUCC" --msgbox "No selection made." 13 70

	    fi
        done

        if dialog --title "FUSS FUCC" --defaultno --yesno "Do you want to configure a wifi network?" 13 70; then
	    wifi_="yes"
            wifi_setting="wifi" 
        else
            wifi_="no"
	fi

    else
	join=""
	join_="no"
    fi

    if [ "$join" == "" ] ; then

        if dialog --title "FUSS FUCC" --yesno "Do you want to run \"fuss-client --standalone\"? " 13 70; then
            standalone="standalone "
	    standalone_="yes"    
        else
            standalone_="no"
        fi
    fi

    if dialog --title "FUSS FUCC" --defaultno --yesno "Do you want to install in \"light\" mode? " 13 70; then
        light="light "
	light_="yes"    
    else
        light_="no"
    fi

    if dialog --title "FUSS FUCC" --defaultno --yesno "Do you want to select a new system language?" 13 70; then
        locale="locale "

        completed=false
        while ! $completed; do

            # Execute the dialog command to create the radiolist cluster dialog
            COUNTER=1
            RADIOLIST=""  # variable where we will keep the list entries for radiolist dialog
            for i in $(cat /home/partimag/clientScripts/locale.txt) ; do
                RADIOLIST="$RADIOLIST $i $COUNTER \n"
                let COUNTER=COUNTER+1
            done

            selected=$(dialog --backtitle "Select locale" \
            --radiolist "You can use the UP/DOWN arrow keys or the \nfirst letter of the choice as a hot key. \
            \n\nPress SPACE to toggle an option on/off. \n " \
            0 0 $COUNTER $RADIOLIST \
            2>&1 >/dev/tty)

            if [ $? -eq 0 ]; then
                # Check the exit status of the dialog command
                echo "You selected: $selected"
            else
                reboot
            fi
            if [ "$selected" != "" ] ; then
                selected_locale=$selected
                selected_locale="$selected_locale "
                completed=true
            else
                dialog --title "FUSS FUCC" --msgbox "No selection made." 13 70

            fi
        done
    else
        locale=""
    fi

    if dialog --title "FUSS FUCC" --defaultno --yesno "Do you want to select a new keyboard layout?" 13 70; then
        keyboard="keyboard "
        
        completed=false
        while ! $completed; do

            # Execute the dialog command to create the radiolist cluster dialog
            COUNTER=1
            RADIOLIST=""  # variable where we will keep the list entries for radiolist dialog
            for i in $(cat /home/partimag/clientScripts/keyboard_layout.txt) ; do
                RADIOLIST="$RADIOLIST $i $COUNTER \n"
                let COUNTER=COUNTER+1
            done

            selected=$(dialog --backtitle "Select locale" \
            --radiolist "You can use the UP/DOWN arrow keys or the \nfirst letter of the choice as a hot key. \
            \n\nPress SPACE to toggle an option on/off. \n " \
            0 0 $COUNTER $RADIOLIST \
            2>&1 >/dev/tty)

            if [ $? -eq 0 ]; then
                # Check the exit status of the dialog command
                echo "You selected: $selected"
            else
                reboot
            fi
            if [ "$selected" != "" ] ; then
                selected_keyboard=$selected
                selected_keyboard="$selected_keyboard "
                
                completed=true
            else
                dialog --title "FUSS FUCC" --msgbox "No selection made." 13 70

            fi
        done
    else
        keyboard=""       
    fi

    if dialog --title "FUSS FUCC" --yesno "Hostname: $hostname \nMAC: $macAddress \nImage: $img \nJoin: $join_ \nCluster: $cluster \nStandalone: $standalone_ \nLight: $light_ \nNew locale: $selected_locale \nNew keyboard: $selected_keyboard \nWifi: $wifi_ \nContinue?" 0 0; then
        host_line="$hostname $macAddress $img $join$cluster$standalone$light$locale$selected_locale$keyboard$selected_keyboard$wifi_setting"
        grep -w $computerList -e $hostname
        if [ $? -eq 0 ]; then
	    sed -Ei "s/^\s*${hostname}\s+.*//g" $computerList && sed -i "/^$/d" $computerList
	fi
	echo $host_line >> $computerList

	dialog --title "FUSS FUCC" --msgbox "Configuration completed, now start cloning." 13 70
    else
	dialog --title "FUSS FUCC" --msgbox "Will now reboot" 13 70
	reboot
	exit 0
    fi

fi

# In this part, checks are made that the parameters (join, locale, keyboard) have a correct value.

joinVar="$(cat $computerList | grep "$macAddress" | grep -E '^\s*[^[:space:]]+.*(\s)join(\s|$)')"

clusterVar="$(cat $computerList | grep "$macAddress" | grep -oPw 'join\s*\K\S+')"

standaloneVar="$(cat $computerList | grep "$macAddress" | grep -E '^\s*[^[:space:]]+.*(\s)standalone(\s|$)')"

wifiVar="$(cat $computerList | grep "$macAddress" | grep -E '^\s*[^[:space:]]+.*(\s)wifi(\s|$)')"


if [ "$joinVar" != "" ] ; then

    if ( [ "$clusterVar" == "" ] || ! string_not_belongs "$clusterVar" ) ; then

        if dialog --title "FUSS FUCC" --yesno "WARNING!!! \n\nCluster name is not valid! If you want to turn off the PC \nand fix computerList, choose Yes, otherwise choose No \nand the installation will continue without joining the server!" 13 70; then

            systemctl poweroff
        fi
    else
        clusterJoin="-g $clusterVar"
        cluster="cluster"
    fi
elif [ "$standaloneVar" != "" ]; then
    standaloneCont="standalone"
fi


if [ "$wifiVar" != "" ] ; then
    wifissidVar="$(cat $wificonf | grep wifissid |  grep -oPw 'wifissid:\s*\K\S+')"
    wifipassVar="$(cat $wificonf| grep wifipass |  grep -oPw 'wifipass:\s*\K\S+')"
    if [ $wifissidVar != "" ] && [ $wifipassVar != "" ]; then
        wifissidVar="\'$wifissidVar\'"
        wifipassVar="\'$wifipassVar\'"
        wifi="--wifi-ssid $wifissidVar --wifi-pass $wifipassVar"
    else
        wifi_ssid=$(dialog --title "FUSS FUCC" --inputbox "\nThe file /srv/clonezilla/clientScripts/wireless_conf, \
containing \nthe wifi-ssid and wifi-pass parameters, does not exist \nor parameters are empty. \nPlease, \
pick a valid WIFI SSID for this PC \nIf the box remains blank or you choose Cancel, \nthe wifi will not be configured. \n " --output-fd 1 0 0)
        if [ "$wifi_ssid" != "" ]; then
            completed=true
            wifi_ssid="\'$wifi_ssid\'"
            wifi_ssid="--wifi-ssid $wifi_ssid "
        fi

        if [ "$wifi_ssid" != "" ] ; then
            wifi_pass=$(dialog --title "FUSS FUCC" --inputbox "\nPlease, pick a valid WIFI PASSWORD for this PC" --output-fd 1 10 70)
            if [ "$wifi_pass" != "" ]; then
                completed=true
                wifi_pass="\'$wifi_pass\'"
                wifi_pass="--wifi-pass $wifi_pass "
                wifi="$wifi_ssid $wifi_pass"                    
            fi
        fi
    fi
fi

localeVar="$(cat $computerList | grep "$macAddress" |  grep -E '^\s*[^[:space:]]+.*(\s)locale(\s|$)' | grep -oPw 'locale\s*\K\S+')"


if [ "$localeVar" != "" ] && ( [ "$clusterJoin" != "" ] || [ "$standaloneCont" != "" ] ); then

    if ! grep -w "$localeVar" /home/partimag/clientScripts/locale.txt ; then

        if dialog --title "FUSS FUCC" --yesno "WARNING!!! \n\nLocale name is not valid! If you want to turn off the PC \nand fix computerList, choose Yes, otherwise choose No \nand the installation will continue without setting a new system language!" 13 70; then

            systemctl poweroff
        fi
    else
        localeVar="--locale $localeVar"
	locale="locale"
    fi
fi

keyboardVar="$(cat $computerList | grep "$macAddress" |  grep -E '^\s*[^[:space:]]+.*(\s)keyboard(\s|$)' |  grep -oPw 'keyboard\s*\K\S+')"


if [ "$keyboardVar" != "" ] && ( [ "$clusterJoin" != "" ] || [ "$standaloneCont" != "" ] ); then

    if ! grep -w "$keyboardVar" /home/partimag/clientScripts/keyboard_layout.txt ; then

        if dialog --title "FUSS FUCC" --yesno "WARNING!!! \n\nKeyboard layout name is not valid! If you want to turn off the PC \nand fix computerList, choose Yes, otherwise choose No \nand the installation will continue without setting a new keyboard layout!" 13 70; then

            systemctl poweroff
        fi

    else
        keyboardVar="--keyboard $keyboardVar"
        keyboard="keyboard"
    fi
fi


imageName=$(cat $computerList | grep "$macAddress" | awk '{print $3}')

# Comment the following line to rejoin clients without cloning (migration 2021)
ocs-sr -b -g auto -e1 auto -e2 -k1 -r -j2 -scr -p true restoredisk $imageName $diskVar
# --------------------------------------------------------------------------------

rootPartition=$(getRootPartitionFuss)

# # PRT 2 ---------------------------
mount $rootPartition $mountPoint

# Check for EFI partition and if the system was booted using UEFI.
# If confirmed, mount it and run grub-install in chroot ---------------------------

# The following line only works from bullseye onwards, when PARTTYPENAME has
# been added to lsblk.
#efiPart=$( lsblk -l -o NAME,PARTTYPENAME | grep EFI | awk '{print $1}')
efiPart=$( lsblk -l -o NAME,PARTTYPE | egrep "(0xef|c12a7328-f81f-11d2-ba4b-00a0c93ec93b)" | awk '{print $1}')

if [ $efiPart ] && [ -d /sys/firmware/efi ]; then
    mount /dev/$efiPart $mountPoint/boot/efi
    for i in /dev /dev/pts /proc /sys /sys/firmware/efi/efivars /run; do sudo mount -B $i $mountPoint$i; done
    chroot $mountPoint grub-install /dev/$diskVar
fi
# -----------------------------------------------------------------------------

currentName="$(cat $mountPoint/etc/hostname)"
newName="$(grep "$macAddress" $computerList | awk '{print $1}')"

echo "SETTING HOSTNAME"

for i in hostname hosts mailname
do
    if [ -e $mountPoint/etc/$i ]; then
	sed -ie "s/$currentName/$newName/g" $mountPoint/etc/$i
    else
	echo "The file $i is not present on this system"
    fi
done

# ###  In this part, the script checks whether
#      "fuss-client" (-a or --standalone) must be launched.
#      If so the .ssh keys are needed and also a script .....
#      A number of files will be created in /root that correspond 
#      to the various parameters of the command.
#
if [ "$joinVar" != "" ] || [ "$standaloneVar" != "" ]; then
    rsync -a /home/partimag/.ssh/ $mountPoint/root/.ssh/
    cp /root/.ssh/known_hosts $mountPoint/root/.ssh/known_hosts
    chown -R root.root $mountPoint/root/.ssh/
    cp /home/partimag/clientScripts/rc.local $mountPoint/etc/
    chmod 770 $mountPoint/etc/rc.local
    cp /home/partimag/clientScripts/clientScript $mountPoint/root/
    if [ -e /home/partimag/clientScripts/new_root_pw ] ; then
        cp /home/partimag/clientScripts/new_root_pw $mountPoint/root/
    fi
    chmod 770 $mountPoint/root/clientScript
    touch $mountPoint/root/reboot
fi

if [ "$cluster" != "" ]; then echo "$clusterJoin" > $mountPoint/root/$cluster ; fi    
   
if [ "$standaloneCont" != "" ]; then touch $mountPoint/root/$standaloneCont ; fi

lightEx="$(cat $computerList | grep "$macAddress" |  grep -E '^\s*[^[:space:]]+.*(\s)light(\s|$)')"


if [ "$lightEx" != "" ];then
    lightVar="--light"
    echo "$lightVar" > $mountPoint/root/light
fi

if [ "$locale" != "" ]; then echo "$localeVar" > $mountPoint/root/$locale ; fi

if [ "$keyboard" != "" ]; then echo "$keyboardVar" > $mountPoint/root/$keyboard ; fi

if [ "$wifi" != "" ] ; then echo "$wifi" > $mountPoint/root/wifi ; fi

# ### END of the preparation stuff

reboot
