#!/bin/bash
#
# Author: leon@leonsio.com
# Licence: BSD
# Version: 1.0
#

# Basic paths
SHELL_API=/bin/cli-shell-api
vyatta_sbindir=/opt/vyatta/sbin
dhcp_map_file=/config/dhcpd_static.map

# Basic commands
SET=${vyatta_sbindir}/my_set
DELETE=${vyatta_sbindir}/my_delete
COPY=${vyatta_sbindir}/my_copy
MOVE=${vyatta_sbindir}/my_move
RENAME=${vyatta_sbindir}/my_rename
ACTIVATE=${vyatta_sbindir}/my_activate
DEACTIVATE=${vyatta_sbindir}/my_activate
COMMENT=${vyatta_sbindir}/my_comment
COMMIT=${vyatta_sbindir}/my_commit
DISCARD=${vyatta_sbindir}/my_discard
SAVE=${vyatta_sbindir}/vyatta-save-config.pl

# Some arrays
declare -A STATIC_HOSTS
declare -A STATIC_DHCP
declare -A STATIC_DOMAIN
declare -A HOST_ADD
declare -A HOST_DELETE
declare -A HOST_CHANGE

# Init session
session_env=$($SHELL_API getSessionEnv $PPID)
eval $session_env
$SHELL_API setupSession

# Check session
$SHELL_API inSession
if [ $? -ne 0 ]; then
	echo "Can not init session"
	exit 1
fi

# Part 1: Get all static host mappings
host_map_list=$($SHELL_API listNodes system static-host-mapping host-name)
eval "HOSTS=($host_map_list)"

for host in "${HOSTS[@]}";
  do
	host_ip=$($SHELL_API returnValue system static-host-mapping host-name $host inet)
	STATIC_HOSTS[$host]=$host_ip
  done

# Part 2: Get DHCP static leases
dhcp_networks=$($SHELL_API listNodes service dhcp-server shared-network-name)
eval "DHCP_NETWORKS=($dhcp_networks)"

for network in "${DHCP_NETWORKS[@]}";
  do
	# 2.1 get subnets
	dhcp_subnets=$($SHELL_API listNodes service dhcp-server shared-network-name $network subnet)
	eval "DHCP_SUBNETS=($dhcp_subnets)"
	for subnet in "${DHCP_SUBNETS[@]}";
	do
		# 2.2 entries
		dhcp_static_leases=$($SHELL_API listNodes service dhcp-server shared-network-name $network subnet $subnet static-mapping)
		eval "DHCP_STATIC_LEASES=($dhcp_static_leases)"
		for host_name in "${DHCP_STATIC_LEASES[@]}";
		do
			#  2.3 host (str to lower)
			host_ip=$($SHELL_API returnValue service dhcp-server shared-network-name $network subnet $subnet static-mapping $host_name ip-address)
			STATIC_DHCP[${host_name}]=$host_ip
			
			host_domain=$($SHELL_API returnValue service dhcp-server shared-network-name $network subnet $subnet domain-name)
			STATIC_DOMAIN[${host_name}]=$host_domain
		done
	done
  done

# Part 3 search for differences between STATIC_DHCP and STATIC_HOSTS
for key in "${!STATIC_DHCP[@]}"
do
	value=${STATIC_DHCP[$key]}
	# 3.1 Search for host entry
	if [[ ${STATIC_HOSTS[$key]} ]]; then
		# 3.2 search for changes between entries
		if [[ ${STATIC_HOSTS[$key]} != ${STATIC_DHCP[$key]} ]]; then
			HOST_CHANGE[$key]=$value
		fi
    	else # 3.3 search for new entries
		HOST_ADD[$key]=$value
    	fi
done

# Part 4 read old leases and search for deleted entries
# 4.1 load old static leases
if [ -f $dhcp_map_file ]; then
	mapfile -t dhcp_static_map < "$dhcp_map_file"
else
	declare -A dhcp_static_map
fi
for dhcp_static_entry in "${dhcp_static_map[@]}"
  do
	value=${STATIC_DHCP[$dhcp_static_entry]}
	# 4.2 search for new/deleted entries
	if ! [[ ${STATIC_DHCP[$dhcp_static_entry]} ]]; then
		#  4.3 entry is old STATIC_DHCP entry and must be deleted from hosts list
		if [[ ${STATIC_HOSTS[$dhcp_static_entry]} ]]; then
			HOST_DELETE[$dhcp_static_entry]=$dhcp_static_entry
		fi
	fi
  done
# Part 5 commit changes
# 5.1 add new entries
write_changes=0
for host in "${!HOST_ADD[@]}"
  do
	domain=${STATIC_DOMAIN[${host_name}]}
	fqdn=$host.$domain
	$SET system static-host-mapping host-name $host inet ${HOST_ADD[$host]}
	if [ -n "$domain" ]; then
	$SET system static-host-mapping host-name $host alias $fqdn
	fi
	if [ $? -ne 0 ]; then
        	echo "SET Failed, abort :("
        	exit 1
	fi
	write_changes=1
  done
# 5.2 write changes
for host in "${!HOST_CHANGE[@]}"
  do
        $SET system static-host-mapping host-name $host inet ${HOST_CHANGE[$host]} alias $host.$domain
	if [ $? -ne 0 ]; then
        	echo "SET Failed, abort :("
        	exit 1
	fi
	write_changes=1
  done
# 5.3 delete old values
for host in "${!HOST_DELETE[@]}"
  do
        $DELETE system static-host-mapping host-name $host
        if [ $? -ne 0 ]; then
                echo "SET Failed, abort :("
                exit 1
        fi
	write_changes=1
  done
# only if we have some changes
if [[ $write_changes == 1 ]]; then
	# 5.4 commit changes
	$COMMIT
	# 5.5 save changes
	$SAVE
fi
#  Part 6 save new dhcp static map to file
rm -rf $dhcp_map_file
for host in "${!STATIC_DHCP[@]}"
do
	echo $host >> $dhcp_map_file
done
