#!/bin/bash

### Include ymclibnettools
. /usr/lib/lib-fliwi/ymc-networktools.bash

if [ $(ymc_is_chroot) -ne 0 ]; then
  echo "WARNING: $0 can not be run inside a chroot..."
  exit 0
fi

##########################
function ymc_script_help
{
  echo ""
  echo "Update the network configuration on a node in Fliwi"
  echo ""
  echo "Usage: $(basename $0) [OPTIONS]"
  echo "====="
  echo ""
  echo "OPTIONS:"
  echo "========"
  echo "--auto"
  echo "  Network configuration is (tried to be) detected automatically."
  echo ""
  echo "--allow-network-disruption"
  echo "  Some operations need to shutdown networking to success."
  echo "  Default is to skip those operations, meaning those will not be"
  echo "  executed without this option set."
  echo ""
  echo "--hostname=<someString>"
  echo "  Overrides the hostname used in automatic detection of settings."
  echo "  Default is to use the local short hostname, as detected by"
  echo "  lib-ymc-networktools (ymc_get_local_short_hostname)."
  echo ""
  echo ""
  echo "DEBUGGING OPTIONS:"
  echo "=================="
  echo "NOTE: The following are most likely only useful for debugging purposes."
  echo "      Try not to use them on any productive environment!"
  echo ""
  echo "--nameserver=<someIP>"
  echo "  Overrides the nameserver used in automatic detection of settings."
  echo "  Default is to use the systems default nameservers."
  echo ""
  echo "--allow-dummy-interfaces"
  echo "  Do not ignore interfaces using driver 'dummy' when detecting real"
  echo "  network interfaces. Default is to ignore dummy network interfaces."
  echo ""
}

function ymc_initialise_script
{
  help=$(echo "$*" | grep -c '\--help')
  auto=$(echo "$*" | grep -c '\--auto')
  ALLOW_NETWORK_DISRUPTION=$(echo "$*" | grep -c '\--allow-network-disruption')
  hostname=$(echo "$*" | grep -E -e '--hostname=' | perl -pi -e 's/.*--hostname=([^ ]+).*/$1/')
  if [ "$hostname" == '' ]; then
    hostname=$(ymc_get_local_short_hostname)
  fi
  DEBUG_DNS=$(echo "$*" | grep -E -e '--nameserver=' | perl -pi -e 's/.*--nameserver=([^ ]+).*/$1/')
  DEBUG_ALLOW_DUMMY_INTERFACES=$(echo "$*" | grep -c '\--allow-dummy-interfaces')

  if [ "$1" == '' ] || [ $help -eq 1 ]; then
    ymc_script_help 1>&2
    exit 1
  fi

  if [ "$SSH_CONNECTION" != '' ] && \
     [ $ALLOW_NETWORK_DISRUPTION -ne 0 ]; then
    ### TODO: Take a closer look int $SSH_CONNECTION to determine if we will drop a needed connection (e.g.: to only show this warning in that case)
    dialog --clear \
           --title "WARNING" \
           --yes-label "CONTINUE" \
           --no-label "ABORT" \
           --defaultno \
           --yesno "WARNING: I detected that you are currently using a ssh-connection. \
                  \n         This connection will go down as the network interfaces \
                  \n         have to be renamed.\
                  \n \
                  \n ----------------------------------------------------------------- \
                  \n PLEASE DO NOT CONTINUE unless you really know what you are about! \
                  \n ----------------------------------------------------------------- \
                  \n \
                  \n Instead you should get access to this machine over a connection,\
                  \n that doesn't depend on networking or at least runs over an \
                  \n interface which doesn't have to be renamed." 15 72
    if [ $? -ne 0 ]; then
      clear
      echo ""
      echo "   --------------------------------------------------"
      echo "  |                     CANCELED                     |"
      echo "   --------------------------------------------------"
      echo "    To (re-)configure the networking run:"
      echo "    # $(basename $0) $*"
      echo ""
      exit 1
    fi
  fi

  if [ $auto -eq 0 ]; then
    echo "ERROR: The option --auto has to be given (see: --help)" 1>&2
    exit 1
  fi
}






ymc_initialise_script $*


#echo "dns|$DEBUG_DNS|"
#echo "host|$hostname|"
#echo "auto|$auto|"
#echo "allow_network_disruption|$allow_network_disruption|"

ymc_get_auto_network_config


### ToDo: Make the validation working on other networks than 'lan' and 'www', too //FF

num_configured_lan_interfaces=$(echo "$lan_interfaces" | wc -w)
num_configured_www_interfaces=$(echo "$www_interfaces" | wc -w)

### Check if a least one interface is configured for LAN
if [ $num_configured_lan_interfaces -lt 1 ]; then
  echo "ERROR: The 'LAN'-network has no interfaces configured on this machine" 1>&2
  exit 1
fi

#### Check if the configuration allows the machine to connect to the internet
#if [ $num_configured_www_interfaces -lt 1 ] && [ "$lan_gateway" == '' ]; then
#  echo "WARNING: This machine will not be able to access the internet, as neither'" 1>&2
#  echo "         an interface for the 'WWW'-network nor a gateway for the" 1>&2
#  echo "         'LAN'-network is configured." 1>&2
#fi

### Check if only one gateway has been configured
if [ "$lan_gateway" != '' ] && [ "$www_gateway" != '' ]; then
  echo "ERROR: More than one gateway is configured on this machine" 1>&2
  exit 1
fi

### Check if LAN has IP-addresses configured
if [ "$lan_ip" == '' ] || [ "$lan_netmask" == '' ]; then
  echo "ERROR: The 'LAN'-network has no valid IP-setup on this machine" 1>&2
  exit 1
fi

### Check if WWW has IP-addresses configured
if [ $num_configured_www_interfaces -gt 0 ]; then
  if [ "$www_ip" == '' ] || [ "$www_netmask" == '' ] || [ "$www_gateway" == '' ]; then
    echo "ERROR: The 'WWW'-network has no valid IP-setup on this machine" 1>&2
    exit 1
  fi
fi


for all_network in $all_networks
do
  ymc_preload_network_layouts $all_network
done


### IPv4-forwarding
echo "# Dynamic sysctl.conf(5) file for sysctl(8) generated by $(basename $0)" > /etc/sysctl.d/fliwi-network-config.conf
echo "#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN" >> /etc/sysctl.d/fliwi-network-config.conf
echo "net.ipv4.ip_forward=$ipv4_forwarding" >> /etc/sysctl.d/fliwi-network-config.conf
/etc/init.d/procps restart


ymc_rename_interfaces $if_rename

### Wash out non-existing interfaces
real_interfaces=$(ymc_get_real_interfaces)
mismatch_in_interfaces=0
for all_network in $all_networks
do
  temp_network_configured=0
  if [ -n "$(ymc_var_value $all_network'_vlan_raw_interfaces')" ]; then
    interfaces_var_name=$all_network'_vlan_raw_interfaces'
  else
    interfaces_var_name=$all_network'_interfaces'
  fi
  temp_interfaces=$(ymc_var_value $interfaces_var_name)
  temp_num_interfaces=$(echo "$temp_interfaces" | wc -w)
  ymc_set_var_content $interfaces_var_name ''
  for interface in $temp_interfaces
  do
    if [ $(ymc_contains "$interface" $real_interfaces) -eq 1 ]; then
      ymc_set_var_content $interfaces_var_name "$(ymc_var_value $interfaces_var_name) $interface"
      temp_network_configured=1
    fi
  done

  ### This adds support for (single) bridges without any real interface...
  if [ $temp_num_interfaces -eq 0 ] && \
     [ "$(ymc_var_value $all_network'_layout')" == 'single_bridge' ]; then
    temp_network_configured=1
  fi

  if [ $temp_network_configured -eq 1 ]; then
    if [ $(echo "$(ymc_var_value $interfaces_var_name)" | wc -w) -ne $temp_num_interfaces ]; then
      echo "ERROR: There is a mismatch between the configured and the actually existing interfaces." 1>&2
      echo "       $all_network (configured): $temp_interfaces" 1>&2
      echo "       $all_network (existing)  : $(ymc_var_value $interfaces_var_name)" 1>&2
      mismatch_in_interfaces=$(expr $mismatch_in_interfaces + 1)
    fi

    ### Define the networks we will configure for this server
    configured_networks=$configured_networks" "$all_network
  fi
done

## Check if we really have all the configured interfaces available
if [ $mismatch_in_interfaces -gt 0 ]; then
  echo "ERROR: There are $mismatch_in_interfaces mismatch(es) between the configured and the actually existing interfaces." 1>&2
  echo "       ABORTING!" 1>&2
  exit 1
fi


### Check if have the correct min/max numbers of interfaces configured for the different layouts
for network in $configured_networks
do
  network_layout=$(ymc_var_value $network"_layout")
  interfaces=$(ymc_var_value $network"_interfaces")
  num_interfaces=$(echo "$interfaces" | wc -w)

  case "$network_layout" in
    single)
      if [ $num_interfaces -ne 1 ]; then
        echo "ERROR: The '$network'-network has layout '$network_layout' but doesn't use exactly one interface for that..." 1>&2
        exit 1
      fi

      if [ "$network" != "$interfaces" ]; then
        echo "ERROR: The single interface '$interfaces' has to be named as '$network'" 1>&2
        exit 1
      fi
    ;;

    single_bridge)
      if [ $num_interfaces -gt 1 ]; then
        echo "ERROR: The '$network'-network has layout '$network_layout' but doesn't use more than one interface for that..." 1>&2
        exit 1
      fi

      if [ "$network" == "$interfaces" ]; then
        echo "ERROR: The single bridge interface '$interfaces' can not be named as '$network'" 1>&2
        exit 1
      fi
    ;;

    bonding|bonding_bridge)
      if [ $num_interfaces -lt 2 ]; then
        echo "WARNING: The '$network'-network has layout '$network_layout' but doesn't use at least two interface for that..." 1>&2
        #exit 1
      fi
    ;;

    *)
      echo "ERROR: The '$network'-network uses an unknown layout '$network_layout'..." 1>&2
      exit 1
    ;;
  esac
done

### RESET /etc/network/interfaces AND write some basics into it
ymc_write_interfaces_header

### SETUP vlan raw interfaces
ymc_activate_vlan_raw_interfaces $configured_networks

### SETUP real non-single interfaces
ymc_activate_non_single_interfaces $configured_networks

### SETUP bonding
ymc_activate_bonding $configured_networks

### SETUP bridging
ymc_activate_bridging $configured_networks

### SETUP real single interfaces
ymc_activate_single_interfaces $configured_networks


exit 0
