#!/bin/sh -u

cachedir="/var/cache/alterator/net-eth"

rdelim='[[:space:]]\+'
wdelim=' '

alterator_api_version=1

. alterator-sh-functions
. alterator-net-functions
. alterator-hw-functions
. shell-config
. shell-var


list_avail_ifaces()
{
	local iface=
	list_eth | while read iface; do
		if iface_has_host_with_cache "$cachedir" "$iface"; then
			continue
		fi

		echo "$iface"
	done
}

list_bond_members()
{
	local name="$1"; shift
	local ifacedir="$(ifacedir_with_cache "$cachedir" "$name")"

	if [ -d "$ifacedir" -a "$(read_iface_option "$ifacedir" TYPE)" = "bond" ]; then
		for s in $(read_iface_host_var "$ifacedir"); do
			echo "$s"
		done
	fi
}

read_bond_iface()
{
	local name="$1"; shift
	local ifacedir="$(ifacedir_with_cache "$cachedir" "$name")"
	local bond_options=

	if [ -z "$name" ] || [ ! -d "$ifacedir" ]; then
		write_string_param "mode" "0"
		write_string_param "bond_options" ""
		return
	fi

	write_string_param "mode" "$(read_iface_option "$ifacedir" BONDMODE)"

	bond_options="$(read_iface_option "$ifacedir" BONDOPTIONS)"
	shell_var_unquote bond_options "$bond_options"
	# Remove alone space in the options
	# (it was setted by us because etcnet not allow empty BONDOPTIONS)
	if [ "$bond_options" = ' ' ]; then
		bond_options=''
	fi
	# arp_ip_target value should be prepended with '+' in the config
	# Remove it during reading
	if [ -n "$bond_options" ]; then
		bond_options="$(printf "%s" "$bond_options" | sed -r 's|arp_ip_target=\+([[:digit:].]+)|arp_ip_target=\1|')"
	fi
	write_string_param "bond_options" "$bond_options"
}

write_bond_iface()
{
	local name="$1"; shift
	local ifacedir="$cachedir/$name"
	local bond_options="$in_bond_options"

	[ -n "$name" -a -d "$ifacedir" ] || return

	write_iface_option "$ifacedir" BONDMODE "$in_mode"
	if [ -n "$bond_options" ]; then
		# arp_ip_target value should be prepended with '+' in the config
		bond_options="$(printf "%s" "$bond_options" | sed -r 's|arp_ip_target=([[:digit:].]+)|arp_ip_target=+\1|')"
	else
		# Etcnet don't allow create bond with empty options.
		# But why not? Just set it to space.
		bond_options=" "
	fi
	write_iface_option "$ifacedir" BONDOPTIONS "\"$bond_options\""
}

init_cache()
{
	local name="$1"; shift

	if [ -z "$name" ]; then
		return
	elif iface_will_removed "$cachedir" "$name"; then
		rm -r -- "$cachedir/$name/"
	elif [ -d "$cachedir/$name" ]; then
		return
	fi

	if [ -d "/etc/net/ifaces/$name" ]; then
		mkdir -p -- "$cachedir/"
		cp -a "/etc/net/ifaces/$name" "$cachedir/"
		return
	fi

	mkdir -p -- "$cachedir/$name"

	cat > "$cachedir/$name/options" <<OPTIONS_TEMPLATE
TYPE=bond
ONBOOT=yes
DISABLED=no
NM_CONTROLLED=no
CONFIG_WIRELESS=no
CONFIG_IPV4=yes
CONFIG_IPV6=no
BOOTPROTO=static
HOST=""
BONDMODE=0
BONDOPTIONS=" "
OPTIONS_TEMPLATE
}

on_message()
{
	case "$in_action" in

		list)
			case "${in__objects##*/}" in
				avail_ifaces) list_avail_ifaces | write_enum;;
			    bonded_ifaces) list_bond_members "$in_bond" | write_enum;;
			esac
			;;
		read)
			case "$in__objects" in
				/)
					read_bond_iface "$in_bond"
					;;
				new_name)
					write_string_param "new_name" "$(next_iface_with_cache "$cachedir" bond)"
					;;
			esac
			;;
		write)
			init_cache "$in_bond"

			case "$in__objects" in
				/)
					write_bond_iface "$in_bond"
					;;
				rm_bond)
					remove_host_iface_with_cache "$cachedir" "$in_bond"
					;;
				add_iface)
					host_add_slaves_with_cache "$cachedir" "$in_bond" "$in_name"
					;;
				del_iface)
					host_del_slaves_with_cache "$cachedir" "$in_bond" "$in_name"
					;;
			esac
			;;
	esac
}

message_loop
