This ipvsadm package contains: - uci ipvs sample configuration file - ipvsadm service startup/shutdown script - scheduler checking real servers' availability and re-configuring ipvs tables accordingly
Dependencies: - ipvs kernel modules - ipvsadm tool Signed-off-by: Mauro Mozzarelli <[email protected]> diff --git a/package/network/utils/ipvsadm/Makefile b/package/network/utils/ipvsadm/Makefile index 1eeca83..b6360d2 100644 --- a/package/network/utils/ipvsadm/Makefile +++ b/package/network/utils/ipvsadm/Makefile @@ -37,6 +37,7 @@ define Package/$(PKG_NAME)/description The Linux Virtual Server can be used to build scalable network services based on a cluster of two or more nodes. endef + #-I$(STAGING_DIR)/usr/include/libnl-tiny -fPIC -DLIBIPVS_USE_NL -D_GNU_SOURCE TARGET_CFLAGS += \ -I$(STAGING_DIR)/usr/include/libnl-tiny @@ -50,6 +51,7 @@ define Package/$(PKG_NAME)/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/ipvsadm $(1)/sbin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ipvsadm-save $(1)/sbin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ipvsadm-restore $(1)/sbin/ + $(CP) ./files/* $(1)/ endef $(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/network/utils/ipvsadm/files/etc/config/ipvs b/package/network/utils/ipvsadm/files/etc/config/ipvs new file mode 100644 index 0000000..50f01d1 --- /dev/null +++ b/package/network/utils/ipvsadm/files/etc/config/ipvs @@ -0,0 +1,57 @@ +# Sample Configuration v2.0 +# +# please see the documentation at www.linuxvirtualserver.org to learn how to +# configure real servers. +# This configuration is used by /etc/init.d/ipvsadm to setup and load balance +# virtual servers to available real servers. +# A cron job is used to activate/deactivate real servers based on their availability (ping) +# +# If virtual and real servers have internet static IPs, the wan interface must be part of a static IP Subnet +# ipvsadm is fully functional for manual configuration + +config vipvs globals + option enabled 0 +# role master|slave + option role 'master' + option interface 'lan' +# if an alias number is not specified in virtual, aliases are created by default starting from 100 +# alias offset specifies a custom offset 0=default to 100 + option alias offset '0' +# valid schedulers are included in the kernel schedulers list + list scheduler wlc + +# for each vip an alias ip is initialized on the wan/lan router interface +# the vip must not be the same as the router's ip +config virtual + option enabled 0 + option name admin + option vip '192.168.10.10' + option interface lan + option alias 10 + option scheduler 'wlc' +# persistent: if set, 0=default timeout of 300s any other number specifies a custom timeout + option persistent '0' +# optional parameters for virtual servers: use ipvsadm syntax + option parameters '-M netmask 255.255.255.255' +# list of real servers associated with this virtual server + list real '192.168.10.100' + list real '192.168.10.101' + +# lists protocols/ports for related virtual server with name admin +config admin + option protocol tcp + option src_port 80 + option dest_port 80 + +config admin + option protocol udp +# if only 'port' is specified then source and destination ports are the same +# port 0 means all ports are forwarded to the real servers + option port 0 + +# configure options specific to a real server +# must have ip with _ instead of dots to comply with uci syntax. The script re-converts these to IP +# packet_forwarding (use ipvsadm switch), weight (numeric), u_threshold (numeric), l_threshold (numeric) +config 192_168_10_100 + option packet_forwarding '-g' + option weight '1' diff --git a/package/network/utils/ipvsadm/files/etc/init.d/ipvsadm b/package/network/utils/ipvsadm/files/etc/init.d/ipvsadm new file mode 100755 index 0000000..d44a3ac --- /dev/null +++ b/package/network/utils/ipvsadm/files/etc/init.d/ipvsadm @@ -0,0 +1,245 @@ +#!/bin/sh /etc/rc.common + +################################################################################ +# ipvsadm v2.0 +# Author: Mauro Mozzarelli +# Description: builds ipvs configuration from uci openwrt parameters +# load/unload ip_vs kernel modules +# start/stop ipvs scheduler +# start/stop cron job scheduler +# Dependencies: /etc/config/ipvs; ipvsadm; ip_vs Kernel modules; cron +# Notes: Firewall must be configured separately +# Configuration files in /tmp/ipvsadm.d: +# virt.* = virtual servers +# *.stop = real server in down state ipvs table +# *.start = real server in up state ipvs table +# vserv.* = virtual servers ipvs table +################################################################################ + +START=70 +STOP=10 + +USE_PROCD=1 + +BASE_DIR=/tmp/ipvsadm.d +TMP_DIR=$BASE_DIR +REAL_SERVERS=realServers +KERNEL_RELEASE=`uname -r` +MODULES=/lib/modules/$KERNEL_RELEASE +IPVSMOD=ip_vs +SCHED=rr +# Reserve first 100 aliases for automated allocation +ALIAS_NEXT=100 +# Cron job used to check if real servers are available and update ipvs +# scheduler accordingly +CRON_SCHEDULER='* * * * * /usr/sbin/checkRealServers # IPVS_SCHEDULER' + +# Get parameters for real servers (repetitive cycle) +get_real_parameters () { + ip=`echo $1 | tr '.' '_'` + param=`uci -q get ipvs.@$ip[0].packet_forwarding` + for i in weight u_threshold l_threshold; do + value=`uci -q get ipvs.@$ip[0].$i` + case $i in + weight) switch="-w" ;; + u_threshold) switch="-x" ;; + l_threshold) switch="-y" ;; + esac + if [ ! -z $value ]; then + let $value 2>/dev/null + isNumeric=$? + if [ $isNumeric -eq 0 ]; then + param="$param $switch $value" + else + param="$param $switch" + fi + fi + done + echo $param +} + +# Check if real server is in the list and add if not present +update_real_server () { + realServer=$1 + gotit=0 + for s in `cat $BASE_DIR/$REAL_SERVERS`; do + if [ $r == $s ]; then + gotit=1 + break + fi + done + if [ $gotit -eq 0 ]; then + echo $r >> $BASE_DIR/$REAL_SERVERS + fi +} + +start_service () { + enabled=`uci -q get ipvs.globals.enabled` + case $enabled in + 0) + exit + ;; + 1) + ;; + *) + echo Invalid initialization parameter: enabled=$enabled + exit + ;; + esac + if [ -d $BASE_DIR ]; then + cd $BASE_DIR + else + mkdir -p $BASE_DIR + cd $BASE_DIR + fi + rm -f $BASE_DIR/* + rm -f $TMP_DIR/*.down + touch $BASE_DIR/$REAL_SERVERS + modprobe $IPVSMOD + cm=0 + for m in `uci -q get ipvs.globals.scheduler`; do + cm=$((cm+1)) + modprobe ${IPVSMOD}_$m + done + # Default to SCHED if no schedulers + if [ $cm -eq 0 ]; then + modprobe ${IPVSMOD}_${SCHED} + fi + offset=`uci -q get ipvs.globals.alias_offset` + if [ ! -z "$offset" ]; then + let $offset 2>/dev/null + isNumeric=$? + if [ $isNumeric -eq 0 ]; then + ALIAS_NEXT=$offset + fi + fi + cv=0 + while [ x`uci -q get ipvs.@virtual[$cv]` == x'virtual' ]; do + enabled=`uci get ipvs.@virtual[$cv].enabled` + if [ $enabled -eq 0 ]; then + let cv=$cv+1 + continue + fi + name=`uci get ipvs.@virtual[$cv].name` + vip=`uci get ipvs.@virtual[$cv].vip` + interface=`uci get ipvs.@virtual[$cv].interface` + device=`uci -P /var/state get network.${interface}.ifname` + ipaddr=`uci -P /var/state get network.${interface}.ipaddr` + alias=`uci -q get ipvs.@virtual[$cv].alias` + scheduler=`uci -q get ipvs.@virtual[$cv].scheduler` + persistent=`uci -q get ipvs.@virtual[$cv].persistent` + v_params=`uci -q get ipvs.@virtual[$cv].parameters` + # ifconfig: get alias number or use a the default + if [ "$vip" != "$ipaddr" ] ; then + let $alias 2>/dev/null + isNumeric=$? + if [ -z "$alias" ] || [ $isNumeric -gt 0 ]; then + alias=$ALIAS_NEXT + let ALIAS_NEXT=$ALIAS_NEXT+1 + fi + ifconfig $device:$alias $vip netmask 255.255.255.255 up + echo "ifconfig $device:$alias down" >> $BASE_DIR/ifconfig_down.sh + fi + if [ -z "$scheduler" ]; then + scheduler=$SCHED + fi + if [ ! -z $persistent ]; then + let $persistent 2>/dev/null + isNumeric=$? + # if numeric and greater than 0 set timeout to value, otherwise use default + if [ $isNumeric -eq 0 ] && [ $persistent -gt 0 ]; then + persistent="-p $persistent" + else + persistent="-p" + fi + fi + # + real=`uci -q get ipvs.@virtual[$cv].real` + if [ ! -z "$real" -a "$real" != " " ]; then + vip_done=no + for r in $real; do + update_real_server $r + r_params="$(get_real_parameters $r)" + cd=0 + while [ x`uci -q get ipvs.@$name[$cd]` == x$name ]; do + protocol=`uci -q get ipvs.@$name[$cd].protocol` + src_port=`uci -q get ipvs.@$name[$cd].src_port` + dest_port=`uci -q get ipvs.@$name[$cd].dest_port` + case $protocol in + tcp) + protocol="-t" + ;; + udp) + protocol="-u" + ;; + *) + # Default to tcp protocol + protocol="-t" + ;; + esac + if [ -z $src_port ]; then + port=`uci -q get ipvs.@$name[$cd].port` + if [ -z $port ]; then + port=0 + fi + src_port=$port + fi + if [ -z $dest_port ]; then + dest_port=$src_port + fi + if [ x$vip_done == x'no' ];then + echo "-A $protocol $vip:$src_port -s $scheduler $persistent $v_params" >> $BASE_DIR/vserv.start.$interface + echo "-D $protocol $vip:$src_port" >> $BASE_DIR/vserv.stop.$interface + fi + echo "-a $protocol $vip:$src_port -r $r:$dest_port $r_params" >> $BASE_DIR/$r.start + echo "-d $protocol $vip:$src_port -r $r" >> $BASE_DIR/$r.stop + cd=$((cd+1)) + done + vip_done=yes + done + fi + let cv=$cv+1 + done + for i in `cat $BASE_DIR/$REAL_SERVERS`; do + date > $TMP_DIR/$i.down + done + for i in ${BASE_DIR}/vserv.start.* ; do + ipvsadm -R < $i + done + + grole=`uci get ipvs.globals.role` + gintf=`uci get ipvs.globals.interface` + ipvsadm --start-daemon $grole --mcast-interface `uci -P /var/state get network.$gintf.ifname` + if [ $? -gt 0 ]; then + logger -p info "ERROR: IPVSADM daemon failed to start" + exit + fi + logger -p info "IPVSADM daemon started" + + # Clean up any left over crontab entry + # Add real server check scheduler to cron + (crontab -l|grep -v IPVS_SCHEDULER ; echo "$CRON_SCHEDULER")|crontab - +} + +stop_service () { + for i in ${BASE_DIR}/*.stop ; do + ipvsadm -R < $i + done + for i in ${BASE_DIR}/vserv.stop.* ; do + ipvsadm -R < $i + done + /bin/sh $BASE_DIR/ifconfig_down.sh + ipvsadm --stop-daemon `uci get ipvs.globals.role` + rm -f $TMP_DIR/*.down + rm -rf $BASE_DIR + for m in `uci -q get ipvs.globals.scheduler`; do + cm=$((cm+1)) + rmmod ${IPVSMOD}_${m} + done + # Default to SCHED if no schedulers + if [ $m -eq 0 ]; then + rmmod ${IPVSMOD}_${SCHED} + fi + rmmod $IPVSMOD + crontab -l |grep -v IPVS_SCHEDULER|crontab - +} diff --git a/package/network/utils/ipvsadm/files/usr/sbin/checkRealServers b/package/network/utils/ipvsadm/files/usr/sbin/checkRealServers new file mode 100755 index 0000000..f801c4b --- /dev/null +++ b/package/network/utils/ipvsadm/files/usr/sbin/checkRealServers @@ -0,0 +1,36 @@ +#!/bin/sh +################################################################################ +# Author: Mauro Mozzarelli +# Description: checks whether a real server is up and running and if it is +# then it starts the services +# Dependencies: /tmp/ipvsadm.d +# configuration files created by /etc/init.d/ipvsadm +# virt.* = virtual servers +# *.stop = real server in down state ipvs table +# *.start = real server in up state ipvs table +# *.down = real server down status +################################################################################ + +BASE_DIR=/tmp/ipvsadm.d +TMP_DIR=$BASE_DIR +REAL_SERVERS=realServers + +if [ -f $BASE_DIR/$REAL_SERVERS ]; then + for i in `cat $BASE_DIR/$REAL_SERVERS`; do + ping -qc 3 $i > /dev/null + RESULT=$? + if [ $RESULT -gt 0 ]; then + if [ ! -f $TMP_DIR/$i.down ]; then + ipvsadm -R < $BASE_DIR/$i.stop + date > $TMP_DIR/$i.down + logger -p info "IPVS Server $i is down" + fi + else + if [ -f $TMP_DIR/$i.down ]; then + ipvsadm -R < $BASE_DIR/$i.start + rm $TMP_DIR/$i.down + logger -p info "IPVS Server $i is on-line" + fi + fi + done +fi _______________________________________________ openwrt-devel mailing list [email protected] https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
