#!/bin/bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)vip-management 3.2.0 09.09.2024 (c)2024 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Add or delete secondary private IP (Virtual IP) #@ Docs: https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/managingIPaddresses.htm #@ #@Usage: vip-management [options] action [ipv4] #@ Options: -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ Action: #@ show: Show current state (default). #@ add: Attach ipv4 to instance. #@ delete: Detach ipv4 from instance. #@ route: Add ipv4 to default gateway. #@ ipv4: #@ A valid and unused IPv4 #@ #@Examples: #@ vip-management add 10.0.1.50 #@ Create a second interface using private IP (from primary VNIC). #@ vip-management delete 10.0.1.50 #@ Delete the second interface. # # Exit codes: # 01: Unknown or wrong parameter and only LINUX supported and script needs to be executed with ROOT privileges. # 02: Unknown action. # 03: No 'ifconfig' or 'ip' in PATH. # 04: No suitable interface found in 'ifconfig'. # 05: No IPv4 found in interface. # 06: VIP already defined (add) or does not exists (delete) # 99: User interrupt. # # See also: # **install-scripts**(1) # # Update history: # # V 3.0.0 14.05.2021 New version # V 3.0.1 21.05.2021 Try sudo if user isn't root # V 3.0.2 22.05.2021 New action: show # V 3.1.0 05.06.2023 New copyright # V 3.2.0 09.09.2024 New minor version: Options # # Find executable bash library and source it lib=`which lib.bash 2>/dev/null | sed 's|^no 'lib.bash' in .*||'` if [ "$lib" != "" ]; then source "$lib" else progdir=`dirname "$0"` if [ -r "${progdir}/lib.bash" ]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Convert Netmask to CIDR function NetmaskToCIDR() { local netmask=${1} local cidr=0 if [ "$netmask" != "" ]; then case "$netmask" in 128.0.0.0) cidr=1 ;; 192.0.0.0) cidr=2 ;; 224.0.0.0) cidr=3 ;; 240.0.0.0) cidr=4 ;; 248.0.0.0) cidr=5 ;; 252.0.0.0) cidr=6 ;; 254.0.0.0) cidr=7 ;; 255.0.0.0) cidr=8 ;; 255.128.0.0) cidr=9 ;; 255.192.0.0) cidr=10 ;; 255.224.0.0) cidr=11 ;; 255.240.0.0) cidr=12 ;; 255.248.0.0) cidr=13 ;; 255.252.0.0) cidr=14 ;; 255.254.0.0) cidr=15 ;; 255.255.0.0) cidr=16 ;; 255.255.128.0) cidr=17 ;; 255.255.192.0) cidr=18 ;; 255.255.224.0) cidr=19 ;; 255.255.240.0) cidr=20 ;; 255.255.248.0) cidr=21 ;; 255.255.252.0) cidr=22 ;; 255.255.254.0) cidr=23 ;; 255.255.255.0) cidr=24 ;; 255.255.255.128) cidr=25 ;; 255.255.255.192) cidr=26 ;; 255.255.255.224) cidr=27 ;; 255.255.255.240) cidr=28 ;; 255.255.255.248) cidr=29 ;; 255.255.255.252) cidr=30 ;; 255.255.255.254) cidr=31 ;; 255.255.255.255) cidr=32 ;; esac fi echo "$cidr" } # Add a second IP as a Virtual IP function AddVIP() { local interface=${1} local vip=${2} local netmask=${3} local broadcast=${4} local cidr=0 local filename="" local stat=0 # Create entry in ifconfig if [ "$interface" != "" -a "$vip" != "" -a "$netmask" != "" ]; then filename="/etc/sysconfig/network-scripts/ifcfg-${interface}:vip" cidr=`NetmaskToCIDR "$netmask"` if [ "$broadcast" != "" ]; then ip addr add "${vip}/${cidr}" dev "$interface" label "${interface}:vip" broadcast "$broadcast" stat=$? else ip addr add "${vip}/${cidr}" dev "$interface" label "${interface}:vip" stat=$? fi # Create file to make it persitent abfter reboot if [ $stat -eq 0 ]; then echo 'DEVICE="'$interface':vip"' > $filename echo "BOOTPROTO=static" >> $filename echo "IPADDR=$vip" >> $filename echo "NETMASK=$netmask" >> $filename if [ "$broadcast" != "" ]; then echo "BROADCAST=$broadcast" >> $filename fi echo "ONBOOT=yes" >> $filename # Display success echo "VIP '$vip' added to interface '${interface}:vip'." fi fi } # Delete a second IP as a Virtual IP function DeleteVIP() { local interface=${1} local vip=${2} local netmask=${3} local cidr=0 local filename="" local stat=0 # Create entry in ifconfig if [ "$interface" != "" -a "$vip" != "" -a "$netmask" != "" ]; then filename="/etc/sysconfig/network-scripts/ifcfg-${interface}:vip" cidr=`NetmaskToCIDR "$netmask"` ip addr del "${vip}/${cidr}" dev "$interface" stat=$? if [ $stat -eq 0 ]; then # Delete file to make it persitent abfter reboot rm -f $filename # Display success echo "VIP '$vip' deleted from interface '${interface}:vip'." fi fi } # Preset action="" vip="" # Check parameters: Loop until all parameters are used up while [ $# -gt 0 ]; do pname=${1} case "$pname" in -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; *) shift paramck=`echo "$pname" | grep '^-'` # Types don't begin with '-' if [ "$paramck" != "" ]; then errstr="Unknown option '$pname'." else if [ "$action" = "" ]; then action=`echo "$pname" | tolower` else if [ "$vip" = "" ]; then vip="$pname" else errstr="VIP was already specified '$vip'. Unknown additional parameter: '$pname'." fi fi fi esac done # Plausibility check # Check if we are running on Linux if [ "$OS" != "Linux" ]; then errstr="This script only supports LINUX." else if [ "$action" = "" ]; then action="show" elif [ "$action" != "show" -a "$action" != "route" -a "$vip" = "" ]; then errstr="Please use this script with an action (add or delete) and a virtual ip as second paramater." fi fi # Display help or error message DisplayHelp ### Main if [ "$USER" != "root" ]; then # Try sudo check-sudo stat=$? if [ $stat -eq 0 ]; then sudo --preserve-env=PATH "$script" "$action" "$vip" else exitcode=1 errormsg $exitcode "Need to be root." fi else ifconfig=`filecheck -x ifconfig` iproute=`filecheck -x ip` if [ "$ifconfig" = "" -o "$iproute" = "" ]; then exitcode=3 errormsg $exitcode "No 'ifconfig' or 'ip' in PATH." else result=`"$iproute" route show 2>/dev/null | grep '^default ' | tail -n 1` if [ "$result" != "" ]; then gateway=`echo "$result" | cut -d' ' -f3` iface=`echo "$result" | cut -d' ' -f5` fi result=`echo "$iface" | grep ':vip$'` if [ "$result" != "" ]; then iface=`echo "$iface" | sed 's|:vip$||'` viproute=true else viproute=false fi "$ifconfig" "$iface" > $scratchfile 2>/dev/null lip=`grep "inet " $scratchfile | tail -n 1 | awk '{print $2}'` lipv6=`grep "inet6 " $scratchfile | tail -n 1 | awk '{print $2}'` result=`grep '^'"${iface}"': .* $scratchfile result=`grep 'inet ' $scratchfile | tail -n 1 | tr -s ' ' | sed 's|^ ||'` if [ "$result" != "" ]; then oldvip=`echo "$result" | cut -d' ' -f2` else oldvip="" fi "$iproute" route show > $scratchfile defroute=`grep '^default via' $scratchfile` case "$action" in show) if [ "$oldvip" != "" ]; then echo "Private ip_v4 on interface '$iface': '$ip'." echo "VIP attached to interface '${iface}:vip': '$oldvip'." if [ "$viproute" = true ]; then echo "VIP attached to default route." else echo "VIP not attached to default route." fi echo "Default route: $defroute" else echo "Private ip_v4 on interface '$iface': '$ip'." echo "No VIP attached to interface '$iface'." if [ "$viproute" = true ]; then echo "VIP attached to default route." else echo "VIP not attached to default route." fi echo "Default route: $defroute" fi ;; route) if [ "$oldvip" != "" ]; then result=`echo "$defroute" | sed 's|src '$oldvip'||'` $iproute route replace $result src $oldvip $iproute route show > $scratchfile defroute=`grep '^default via' $scratchfile` echo "Default route: $defroute" else echo "No VIP attached to interface '$iface'." fi ;; add) if [ "$vip" = "$ip" ]; then exitcode=6 errormsg $exitcode "VIP must differ from private ip on interface '${iface}'." else if [ "$oldvip" != "" ]; then exitcode=6 errormsg $exitcode "VIP for '${iface}:vip' already defined: '$oldvip'." else AddVIP "$iface" "$vip" "$netmask" "$broadcast" fi fi ;; delete) if [ "$oldvip" = "" ]; then exitcode=6 errormsg $exitcode "VIP for '${iface}:vip' not defined." else if [ "$oldvip" != "$vip" ]; then exitcode=6 errormsg $exitcode "Existing VIP '$oldvip' for '${iface}:vip' differs from VIP '$vip'." else result=`echo "$defroute" | grep "src $vip"` if [ "$result" != "" ]; then result=`echo "$defroute" | sed 's|src '$vip'||'` $iproute route replace $result fi DeleteVIP "$iface" "$vip" "$netmask" fi fi ;; *) exitcode=2 errormsg $exitcode "Unknown action: '$action'." esac fi fi fi fi # Cleanup and exit Cleanup exit $exitcode