mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			561 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			561 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env bash
 | |
| # $Id: ipassoc_vlan.sh 9804 2010-06-22 18:36:49Z alex $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/network/domr/ipassoc_vlan.sh $
 | |
| # ipassoc.sh -- associate/disassociate a public ip with an instance
 | |
| #
 | |
| #
 | |
| # @VERSION@
 | |
| 
 | |
| # set -x
 | |
| usage() {
 | |
|   printf "Usage:\n %s -A  -i <domR eth1 ip>  -l <public-ip-address>  -r <domr name> [-f] \n" $(basename $0) >&2
 | |
|   printf " %s -D -i <domR eth1 ip> -l <public-ip-address> -r <domr name> [-f] \n" $(basename $0) >&2
 | |
|   printf "If associating first IP in vlan or disassociating last IP in vlan, the following are required: -v <vlan id> -g <vlan gateway> -n <vlan netmask> \n" $(basename $0) >&2
 | |
| }
 | |
| 
 | |
| cert="/root/.ssh/id_rsa.cloud"
 | |
| 
 | |
| get_value() {
 | |
|   local filename=$1
 | |
|   local keyname=$2
 | |
|   grep -i $keyname= $filename | cut -d= -f2
 | |
| }
 | |
| 
 | |
| #verify if supplied ip is indeed in the public domain
 | |
| check_public_ip() {
 | |
|  if [[ $(expr match $1 "10.") -gt 0 ]] 
 | |
|   then
 | |
|     echo "Public IP ($1) cannot be a private IP address!\n"
 | |
|     exit 1
 | |
|   fi
 | |
| }
 | |
| 
 | |
| #ensure that dom0 is set up to do routing and proxy arp
 | |
| check_ip_fw () {
 | |
|   if [ $(cat /proc/sys/net/ipv4/ip_forward) != 1 ];
 | |
|   then
 | |
|     printf "Warning. Dom0 not set up to do forwarding.\n" >&2
 | |
|     printf "Executing: echo 1 > /proc/sys/net/ipv4/ip_forward\n" >&2
 | |
|     printf "To make this permanent, set net.ipv4.ip_forward = 1 in /etc/sysctl.conf\n" >&2
 | |
|     echo 1 > /proc/sys/net/ipv4/ip_forward
 | |
|   fi
 | |
|   #if [ $(cat /proc/sys/net/ipv4/conf/eth0/proxy_arp) != 1 ];
 | |
|   #then
 | |
|     #printf "Warning. Dom0 not set up to do proxy ARP.\n"
 | |
|     #printf "Executing: echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp\n"
 | |
|     #printf "To make this permanent, set net.ipv4.conf.eth0.proxy_arp = 1 in /etc/sysctl.conf\n"
 | |
|     #echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
 | |
|   #fi
 | |
| }
 | |
| 
 | |
| 
 | |
| # check if gateway domain is up and running
 | |
| check_gw() {
 | |
|   ping -c 1 -n -q $1 > /dev/null
 | |
|   if [ $? -gt 0 ]
 | |
|   then
 | |
|     sleep 1
 | |
|     ping -c 1 -n -q $1 > /dev/null
 | |
|   fi
 | |
|   return $?;
 | |
| }
 | |
| 
 | |
| #Add the NAT entries into iptables in the routing domain
 | |
| add_nat_entry() {
 | |
|   local dRIp=$1
 | |
|   local pubIp=$2
 | |
|    ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$dRIp "\
 | |
|       ip addr add dev eth2 $pubIp
 | |
|       iptables -t nat -I POSTROUTING   -j SNAT -o eth2 --to-source $pubIp ;
 | |
|       /sbin/arping -c 3 -I eth2 -A -U -s $pubIp $pubIp;
 | |
|      "
 | |
|   if [ $? -gt 0  -a $? -ne 2 ]
 | |
|   then
 | |
|      return 1
 | |
|   fi
 | |
| 
 | |
|   return 0
 | |
| }
 | |
| 
 | |
| #remove the NAT entries into iptables in the routing domain
 | |
| del_nat_entry() {
 | |
|   local dRIp=$1
 | |
|   local pubIp=$2
 | |
|    ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$dRIp "\
 | |
|       iptables -t nat -D POSTROUTING   -j SNAT -o eth2 --to-source $pubIp;
 | |
|       ip addr del dev eth2 $pubIp/32
 | |
|      "
 | |
|  
 | |
|   if [ $? -gt 0  -a $? -ne 2 ]
 | |
|   then
 | |
|      return 1
 | |
|   fi
 | |
| 
 | |
|   return $?
 | |
| }
 | |
| 
 | |
| _vifname() {
 | |
|  local vmname=$1
 | |
|  local domid=$(xm domid $vmname)
 | |
|  echo vif${domid}
 | |
| }
 | |
| 
 | |
| add_acct_rule() {
 | |
|   local vmname=$1
 | |
|   local intf=$2
 | |
|   local dstip=$3
 | |
| 
 | |
|   local vifname=$(_vifname $vmname)
 | |
| 
 | |
|   iptables -A FORWARD -m physdev  --physdev-out $vifname.$intf -d $dstip -j ACCEPT
 | |
| 
 | |
|   return $?
 | |
| }
 | |
| 
 | |
| remove_acct_rule() {
 | |
|   local vmname=$1
 | |
|   local intf=$2
 | |
|   local dstip=$3
 | |
| 
 | |
|   local vifname=$(_vifname $vmname)
 | |
| 
 | |
|   iptables -D FORWARD -m physdev  --physdev-out $vifname.$intf -d $dstip -j ACCEPT
 | |
| 
 | |
|   return $?
 | |
| }
 | |
| 
 | |
| add_first_ip() {
 | |
|   local domRname=$1
 | |
|   local domRIp=$2
 | |
|   local publicIp=$3
 | |
|   local eth2mac=$4
 | |
|   local vifname=""
 | |
|   local domid=0
 | |
| 
 | |
|   if  ! xm list $domRname  &>/dev/null
 | |
|   then
 | |
|     printf "Error: routing domain $domRname does not exist\n" >&2
 | |
|     exit 2
 | |
|   fi
 | |
| 
 | |
| 
 | |
|   #check_public_ip "$publicIp"
 | |
| 
 | |
|     
 | |
|   # Ensure that dom0 is set up to do routing
 | |
|   #check_ip_fw
 | |
|    
 | |
|   
 | |
|   #program ip tables in domR and route in dom0
 | |
|   if  ! add_nat_entry $domRIp $publicIp 
 | |
|   then
 | |
|      printf  "Unable add nat entry on gateway, exiting\n" >&2
 | |
|      return 4
 | |
|   fi
 | |
| 
 | |
|   return 0
 | |
| }
 | |
| 
 | |
| check_if_ip_assigned_to_vif() {
 | |
| 		local domRIp=$1
 | |
|         local vif=$2
 | |
|         local ip=$3
 | |
| 
 | |
|         local vifIp=$(ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domRIp "\
 | |
|                                 text=\$(ifconfig $vif | grep \"inet addr\" | cut -d: -f2); \
 | |
|                                 ip="none"; \
 | |
|                                 for i in \$text; do ip=\$i; break; done; \
 | |
|                                 echo \$ip;")
 | |
| 
 | |
|         if [ "$ip" == "$vifIp" ]
 | |
|         then
 | |
|             	return 0
 | |
|         else
 | |
|             	return 1
 | |
|         fi
 | |
| }
 | |
| 
 | |
| 
 | |
| add_an_ip () {
 | |
|   local dRIp=$1
 | |
|   local pubIp=$2
 | |
|   local vif=$3
 | |
|   local vflag=$4
 | |
|   local vlanNetmask=$5
 | |
|   
 | |
|    ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$dRIp "\
 | |
|       ip addr add dev $vif $pubIp; \
 | |
|       if [ "$vflag" == "1" ]; then ifconfig $vif netmask $vlanNetmask up; fi; \
 | |
|       /sbin/arping -c 3 -I $vif -A -U -s $pubIp $pubIp; \
 | |
|      "
 | |
|    return $?
 | |
| }
 | |
| 
 | |
| number_of_bits() {
 | |
|         local decNum=$1
 | |
| 
 | |
|         local bits=0
 | |
|         while [ $decNum -gt 0 ]
 | |
|         do
 | |
|           	local lastBit=$(expr $decNum % 2)
 | |
|                 if [ "$lastBit" == "1" ]
 | |
|                 then
 | |
|                     	let bits+=1
 | |
|                 fi
 | |
|                 let decNum=$decNum/2
 | |
|         done
 | |
| 
 | |
| 	echo $bits
 | |
| }
 | |
| 
 | |
| netmask_to_cidr() {
 | |
|         local netmask=$1
 | |
| 
 | |
|         local cidr=0
 | |
|         local IFS=.
 | |
|         for octet in $netmask
 | |
|         do
 | |
|                 local octetBits=$(number_of_bits $octet)
 | |
|                 let cidr+=$octetBits
 | |
|         done
 | |
| 
 | |
|         echo $cidr
 | |
| }
 | |
| 
 | |
| 
 | |
| remove_an_ip () {
 | |
|   local dRIp=$1
 | |
|   local pubIp=$2
 | |
|   local vif=$3
 | |
|   local vlanNetmask=$4
 | |
|   
 | |
|   # Check if the public IP is assigned to the VIF itself
 | |
|   check_if_ip_assigned_to_vif $dRIp $vif $pubIp
 | |
|   
 | |
|   if [ $? -eq 0 ]
 | |
|   then
 | |
| 	# Convert the VLAN netmask to a CIDR
 | |
| 	local cidr=$(netmask_to_cidr $vlanNetmask)
 | |
| 	
 | |
| 	# Delete the IP address by providing the correct CIDR (not 32 in this case)
 | |
| 	# Then, set the correct netmask on the VIF, since at this point it will have a netmask of 255.255.255.255
 | |
| 	# Finally, detect what the new IP address on the VIF is, and correct the ifcfg-VIF file to reflect this
 | |
| 	
 | |
| 	ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$dRIp "\
 | |
| 		ip addr del dev $vif $pubIp/$cidr; \
 | |
| 		ifconfig $vif netmask $vlanNetmask up; \
 | |
| 		text=\$(ifconfig $vif | grep \"inet addr\" | cut -d: -f2); \
 | |
| 		ip="none"; \
 | |
| 		for i in \$text; do ip=\$i; break; done; \
 | |
| 		sed -i /IPADDR/d /etc/sysconfig/network-scripts/ifcfg-$vif; \
 | |
| 		echo "IPADDR=\$ip" >> /etc/sysconfig/network-scripts/ifcfg-$vif; \
 | |
| 	"
 | |
|   else
 | |
| 	ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$dRIp "\
 | |
| 		ip addr del dev $vif $pubIp/32
 | |
| 	"
 | |
|   fi
 | |
|   
 | |
|   if [ $? -gt 0  -a $? -ne 2 ]
 | |
|   then
 | |
|      return 1
 | |
|   fi
 | |
| }
 | |
| 
 | |
| attach_bridge_to_domr() {
 | |
| 	local domRName=$1
 | |
| 	local domRIp=$2
 | |
| 	local vlanId=$3
 | |
| 	local vlanGateway=$4
 | |
| 	local vlanNetmask=$5
 | |
| 	local publicIp=$6
 | |
| 	
 | |
| 	local bridgeName=xenbr1.$vlanId
 | |
| 	
 | |
| 	xm network-attach $domRName bridge=$bridgeName 
 | |
| 	
 | |
| 	if [ $? -gt 0 ]
 | |
| 	then
 | |
| 		return 1
 | |
| 	fi
 | |
| 	
 | |
| 	# Figure out what VIF we just added! It will be the only VIF that does not have an IP address assigned in ifcfg-eth*, since we haven't created any ifcfg-eth* file yet.
 | |
| 	local newVif="none"
 | |
| 	local vifList=$(get_vif_list $domRIp)
 | |
| 	
 | |
| 	for i in $vifList
 | |
| 	do
 | |
| 		local vif=$(echo $i | cut -d: -f1)
 | |
| 		local vifIp=$(echo $i | cut -d: -f2)
 | |
| 		
 | |
| 		if [ "$vifIp" == "" ]
 | |
| 		then
 | |
| 			newVif="$vif"
 | |
| 			break
 | |
| 		fi
 | |
| 	done
 | |
| 	
 | |
| 	if [ "$newVif" == "none" ]
 | |
| 	then
 | |
| 		echo "Could not detect newly added VIF"
 | |
| 		exit 1
 | |
| 	fi
 | |
| 	
 | |
| 	local ifcfgFilePath="/etc/sysconfig/network-scripts/ifcfg-$newVif"
 | |
| 	
 | |
| 	# Via SSH: Create ifcfg-eth* file and add vlanGateway to /etc/sysconfig/network
 | |
| 	ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domRIp "\
 | |
| 		touch $ifcfgFilePath; \
 | |
| 		echo "DEVICE=$newVif" >> $ifcfgFilePath; \
 | |
| 		echo "ONBOOT=yes" >> $ifcfgFilePath; \
 | |
| 		echo "TYPE=Ethernet" >> $ifcfgFilePath; \
 | |
| 		echo "IPADDR=$publicIp" >> $ifcfgFilePath; \
 | |
| 		echo "NETMASK=$vlanNetmask" >> $ifcfgFilePath; \
 | |
| 		echo "GATEWAY=$vlanGateway" >> /etc/sysconfig/network; \
 | |
| 	"
 | |
| 	
 | |
| 	if [ $? -gt 0 ]
 | |
| 	then
 | |
| 		echo "Could not create ifcfg-eth* file for newly added VIF"
 | |
| 		exit 1
 | |
| 	fi
 | |
| 	
 | |
| 	return $?
 | |
| }
 | |
| 
 | |
| get_vif_id() {
 | |
| 	local domRIp=$1
 | |
| 	local domRName=$2
 | |
| 	local vifName=$3
 | |
| 
 | |
| 	# First get the MAC address of the VIF from DomR
 | |
| 	local command="\
 | |
| 		macAddrOfVif=\"none\"; \
 | |
| 		for i in \$(ifconfig $vifName | grep HWaddr); do macAddrOfVif=\$i; done; \
 | |
| 		echo \$macAddrOfVif;"
 | |
| 
 | |
| 	local macAddr=$(ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domRIp "$command")
 | |
| 
 | |
| 	if [ "$macAddr" == "none" ]
 | |
| 	then
 | |
| 		echo "none"
 | |
| 		return
 | |
| 	fi
 | |
| 
 | |
| 	# Do xm network-list and find the vif ID that corresponds to the MAC address
 | |
| 	local vifId="none"
 | |
| 	local networkList=$(xm network-list $domRName | grep -i "$macAddr")
 | |
| 	for i in $networkList; do vifId=$i; break; done;
 | |
| 
 | |
| 	echo $vifId
 | |
| }
 | |
| 
 | |
| detach_bridge_from_domr() {
 | |
| 	local domRName=$1
 | |
| 	local domRIp=$2
 | |
| 	local vlanGateway=$3
 | |
| 	local correctVif=$4
 | |
| 
 | |
| 	local vifId=$(get_vif_id $domRIp $domRName $correctVif)
 | |
| 	
 | |
| 	xm network-detach $domRName $vifId
 | |
| 	
 | |
| 	if [ $? -gt 0 ]
 | |
| 	then
 | |
| 		return 1
 | |
| 	fi
 | |
| 	
 | |
| 	# Remove ifcfg-eth* file and vlanGateway from /etc/sysconfig/network via SSH
 | |
| 	ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domRIp "\
 | |
| 		rm /etc/sysconfig/network-scripts/ifcfg-$correctVif;
 | |
| 		sed -i /"GATEWAY=$vlanGateway"/d /etc/sysconfig/network;
 | |
| 	"
 | |
| 	
 | |
| 	return $?
 | |
| }
 | |
| 
 | |
| get_subnet() {
 | |
| 	local ip=$1
 | |
| 	local netmask=$2
 | |
| 
 | |
| 	local ip1=($(echo $ip | awk -F"." '{print $1,$2,$3,$4}'))
 | |
| 	local netmask1=($(echo $netmask | awk -F"." '{print $1,$2,$3,$4}'))
 | |
| 	local subnet=$((${ip1[0]} & ${netmask1[0]})).$((${ip1[1]} & ${netmask1[1]})).$((${ip1[2]} & ${netmask1[2]})).$((${ip1[3]} & ${netmask1[3]}))
 | |
| 
 | |
| 	echo $subnet
 | |
| }
 | |
| 
 | |
| get_vif_list() {
 | |
|         local domRIp=$1
 | |
| 
 | |
|         local command=" vifListDomR=\"\"; \
 | |
|                                         for i in /sys/class/net/eth*; do \
 | |
|                                                 vif=\$(basename \$i); \
 | |
|                                                 vifIp=\$(grep -i IPADDR= /etc/sysconfig/network-scripts/ifcfg-\$vif | cut -d= -f2); \
 | |
|                                                 vifNetmask=\$(grep -i NETMASK= /etc/sysconfig/network-scripts/ifcfg-\$vif | cut -d= -f2); \
 | |
|                                                 vifListDomR=\$vifListDomR\" \$vif:\$vifIp:\$vifNetmask\"; \
 | |
|                                         done; \
 | |
|                                         echo \$vifListDomR;"
 | |
| 
 | |
|         local vifList=$(ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domRIp $command)
 | |
| 
 | |
|         echo $vifList
 | |
| }
 | |
| 
 | |
| find_correct_vif() {
 | |
| 	local domRIp=$1
 | |
| 	local publicIp=$2
 | |
| 	local vlanNetmask=$3
 | |
| 	
 | |
| 	local correctVif="none"
 | |
| 	
 | |
| 	local vlanSubnet=$(get_subnet $publicIp $vlanNetmask)
 | |
| 	local vifList=$(get_vif_list $domRIp)
 | |
| 
 | |
| 	for i in $vifList
 | |
| 	do
 | |
| 		local vif=$(echo $i | cut -d: -f1)
 | |
| 		local vifIp=$(echo $i | cut -d: -f2)
 | |
| 		local vifNetmask=$(echo $i | cut -d: -f3)
 | |
| 		local vifSubnet=$(get_subnet $vifIp $vifNetmask)
 | |
| 		
 | |
| 		if [ "$vlanSubnet" == "$vifSubnet" ]
 | |
| 		then
 | |
| 			correctVif="$vif"
 | |
| 			break
 | |
| 		fi
 | |
| 	done
 | |
| 	
 | |
| 	echo $correctVif
 | |
| }
 | |
| 
 | |
| #set -x
 | |
| 
 | |
| fflag=
 | |
| Aflag=
 | |
| Dflag=
 | |
| rflag=
 | |
| iflag=
 | |
| aflag=
 | |
| lflag=
 | |
| vflag=0
 | |
| gflag=
 | |
| nflag=
 | |
| op=""
 | |
| 
 | |
| while getopts 'fADr:i:a:l:v:g:n:' OPTION
 | |
| do
 | |
|   case $OPTION in
 | |
|   A)	Aflag=1
 | |
| 		op="-A"
 | |
| 		;;
 | |
|   D)	Dflag=1
 | |
| 		op="-D"
 | |
| 		;;
 | |
|   f)	fflag=1
 | |
| 		;;
 | |
|   r)	rflag=1
 | |
| 		domRname="$OPTARG"
 | |
| 		;;
 | |
|   i)	iflag=1
 | |
| 		domRIp="$OPTARG"
 | |
| 		;;
 | |
|   l)	lflag=1
 | |
| 		publicIp="$OPTARG"
 | |
| 		;;
 | |
|   a)	aflag=1
 | |
| 		eth2mac="$OPTARG"
 | |
| 		;;
 | |
|   v)	vflag=1
 | |
|   		vlanId="$OPTARG"
 | |
|   		;;
 | |
|   g)	gflag=1	
 | |
|   		gateway="$OPTARG"
 | |
|   		;;
 | |
|   n)	nflag=1
 | |
|   		netmask="$OPTARG"
 | |
|   		;;
 | |
|   ?)	usage
 | |
| 		exit 2
 | |
| 		;;
 | |
|   esac
 | |
| done
 | |
| 
 | |
| #Either the A flag or the D flag but not both
 | |
| if [ "$Aflag$Dflag" != "1" ]
 | |
| then
 | |
|  usage
 | |
|  exit 2
 | |
| fi
 | |
| 
 | |
| if [ "$Aflag$lflag$iflag$rflag$nflag" != "11111" ] && [ "$Dflag$lflag$iflag$rflag$nflag" != "11111" ]
 | |
| then
 | |
|    exit 2
 | |
| fi
 | |
| 
 | |
| # If a vlanId is passed in, then a vlanGateway must be passed in
 | |
| if [ "$vflag" == "1" ] && [ "$gflag" != "1" ]
 | |
| then
 | |
| 	usage
 | |
| 	exit 2
 | |
| fi
 | |
| 
 | |
| # check if gateway domain is up and running
 | |
| if ! check_gw "$domRIp"
 | |
| then
 | |
|    printf "Unable to ping the routing domain, exiting\n" >&2
 | |
|    exit 3
 | |
| fi
 | |
| 
 | |
| # If this is an add and a vlanId was passed in, hotplug a new vif on DomR
 | |
| if [ "$Aflag" == "1" ] && [ "$vflag" == "1" ]
 | |
| then
 | |
| 	attach_bridge_to_domr $domRname $domRIp $vlanId $gateway $netmask $publicIp
 | |
|   	
 | |
| 	if [ $? -gt 0 ]
 | |
| 	then
 | |
| 		exit 1
 | |
| 	fi
 | |
| fi
 | |
| 
 | |
| # Find the VIF that we need to use on DomR
 | |
| correctVif=$(find_correct_vif $domRIp $publicIp $netmask)
 | |
| 
 | |
| if [ "$fflag" == "1" ] && [ "$Aflag" == "1" ]
 | |
| then
 | |
|   add_nat_entry $domRIp $publicIp 
 | |
|   exit $?
 | |
| fi
 | |
| 
 | |
| if [ "$Aflag" == "1" ]
 | |
| then  
 | |
|   add_an_ip $domRIp $publicIp $correctVif $vflag $netmask
 | |
|   exit $?
 | |
| fi
 | |
| 
 | |
| if [ "$fflag" == "1" ] && [ "$Dflag" == "1" ]
 | |
| then
 | |
|   del_nat_entry $domRIp $publicIp 
 | |
|   exit $?
 | |
| fi
 | |
| 
 | |
| if [ "$Dflag" == "1" ]
 | |
| then
 | |
|   remove_an_ip $domRIp $publicIp $correctVif $netmask
 | |
|   
 | |
|   # If a vlanId was passed in, remove the vlan's vif from DomR
 | |
|   if [ "$vflag" == "1" ]
 | |
|   then
 | |
|   	detach_bridge_from_domr $domRname $domRIp $gateway $correctVif
 | |
|   	
 | |
| 	if [ $? -gt 0 ]
 | |
| 	then
 | |
| 		exit 1
 | |
| 	fi
 | |
|   fi
 | |
|   
 | |
|   exit $?
 | |
| fi
 | |
| 
 | |
| exit 0
 | |
| 
 |