#!/bin/bash

CONFIG_DIR="/etc/vstorage"
CLUSTERS_DIR="${CONFIG_DIR}/clusters"
SYSTEMD_DIR="/usr/lib/systemd/system"
SYSTEMD_TOOL="/usr/bin/systemctl"
LOCK_FILE=".lock"

mdsd_target_file() {
cat  <<EOFT
[Unit]
Description=Metadata server(MDS) target for $CLUSTER_NAME cluster
PartOf=vstorage-mdsd.target

[Install]
WantedBy=vstorage-mdsd.target
EOFT
}

csd_target_file() {
cat  <<EOFT
[Unit]
Description=Chunk server(CS) target for $CLUSTER_NAME cluster
PartOf=vstorage-csd.target

[Install]
WantedBy=vstorage-csd.target
EOFT
}

create_cluster_target() {
	local OP="$1"
	local CLUSTER_NAME="$2"
	
	#example: vstorage-csd.my_pcs4.target
	local TARGET_NAME="vstorage-${DAEMON_NAME}.${CLUSTER_NAME}.target"
	[ -f $TARGET_NAME ] && return 0

	$OP > ${SYSTEMD_DIR}/${TARGET_NAME}
	$SYSTEMD_TOOL --quiet enable ${TARGET_NAME}
}

service_unit_file() {
cat  <<EOFT
.include /etc/vstorage/vstorage-$DAEMON_NAME.service
.include /etc/vstorage/clusters/$CLUSTER_NAME/vstorage-$DAEMON_NAME.service

[Unit]
Description=vstorage-$DAEMON_NAME($DAEMON_DIR)
PartOf=vstorage-$DAEMON_NAME.$CLUSTER_NAME.target
Before=remote-fs-pre.target
After=vstorage-$DAEMON_NAME-pre.target

[Service]
Environment="DAEMON=$DAEMON_NAME" "CLUSTER=$CLUSTER_NAME" "DAEMON_DIR=$DAEMON_DIR"
PIDFile=$DAEMON_DIR/$CONTROL_DIR/$DAEMON_NAME.pid

[Install]
WantedBy=vstorage-$DAEMON_NAME.$CLUSTER_NAME.target
EOFT
}

create_daemon_service() {
	local CLUSTER_NAME="$1"
	local DAEMON_DIR="$2"

	[ ! -d "$DAEMON_DIR" ] && return 0

	[ -f "$DAEMON_DIR/control/id" ] && SERVICEID=$(cat "$DAEMON_DIR/control/id")
	[ -f "$DAEMON_DIR/id" ] && SERVICEID=$(cat "$DAEMON_DIR/id")
	[ -z "$SERVICEID" ] && return 0

	#unit file example vstorage-mdsd.my_pcs4.1.service
	local UNIT_NAME="vstorage-${DAEMON_NAME}.${CLUSTER_NAME}.${SERVICEID}.service"
	local UNIT_FILE="${SYSTEMD_DIR}/${UNIT_NAME}"
	if [ -f $UNIT_FILE ] ; then
		# check if unit file includes common stub which is being upgraded separately from the unit file
		grep "\.include" $UNIT_FILE >/dev/null
		if [ $? -eq 0 ]; then
			return 0
		fi
		# if not replace it with new version with .include directive
	fi

	service_unit_file > ${UNIT_FILE}
	$SYSTEMD_TOOL --quiet enable ${UNIT_NAME}
}

for_cluster() {
	local OP="$1"
	local CLUSTER_NAME="$2"
	local CLUSTER_DIR="${CLUSTERS_DIR}/$CLUSTER_NAME"
	# lock per-cluster lock before accessing lists
	( flock -x -w 10 100 || exit 1
		cat "${CLUSTER_DIR}/$LIST_FILE" 2>/dev/null | grep -v '^#' | grep -v '^\s*$' | while read dir; do
			# '100<&-' explicitely closes fd 100 for childs, especially monitor
			("$OP" "${CLUSTER_NAME}" "${dir}") 100<&-
		done
	) 100>"${CLUSTER_DIR}/$LOCK_FILE" || echo "Failed to obtain lock: ${CLUSTER_DIR}/$LOCK_FILE"
}

for_all() {
	local OP1="$1"
	local OP2="$2"
	ls -d "${CLUSTERS_DIR}"/* 2>/dev/null | while read cluster; do
		local CLUSTER_NAME=$(basename "${cluster}")
		create_cluster_target "${OP2}" "${CLUSTER_NAME}"
		for_cluster "${OP1}" "${CLUSTER_NAME}"
	done
}

handle_gen()
{
	if [ "$#" -eq 1 ]; then
		SERVICE="$1"
		DAEMON_NAME="${SERVICE}d"
		SUBSYS="vstorage-${DAEMON_NAME}"
		LIST_FILE="${SERVICE}.list"
		
		case "$SERVICE" in
		  mds)
			CONTROL_DIR="."
			for_all create_daemon_service mdsd_target_file
			;;
		  cs)
			CONTROL_DIR="control"
			for_all create_daemon_service csd_target_file
			;;
		  *)
			echo "Invalid argument"
			echo "Usage: $0 {mds|cs}"
			exit 1
		esac
	
	else
			echo "Usage: $0 {mds|cs}"
			exit 1;
	fi
}

handle_gen "$@"
