#!/bin/bash

$CLOUD_UUID
$CLOUD_NAME
$CLOUD_PASSWD
$CLOUD_HOST
$LISTEN_PORT
$ISSUE
$OVERLAY
$PROXY_IP
$OLD_UMASK
$DELET_LISTEN_PORT
$SPACE
$DONOT_BIND_CLOUD_ACCOUNT
$UPDATE_PORT
$CLOUD_PORT
$SCAN_PORT
$CONND_PORT
$MONITOR_PORT
$FOR_ENGLISH


AGENT_PATH=/usr/local/yunsuo_agent
ARCH=x64
SERVER_NAME=yunsuo_agent_service
GUARD_NAME=yunsuo_agent_guard
SCRIPT_SERVER_NAME=yunsuo
SCRIPT_GUARD_NAME=yunsuo_guard
DEFAULT_UPDATE_HOST=update.yunsuo.com.cn
DEFAULT_API_HOST=apiv3.yunsuo.com.cn
DEFAULT_SCAN_HOST=scan.yunsuo.com.cn
DEFAULT_MONITOR_HOST=monitor.yunsuo.com.cn
PACKAGE_TYPE=normal
BIND_CLOUD_ENFORCE=no
AGENT_LIB_LINK=/usr/local/lib/jlib64

GLOBAL_C=60
PROGRAM_NAME=$0
OPTION_COUNT=$#

function success()
{
	echo -e "\033[${GLOBAL_C}G[\033[32m OK \033[0m]"
}

function fail()
{
	echo -e "\033[${GLOBAL_C}G[\033[31m FAILED \033[0m]"
}

function notfound()
{
	echo -e "\033[${GLOBAL_C}G[\033[33m NOT FOUND \033[0m]"
}

function warning()
{
	echo -e "\033[${GLOBAL_C}G[\033[33m WARNING \033[0m]"
}

function welcome_info()
{
	echo "Welcome."
	echo "If you encounter any problems during installation, you can use 'ctrl-c' to cancel."
	echo ""
}

# 帮助函数
function helper()
{
	echo "Usage: "
	echo "  $PROGRAM_NAME [OPTIONS] [LONG OPTIONS]"
	echo ""
	echo "OPTIONS:"
	echo "  -u xxx: Cloud center username"
	echo "  -p xxx: Cloud center password"
	echo "  -U xxx: Cloud center UUID"
	echo "  -l xxx: Agent's listen port. default is 5555"
	echo "  -o xxx: Operation system type. surport centos, redhat, ubuntu, suse, debian"
	echo "  -c xxx: Cloud Center Host"
	echo "  -P xxx: Set proxy server ip"
	echo "  -s xxx: Install Path"
	echo "  -b xxx: Max use space, max usage"
	echo "  -B: Don't bind cloud center account"
	echo "  -d: Delete listen port"
	echo "  -f: Overlay installation"
	echo "  -e: for english"
	echo "  -h: help information"
	echo ""
	echo "LONG OPTIONS:"
	echo "  --update_port=xxx: add/modify update host port"
	echo "  --cloud_port=xxx: add/modify cloud center host port"
	echo "  --scan_port=xxx: add/modify scan center host port"
	echo "  --connd_port=xxx: modify connect port"
	echo "  --monitor_port=xxx: add/modify monitor center host port"
}

# 卸载agent
function clear_residue()
{
	if [ -x $AGENT_PATH/uninstall ];then
		$AGENT_PATH/uninstall 2&> /dev/null <<EOF
		y
EOF
	else
		rm -rf $AGENT_PATH
	fi
}

# 注册信号处理
function register_signal()
{
	trap "clear_residue && echo && echo 'Cancel install successed. Bye' && exit" INT
}

# 参数解析
function parse_options()
{
	OPTION_ARGS=`getopt --options u:p:U:l:o:c:P:s:b:fdhBe --long update_port:,cloud_port:,scan_port:,connd_port:,monitor_port: -- "$@"`
	if [ $? != 0 ];then
		helper
		exit
	fi

	eval set -- "${OPTION_ARGS}"

	while true
	do
		case "$1" in
			-u)
				CLOUD_NAME=$2
				shift 2 ;;
			-p)	
				CLOUD_PASSWD=$2
				shift 2 ;;
			-U)	
				CLOUD_UUID=$2
				shift 2 ;;
			-l)	
				LISTEN_PORT=$2
				shift 2 ;;
			-o)	
				ISSUE=$2
				shift 2 ;;
			-c)	
				CLOUD_HOST=$2
				shift 2 ;;
			-P)	
				PROXY_IP=$2
				shift 2 ;;
			-s)	
				subdir=${AGENT_PATH##*/}
				temp=${2%?}
			   	lastchar=${2##$temp}
			   	if [ "$lastchar" = "/" ];then
			   		AGENT_PATH=$2$subdir
				else
					AGENT_PATH=$2/$subdir
				fi
				shift 2 ;;
			-b)	
				SPACE=$2
				shift 2 ;;
			--update_port)
				UPDATE_PORT=$2
				shift 2 ;;
			--cloud_port)
				CLOUD_PORT=$2
				shift 2 ;;
			--scan_port)
				SCAN_PORT=$2
				shift 2 ;;
			--connd_port)
				CONND_PORT=$2
				shift 2 ;;
			--monitor_port)
				MONITOR_PORT=$2
				shift 2 ;;	
			-f)	
				OVERLAY="y"
				shift ;;
			-d)	
				DELET_LISTEN_PORT="y"
				shift ;;
			-B)	
				DONOT_BIND_CLOUD_ACCOUNT="y"
				shift ;;
			-e)
				FOR_ENGLISH="y"
				shift ;;
			--)	
				shift
				break
				;;
			-h|*)
				helper
				exit ;;
		esac
	done

	# if [ $OPTION_COUNT -gt 0 ];then
	# 	while getopts "u:p:U:l:o:c:P:s:b:fdhB" opt
	# 	do
	# 		case $opt in
	# 			u)	CLOUD_NAME=$OPTARG ;;
	# 			p)	CLOUD_PASSWD=$OPTARG ;;
	# 			U)	CLOUD_UUID=$OPTARG ;;
	# 			l)	LISTEN_PORT=$OPTARG ;;
	# 			o)	ISSUE=$OPTARG ;;
	# 			f)	OVERLAY="y" ;;
	# 			d)	DELET_LISTEN_PORT="y" ;;
	# 			c)	CLOUD_HOST=$OPTARG ;;
	# 			P)	PROXY_IP=$OPTARG ;;
	# 			s)	subdir=${AGENT_PATH##*/}
	# 				temp=${OPTARG%?}
	# 				lastchar=${OPTARG##$temp}
	# 				if [ "$lastchar" = "/" ];then
	# 					AGENT_PATH=$OPTARG$subdir
	# 				else
	# 					AGENT_PATH=$OPTARG/$subdir
	# 				fi
	# 				;;
	# 			b)	SPACE=$OPTARG ;;
	# 			B)	DONOT_BIND_CLOUD_ACCOUNT="y" ;;
	# 			h)	helper
	# 				exit ;;
	# 			?)	helper
	# 				exit ;;
	# 		esac
	# 	done
	# fi
}

# 检查安装包是否与系统匹配
function check_arch()
{
    if [ "$ARCH" = "x86" ];then
        if [ `uname -m` = "x86_64" ];then
            return 1
        else
            return 0
        fi
    else
        if [ `uname -m` != "x86_64" ];then
            return 1
        else
            return 0
        fi 
    fi
}

# 检查系统版本
function check_issue()
{
	if [ -z "$ISSUE" ];then
		if [ ! -z `find /usr/bin -name apt-get` ];then
			k_version=`uname -r`
			if [[ "$k_version" =~ "generic" ]] || [[ "$k_version" =~ "server" ]];then
				ISSUE="ubuntu"
			else
				ISSUE="debian"
			fi
		elif [ ! -z `find /usr/bin -name yum` ];then
			ISSUE="centos"
		elif [ ! -z `which YaST 2> /dev/null` ] || [ ! -z `which yast 2> /dev/null` ];then
			ISSUE="suse"
		else
			return 1
		fi
	else
		if [[ "$ISSUE" != "centos" ]] && [[ "$ISSUE" != "ubuntu" ]] && [[ "$ISSUE" != "suse" ]] && [[ "$ISSUE" != "redhat" ]] && [[ "$ISSUE" != "debian" ]];then
			return 1
		elif [[ "$ISSUE" = "redhat" ]];then
			ISSUE="centos"
		fi
	fi
	
	return 0    
}

# 检查是否已经安装agent
function check_installed()
{
	if [ -d $AGENT_PATH ];then
		if [ -z $OVERLAY ];then
			# 安装时未指定覆盖安装, 这里做提示, 是否覆盖安装
			echo
			echo -n "Overlay installation?(Y/N): "
			read OVERLAY
		fi
		
		if [ "$OVERLAY" != "y" ] && [ "$OVERLAY" != "Y" ];then
			# 不覆盖安装
			return 1
		else
			# 覆盖安装(这里做卸载操作)
			clear_residue
		fi
	fi
	
	return 0
}

# 检查驱动是否已安装
function check_dirvers()
{
	which lsmod 2&> /dev/null
	if [ $? -ne 0 ];then
		# 系统可能不存在lsmod命令，因此不做驱动检查，直接安装
		return 0
	fi

	driver_not_uninstall=`lsmod | grep resguard_linux | grep -v grep | head -1 | awk '{print $1}'`
	if [ ! -z "$driver_not_uninstall" ];then
		return 1
	fi
	
	return 0
}

# 检查是否有足够的空间(600M)
function check_space()
{
	execute_path=$0
	execute_path=`echo ${execute_path%%install}`
	if [ -z $execute_path ];then
		execute_path=.
	fi

	chmod +x $execute_path/check_disk_space

	install_path=${AGENT_PATH%/*}

	$execute_path/check_disk_space $install_path $SPACE
	if [ $? -ne 0 ];then
		return 1
	fi

	return 0
}

# 检查当前用户是否为root(uid=0)用户
function check_user_is_root()
{
	if [ "$UID" != "0" ];then
		return 1
	fi

	return 0
}

# 检查当前系统环境是否允许安装
function check_installation_environment()
{
	echo -n "checking installation environment:"
	
	while true
	do
		# 检查当前用户是否为root
		check_user_is_root
		if [ $? -ne 0 ];then
			error_info="Installer must run with root(uid=0), current user is $UID"
			break
		fi

		# 检查包是否匹配
		check_arch
		if [ $? -ne 0 ];then
			error_info="Installation package and system version mismatch, please confirm package"
			break
		fi

		# 检查system issue
		check_issue
		if [ $? -ne 0 ];then
			error_info="Installer could not detect system issue, please specify system issue to install."
			break
		fi
		
		# 检查是否已经安装过
		check_installed
		if [ $? -ne 0 ];then
			error_info="Has been installed."
			break
		fi
		
		# 检查驱动
		check_dirvers
		if [ $? -ne 0 ];then
			error_info="Drivers not uninstall, Please Reboot Your System and Install."
			break
		fi

		# 检查是否有足够的空间
		check_space
		if [ $? -ne 0 ];then
			error_info="No space left on device, please check it before installing"
			break
		fi

		success
		return 
	done
	
	fail
	echo ""
	echo "Error: $error_info"
	exit
}

# 安装准备
function prepare_before_install()
{
	execute_path=$0
	execute_path=`echo ${execute_path%%install}`
	if [ -z $execute_path ];then
		execute_path=.
	fi

	# 解压
	echo -n "decompression package:"
	mkdir -p $AGENT_PATH 2> /dev/null
	tar zxf $execute_path/src_lib.tar.gz -C $AGENT_PATH 2> /dev/null

	# 创建及修改必要文件
	test ! -d /var/log && mkdir /var/log
	
	# 创建软链
	test ! -d /usr/local/lib && mkdir /usr/local/lib
	test -d $AGENT_LIB_LINK && rm -rf $AGENT_LIB_LINK
	ln -s $AGENT_PATH/libs $AGENT_LIB_LINK
	
	# 生成路径控制文件
	echo "$AGENT_PATH" > /var/log/version_control
	echo "server_name: $SERVER_NAME" > $AGENT_PATH/command_control
	echo "guard_name: $GUARD_NAME" >> $AGENT_PATH/command_control
	echo "script_server: $SCRIPT_SERVER_NAME" >> $AGENT_PATH/command_control
	echo "script_guard: $SCRIPT_GUARD_NAME" >> $AGENT_PATH/command_control

	# 需要用到的可执行文件+x
	chmod +x $AGENT_PATH/change_port
	chmod +x $AGENT_PATH/agent_smart_tool.sh
	chmod +x $AGENT_PATH/register_cloud_center
	chmod +x $AGENT_PATH/uninstall_driver
	chmod +x $AGENT_PATH/setup_configure
	chmod +x $AGENT_PATH/Update
	chmod +x $AGENT_PATH/upsd
	
	test -f $execute_path/custom_ac && cp $execute_path/custom_ac $AGENT_PATH/config/other

	# 修改cloud center host
	if [ ! -z "$CLOUD_HOST" ];then
		sed -i "s/$DEFAULT_UPDATE_HOST/$CLOUD_HOST/g" $AGENT_PATH/config.xml
		sed -i "s/$DEFAULT_API_HOST/$CLOUD_HOST/g" $AGENT_PATH/config.xml
		sed -i "s/$DEFAULT_SCAN_HOST/$CLOUD_HOST:7901/g" $AGENT_PATH/config.xml
		sed -i "s/$DEFAULT_MONITOR_HOST/$CLOUD_HOST/g" $AGENT_PATH/config.xml
		sed -i "s/1:tcp:127.0.0.1:443/1:tcp:127.0.0.1:555/g" $AGENT_PATH/config.xml
	fi

	# 修改各类host的端口
	if [ ! -z $UPDATE_PORT ];then
		$AGENT_PATH/change_port -l update_port:$UPDATE_PORT
	fi

	if [ ! -z $CLOUD_PORT ];then
		$AGENT_PATH/change_port -l cloud_port:$CLOUD_PORT
	fi

	if [ ! -z $SCAN_PORT ];then
		$AGENT_PATH/change_port -l scan_port:$SCAN_PORT
	fi

	if [ ! -z $CONND_PORT ];then
		$AGENT_PATH/change_port -l connd_port:$CONND_PORT
	fi

	if [ ! -z $MONITOR_PORT ];then
		$AGENT_PATH/change_port -l monitor_port:$MONITOR_PORT
	fi

	if [ "$FOR_ENGLISH" = "y" ];then
		sed -i 's/\(^.*\)<var name="en_version".*$/\1<var name="en_version" type="string" value="1" \/>/g' $AGENT_PATH/config.xml
		cp -f $AGENT_PATH/script/agent_config_web_secure.xml.en $AGENT_PATH/script/agent_config_web_secure.xml
		cp -f $AGENT_PATH/script/agent_config_web_virtual_patch.json.en $AGENT_PATH/script/agent_config_web_virtual_patch.json

		cp -f $AGENT_PATH/default/agent_config_web_secure.xml.en $AGENT_PATH/default/agent_config_web_secure.xml
		cp -f $AGENT_PATH/default/agent_config_web_virtual_patch.json.en $AGENT_PATH/default/agent_config_web_virtual_patch.json
	fi

	success
}

# 配置代理服务器IP
function configure_proxy()
{
	if [ ! -z "$PROXY_IP" ];then
		$AGENT_PATH/change_port -p $PROXY_IP
	fi
}

# 绑定错误信息输出
function bind_error()
{
    if [ "$BIND_CLOUD_ENFORCE" = "yes" ];then
        echo "Your registration hasn't been successful, the installation program has been stopped."
        clear_residue
        exit
    fi
}

# 绑定云中心
function bind_cloud_account()
{
	if [ "$DONOT_BIND_CLOUD_ACCOUNT" = "y" ];then
		return 
	fi

    # 内置账号绑定
	if [ -f $AGENT_PATH/config/other/cloud_center_uuid ];then
		$AGENT_PATH/register_cloud_center bind
		if [ $? != 0 ];then
			bind_error
		fi 

        return
	fi

    # UUID绑定
    if [ ! -z $CLOUD_UUID ];then
        $AGENT_PATH/register_cloud_center bind $CLOUD_UUID
        if [ $? != 0 ];then
			bind_error
		fi 

        return
    fi

    # 用户名密码绑定
    if [ -z "$CLOUD_NAME" ] || [ -z "$CLOUD_PASSWD" ];then
        if [ "$BIND_CLOUD_ENFORCE" = "yes" ];then
            echo "Verify the cloud center account."

            while true
            do
                echo -n "Cloud Center Username: "
                read CLOUD_NAME

                echo -n "Cloud Center Password: "
                stty -echo
                read CLOUD_PASSWD 
                stty echo
                echo

                if [ ! -z $CLOUD_NAME ] && [ ! -z $CLOUD_PASSWD ];then
                    break
                fi
            done
        fi
    fi
    if [ ! -z "$CLOUD_NAME" ] && [ ! -z "$CLOUD_PASSWD" ];then
        $AGENT_PATH/agent_smart_tool.sh -u $CLOUD_NAME -p $CLOUD_PASSWD
        if [ $? != 0 ];then
            bind_error
        fi
    fi
}

# 修改监听端口
function update_listen_port()
{
	if [ ! -z "$LISTEN_PORT" ];then
		$AGENT_PATH/agent_smart_tool.sh -l $LISTEN_PORT
	fi
}

# 删除监听端口
function delet_listen_port()
{
	if [ ! -z "$DELET_LISTEN_PORT" ];then
		if [ "$DELET_LISTEN_PORT" = "y" ];then
			$AGENT_PATH/agent_smart_tool.sh -d
		fi
	fi
}

# 配置云锁运行环境
function execute_configure_script()
{
	cd $AGENT_PATH
	
	# 生成configure_file文件, 该文件内容为具体的配置信息
	test -f configure_file && rm -rf configure_file ; echo "1:$PACKAGE_TYPE:$ARCH:$AGENT_PATH:$ISSUE" > configure_file
	
	export JHSE_SAFE_PATH=$AGENT_PATH
	export LC_ALL="C"
	export LANG="C"

	# 下载驱动
	./Update kernel $ISSUE
	
	# 配置云锁
	./setup_configure -c setup.xml -l runlog/setup.log -e "ALL" -t "ALL" -s safe -m cmdline 2>/dev/null

	echo ""
	echo "Install Complete."
}

# 设置当前bash的umask值为022, 且保存原始的umask值
function reset_umask()
{
	OLD_UMASK=`umask`	
	umask 022
}

# 还原原始umask
function restore_umask()
{
	umask $OLD_UMASK
}

# 安装selinux规则模块
function install_selinux_policy()
{
	echo -n "Install Selinux Policy Module:"

	cur_path=`pwd`
	cd $AGENT_PATH
	
	install_res=0
	
	while true
	do
		if [ ! -f /usr/sbin/semodule ];then 
			break 
		fi
		
		if [ `getenforce` != "Enforcing" ];then
			break
		fi
		
		# 判断policy版本
		policy_version=`sestatus | grep version | awk -F':' '{print $2}' | xargs echo`
		if [ $policy_version -ge 21 ] && [ $policy_version -lt 24 ];then
			cp agent_selinux_policy.21 agent_selinux_policy.te
		elif [ $policy_version -ge 24 ];then
			cp agent_selinux_policy.24 agent_selinux_policy.te
		else
			break
		fi
		
		# 编译selinux规则模块
		checkmodule -M -m -o agent_selinux_policy.mod agent_selinux_policy.te > /dev/null
		if [ $? -ne 0 ];then
			install_res=1
			break
		fi
		
		# 生成selinux规则模块
		semodule_package -o agent_selinux_policy.pp -m agent_selinux_policy.mod
		if [ $? -ne 0 ];then
			install_res=1
			break
		fi
		
		# 安装selinux规则模块
		semodule -i agent_selinux_policy.pp
		if [ $? -ne 0 ];then
			install_res=1
			break
		fi
		
		# 设置lib库的标签
		chcon -R -u system_u -t lib_t libs pam apache
		
		# 清理临时文件
		rm -rf agent_selinux_policy.te agent_selinux_policy.mod agent_selinux_policy.pp
		
		break
	done 
	
	# 恢复工作目录
	cd $cur_path
	
	if [ $install_res -eq 0 ];then
		success
	else
		fail
	fi
}


######################################################
# Main
######################################################
parse_options $*
welcome_info
register_signal
reset_umask
check_installation_environment
prepare_before_install $0
install_selinux_policy
configure_proxy
bind_cloud_account
update_listen_port
delet_listen_port
execute_configure_script
restore_umask