#!/bin/sh

set -e

if [ -z "${OCI_API_URL}" ] ; then
	echo "Please add: export OCI_API_URL=\"http(s)://<url-or-IP-of-your-oci-server>/oci/api.php?\""
	echo "to your .bashrc in order to use "$(basename $0)
	echo "You may as well want to set OCI_LOGIN and OCI_PASS to be authenticated."
	exit 1
fi

usage (){
	echo $(basename $0)": configure your baremetal cluster through the OCI API."
	echo ""
	echo $(basename $0)" <action>"
	echo ""
	echo "Actions are:"
	echo "  machine-list"
	echo "  machine-destroy (remove machine from db)"
	echo "  machine-add <machine_serial> <cluster_name> <role_name> <location_name>"
	echo "  machine-remove <machine_serial>"
	echo "  machine-reboot-on-hdd <serial>"
	echo "  machine-reboot-on-live <serial>"
	echo "  machine-ipmi-reboot-on-hdd <serial>"
	echo "  machine-ipmi-reboot-on-live <serial>"
	echo "  machine-install-os <serial>"
	echo "  machine-install-log <serial>"
	echo "  machine-set-ipmi <serial> <use-ipmi:yes/no> <ipmi-ip-addr> <ipmi-port> <ipmi-username> <ipmi-password>"
	echo ""
	echo "  location-list"
	echo "  location-create <name> <swiftregion>"
	echo "  location-delete <name>"
	echo ""
	echo "  network-create <name> <ip> <cidr_mask> <location> <is-public:yes/no>"
	echo "  network-list"
	echo "  network-delete <name>"
	echo "  network-add <network_name> <cluster_name> <role_name> <iface1> <iface2>"
	echo "  network-remove <network_name>"
	echo ""
	echo "  cluster-list"
	echo "  cluster-create <name> <domaine-name.com>"
	echo "  cluster-delete <name>"
	echo "  cluster-show-networks <cluster-name>"
	echo "  cluster-show-machines <cluster-name>"
	echo "  cluster-show-ips <cluster-name>"
	echo ""
	echo "  swift-region-list"
	echo "  swift-region-create <name>"
	echo "  swift-region-delete <name>"
	echo ""
	echo "  swift-calculate-ring <cluster-name>"
	exit 0
}

# Parameter: $1 = URL param
# return: API_RESPONSE_FILE
# The function exits printing API message if status != success
ocicli_call (){
	local STATUS MESSAGE URL_PARAM
	if [ -z "${1}" ] ; then
		echo "Missing URL_PARAM when calling ocicli_call()"
		exit 1
	fi
	URL_PARAM="${1}"

	if [ -n "${OCI_LOGIN}" ] && [ -n "${OCI_PASS}" ] ; then
		URL_PARAM="${URL_PARAM}&oci_login=${OCI_LOGIN}&oci_pass=${OCI_PASS}"
	fi

	API_RESPONSE_FILE=$(mktemp -t oci-poc-install-cluster.XXXXXX)
	if [ "${DEBUG}" = "on" ] ; then
		echo "curl -s \"${OCI_API_URL}${URL_PARAM}\""
	fi
	curl -s ${OCI_API_URL}${URL_PARAM} >${API_RESPONSE_FILE}
	STATUS=$(cat ${API_RESPONSE_FILE} | jq -r '.["status"]')
	if ! [ "${STATUS}" = "success" ] ; then
		echo "Could not query API:"
		MESSAGE=$(cat ${API_RESPONSE_FILE} | jq -r '.["message"]')
		echo $MESSAGE
		rm ${API_RESPONSE_FILE}
		exit 1
	fi
}

ocicli_machine_list (){
	ocicli_call "action=machine_list"
	echo "serial,Cur_ip,memory,status,lastseen,cluster,ladvd,product_name,BIOSver,IPMIver,IPMI_IP,hostname,notes"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.product_name,.serial)|.["data"][] | "\(.serial),\(.ipaddr),\(.memory),\(.status),\(.lastseen),\(.cluster),\(.ladvd_report),\(.product_name),\(.bios_version),\(.ipmi_firmware_version),\(.ipmi_detected_ip),\(.hostname),\(.notes)"'
}

ocicli_location_list (){
	ocicli_call "action=location_list"
	echo "id,name,swiftregion"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"][] | "\(.id),\(.name),\(.swiftregion)"'
}


ocicli_network_list (){
	ocicli_call "action=network_list"
	echo "name,ip,cidr,is_public,cluster,role,iface1,iface2,location_id"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.name)|.["data"][] | "\(.name),\(.ip),\(.cidr),\(.is_public),\(.cluster),\(.role),\(.iface1),\(.iface2),\(.location_id)"'
}

ocicli_cluster_list (){
	ocicli_call "action=cluster_list"
	echo "id,name,domain"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.name)|.["data"][] | "\(.id),\(.name),\(.domain)"'
}

ocicli_swiftregion_list () {
	ocicli_call "action=swiftregion_list"
	echo "id,name"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.name)|.["data"][] | "\(.id),\(.name)"'
}

ocicli_cluster_show_networks (){
	ocicli_call "action=cluster_show_networks&cluster_name=${1}"
	echo "name,ip,cidr,is_public,cluster,role,iface1,iface2,location_id"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.name)|.["data"][] | "\(.name),\(.ip),\(.cidr),\(.is_public),\(.cluster),\(.role),\(.iface1),\(.iface2),\(.location_id)"'
}

ocicli_cluster_show_machines (){
	ocicli_call "action=cluster_show_machines&cluster_name=${1}"
	echo "serial,ipaddr,memory,status,lastseen,hostname"
	cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.serial)|.["data"][] | "\(.serial),\(.ipaddr),\(.memory),\(.status),\(.lastseen),\(.hostname)"'
}

ocicli_display_status (){
	STATUS=$(cat ${API_RESPONSE_FILE} | jq -r '.["status"]')
	if [ "${STATUS}" = 'success' ] ; then
		echo "Ok."
	else
		echo "Status not ok:"
		cat ${API_RESPONSE_FILE} | jq -r '.["message"]'
	fi
}

#########################
### Parameter parsing ###
#########################

if [ -z "${1}" ] ; then
	usage
fi

if [ "${1}" = -d ] ; then
	DEBUG=on
	MINUS_D="-d"
	shift
fi

# If using -csv, procress as normal
if [ "${1}" = -csv ] ; then
	shift
else
	# If not, (and not for all commands...), we call ourself with -csv and filter the CSV output through the column program
	case ${1} in
	"machine-install-os")
		echo -n ""
	;;
	"machine-install-log")
		echo -n ""
	;;
	"swift-calculate-ring")
		echo -n ""
	;;
	*)
		$0 ${MINUS_D} -csv $@ | column -t -s $','
		exit 0
	;;
	esac
fi

ACTION=${1}
shift

case "${ACTION}" in
	"machine-list")
		ocicli_machine_list
	;;
	# Add a machine to a cluster
	"machine-add")
		ocicli_call "action=machine_add&machine_serial=${1}&cluster_name=${2}&role_name=${3}&location_name=${4}"  
		ocicli_display_status
	;;
	"machine-remove")
		ocicli_call "action=machine_remove&machine_serial=${1}"
		ocicli_display_status
	;;
	"machine-destroy")
		ocicli_call "action=machine_destroy&machine_serial=${1}"
		ocicli_display_status
	;;
	"machine-show-from-hostname")
		ocicli_call "action=machine_show_from_hostname&hostname=${1}"
		echo "serial,ipaddr,memory,status,lastseen,hostname"
		cat ${API_RESPONSE_FILE} | jq -r '.["data"] | "\(.serial),\(.ipaddr),\(.memory),\(.status),\(.lastseen),\(.hostname)"'
	;;
	"machine-reboot-on-hdd")
		ocicli_call "action=machine_reboot_on_hdd&serial=${1}"
		ocicli_display_status
	;;
	"machine-reboot-on-live")
		ocicli_call "action=machine_reboot_on_live&serial=${1}"
		ocicli_display_status
	;;
	"machine-ipmi-reboot-on-hdd")
		ocicli_call "action=ipmi_reboot_on_hdd&serial=${1}"
		ocicli_display_status
	;;
	"machine-ipmi-reboot-on-live")
		ocicli_call "action=ipmi_reboot_on_live&serial=${1}"
		ocicli_display_status
	;;
	"machine-install-os")
		ocicli_call "action=machine_install_os&serial=${1}"
		cat ${API_RESPONSE_FILE} | jq -r '.["data"]'
	;;
	"machine-install-log")
		ocicli_call "action=machine_install_log&serial=${1}"
		cat ${API_RESPONSE_FILE} | jq -r '.["data"]'
	;;
	"machine-set-ipmi")
		ocicli_call "action=machine_set_ipmi&serial=${1}&ipmi_use=${2}&ipmi_addr=${3}&ipmi_port=${4}&ipmi_username=${5}&ipmi_password=${6}"
		ocicli_display_status
	;;

	"location-list")
		ocicli_location_list
	;;
	"location-create")
		ocicli_call "action=location_create&name=${1}&swiftregion=${2}"
		ocicli_display_status
	;;
	"location-delete")
		ocicli_call "action=location_delete&name=${1}"  
		ocicli_display_status
	;;

	"network-create")
		ocicli_call "action=new_network&name=${1}&ipaddr=${2}&cidr_mask=${3}&location=${4}&is_public=${5}"
		ocicli_display_status
	;;
	"network-list")
		ocicli_network_list
	;;
	"network-delete")
		ocicli_call "action=network_delete&name=${1}"
		ocicli_display_status
	;;
	# Add a network to a cluster
	"network-add")
		ocicli_call "action=network_add&network_name=${1}&cluster_name=${2}&role_name=${3}&iface1=${4}&iface2=${5}"
		ocicli_display_status
	;;
	# Remove a network from a cluster
	"network-remove")
		ocicli_call "action=network_remove&network_name=${1}"
		ocicli_display_status
	;;

	"cluster-list")
		ocicli_cluster_list
	;;
	"cluster-create")
		ocicli_call "action=cluster_create&name=${1}&domain=${2}"
		ocicli_display_status
	;;
	"cluster-delete")
		ocicli_call "action=cluster_delete&name=${1}"
		ocicli_display_status
	;;
	"cluster-show-networks")
		ocicli_cluster_show_networks $@
	;;
	"cluster-show-machines")
		ocicli_cluster_show_machines $@
	;;
	"cluster-show-ips")
		ocicli_call "action=cluster_show_ips&name=${1}"
		echo "hostname,ip"
		cat ${API_RESPONSE_FILE} | jq -r '.["data"]|=sort_by(.hostname)|.["data"][] | "\(.hostname),\(.ipaddr)"'
	;;

	"swift-region-list")
		ocicli_swiftregion_list
	;;
	"swift-region-create")
		ocicli_call "action=swiftregion_create&name=${1}"
		ocicli_display_status
	;;
	"swift-region-delete")
		ocicli_call "action=swiftregion_delete&name=${1}"
		ocicli_display_status
	;;
	"swift-calculate-ring")
		ocicli_call "action=swift_caculate_ring&cluster_name=${1}"
		echo "Output for the job:"
		cat ${API_RESPONSE_FILE} | jq -r '.["data"]'
	;;

	*)
		usage
	;;
esac
