[OpenWrt-Devel] [PATCH v3 2/2] ipvsadm: uci configuration, init, scheduler
Mauro Mozzarelli
mauro at ezplanet.net
Mon Mar 7 17:44:56 EST 2016
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 <mauro at ezplanet.net>
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. at virtual[$cv]` == x'virtual' ]; do
+ enabled=`uci get ipvs. at virtual[$cv].enabled`
+ if [ $enabled -eq 0 ]; then
+ let cv=$cv+1
+ continue
+ fi
+ name=`uci get ipvs. at virtual[$cv].name`
+ vip=`uci get ipvs. at virtual[$cv].vip`
+ interface=`uci get ipvs. at 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. at virtual[$cv].alias`
+ scheduler=`uci -q get ipvs. at virtual[$cv].scheduler`
+ persistent=`uci -q get ipvs. at virtual[$cv].persistent`
+ v_params=`uci -q get ipvs. at 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. at 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
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list