#!/bin/bash #============================================================================ # xend-network # # Version = 1.1.1 # Date = 2008-01-10 # # Maintainer(s) = Ron Terry - ron (at) pronetworkconsulting (dot) com # # The latest version can be found at: # # http://pronetworkconsulting.com/linux/scripts/network-multinet.html # # Description: # # This script creates, deletes, and modifies virtual networks on the fly # without having to restart the Xen network script. The same functions # are used to create/delete virtual networks in this script as are used # in the network-multinet network script. # # Vars: # # SCRIPT_PATH- -Path to the directory that contains the Xen # network helper scripts # # DEFAULT_SNM -Default subnet mask value to use (number of bits) # if not defined from the command line # # MODE -Mode that the xend-network script is running in: # (add, del, delall, mod, show) # # NET_DEV -Network interface name # NET_DEV_MAC -MAC address to be assigned to the network interface # NET_DEV_IP -IP address to be assigned to the network interface # NET_TYPE -Type of netowrk # (bridge, nat, hostonly, route, nohost, empty) # NET_NUMBER -Number of the specifed network type # NET_NAME -Name of the specified network # (xenbr, xennat, xenhost, xenroute, xennohost, xenempty) # NAT_EXTERNAL_INTERFACE -Network interface to masquerade all NAT network # trafic with # NET_DHCP_SRV -Parameter defining whether or not the DHCP server # should be enabled on the specified network: # (dhcp-on, dhcp-off) #============================================================================ #### Read config files and set variables ################################## SCRIPT_PATH="/etc/xen/scripts" DEFAULT_SNM="24" . $SCRIPT_PATH/multinet-common.sh #### Script Functions ##################################################### usage() { echo "Usage: xend-network add|del|mod {options}" echo echo " Options: -t :bridged|nat|hostonly|routed|nohost|empty" echo " -i :Virtual network interface - vethX" echo " (for nat, hostonly and routed bridges only)" echo " -I :Physical network interface - ethX" echo " (for bridged and nohost bridges only)" echo " -m :MAC address" echo " (for nat, hostonly and routed bridges only)" echo " -a :IP address" echo " (for nat, hostonly and routed bridges only)" echo " -n :Bridge number (optional)" echo " -N :Bridge name (optional)" echo " -M :New Bridge name (used with rename option only)" echo " -e :External network interface" echo " (optional - for nat and routed networks only)" echo " -d :Enable DHCP on this network" echo echo "Examples:" echo echo " bridged network: xend-network add -t bridge -i eth0" echo " nat network: xend-network add -t nat -i veth0 -m 00:11:22:aa:bb:cc -a 10.0.0.1" echo " hostonly network: xend-network add -t hostonly -i veth0 -m 00:11:22:aa:bb:cc -a 10.0.0.1" echo " routed network: xend-network add -t route -i veth0 -m 00:11:22:aa:bb:cc -a 10.0.0.1" echo " nohost network: xend-network add -t nohost -i eth0" echo " empty network: xend-network add -t empty" echo " empty network: xend-network del -N nat1" } get_mode() { if ! [ -z "$1" ] && ! echo "$1" | grep -q "^-" then case $1 in add) MODE="add" echo "Running in add mode" ;; del) MODE="del" echo "Running in delete mode" ;; delall) MODE="delall" echo "Running in delete-all mode" ;; mod) MODE="mod" echo "Running in modify mode" ;; show) MODE="show" echo "Running in show mode" ;; esac shift echo "Options: $*" get_options $* else usage exit 1 fi } get_options() { while getopts "t:i:I:m:a:n:N:M:e:dh" OPTIONS do case $OPTIONS in i) NET_DEV=$OPTARG echo "Network Interface = $NET_DEV" echo "----------------------------" ;; I) NET_DEV=$OPTARG echo "Network Interface = $NET_DEV" echo "----------------------------" ;; m) NET_DEV_MAC=$OPTARG echo "MAC Address = $NET_DEV_MAC" echo "----------------------------" ;; a) NET_DEV_IP=$OPTARG echo "IP Address = $NET_DEV_IP" echo "----------------------------" ;; t) NET_TYPE=$OPTARG echo "Network type = $NET_TYPE" echo "----------------------------" ;; n) NET_NUMBER=$OPTARG echo "Number of Network Type = $NET_NUMBER" echo "----------------------------" ;; N) NET_NAME=$OPTARG echo "Network Name = $NET_NAME" echo "----------------------------" ;; M) NEW_NET_NAME=$OPTARG echo "New Network Name = $NEW_NET_NAME" echo "----------------------------" ;; e) NAT_EXTERNAL_INTERFACE=$OPTARG echo "NAT External Interface = $NAT_EXTERNAL_INTERFACE" echo "----------------------------" ;; d) NET_DHCP_SRV="dhcp-on" ;; h) usage exit 0 ;; esac done if [ -z $NET_DHCP_SRV ] then NET_DHCP_SRV="dhcp-off" fi } #***** Address Generating Functions *************************************** gen_mac_addr() { local RANDOM=`od -An -N2 -i /dev/random` local MAC="00:16:3E" MAC="$MAC:"`printf "%02X\n" $[ ( $RANDOM % 255 ) + 1 ] ` MAC="$MAC:"`printf "%02X\n" $[ ( $RANDOM % 255 ) + 1 ] ` MAC="$MAC:"`printf "%02X\n" $[ ( $RANDOM % 255 ) + 1 ] ` echo $MAC #NET_DEV_MAC="$MAC" } gen_ip_addr(){ local DUP="" until [ "$DUP" = "N" ] do local IP=10.$(( 1+(`od -An -N2 -i /dev/random` )%(254-1+1) )).$(( 1+(`od -An -N2 -i /dev/random` )%(254-1+1) )).$(( 1+(`od -An -N2 -i /dev/random` )%(254-1+1) )) local NET_ID=`echo $IP|cut -d "." -f 1-3`.0\/$DEFAULT_SNM if ! ip route show | grep "$NET_ID" && ! ip addr show | grep "$IP" then DUP="N" fi done echo "$IP"/$DEFAULT_SNM #NET_DEV_IP="$IP"\/24 } #***** Option Finding Functions ******************************************* find_next_net_number() { # Variables passed in (only one of the following): # $BRIDGE_NAME $NAT_NAME $HOSTONLY_NAME $ROUTE_NAME $NOHOST_NAME $EMPTY_NAME local TYPE_NAME="$1" if [ -z $NET_NUMBER ] then local BRIDGE_TYPE_LIST=`ip addr show | grep ".*: $TYPE_NAME" | cut -d ":" -f 2 | cut -d " " -f 2` for BRIDGE in $BRIDGE_TYPE_LIST do NET_NUMBER=${BRIDGE##${BRIDGE%%[0-9]*}} done ((NET_NUMBER++)) if [ "$NET_NUMBER" -eq "1" ] && ! ip addr show | grep -q ".*: $TYPE_NAME"0 then #((NET_NUMBER--)) NET_NUMBER="0" fi fi } find_next_net_device() { # Variables passed in (only one fo the following): # $BRIDGE_NAME $NAT_NAME $HOSTONLY_NAME $ROUTE_NAME $NOHOST_NAME local DEV_NUMBER local TYPE_NAME="$1" if [ -z $NET_DEV ] then case $NET_TYPE in bridge|nohost) DEV_NAME="$DEFAULT_PDEV" ;; nat|hostonly|route) DEV_NAME="$DEFAULT_VDEV" ;; esac local DEV_LIST=`ip addr show | grep ".*: $DEV_NAME" | cut -d ":" -f 2 | cut -d " " -f 2` for DEVICE in $DEV_LIST do DEV_NUMBER=${DEVICE##${DEVICE%%[0-9]*}} done NEXT_DEV_NUMBER="$DEV_NUMBER" ((NEXT_DEV_NUMBER++)) case $NET_TYPE in bridge|nohost) if ! ip addr show | grep -q ".*: $DEV_NAME$DEV_NUMBER" && ! ip addr show | grep -q ".*: $TYPE_NAME$DEV_NUMBER" then NET_DEV="$DEFAULT_DEV$DEV_NUMBER" VIF_COUNT="$DEV_NUMBER" else NET_DEV="$DEFAULT_DEV$NEXT_DEV_NUMBER" VIF_COUNT="$NEXT_DEV_NUMBER" fi ;; nat|hostonly|route) if ! ip addr show | grep -q ".*: $TYPE_NAME$DEV_NUMBER" then NET_DEV="$DEV_NAME$DEV_NUMBER" VIF_COUNT="$DEV_NUMBER" else NET_DEV="$DEV_NAME$NEXT_DEV_NUMBER" VIF_COUNT="$NEXT_DEV_NUMBER" fi ;; esac fi } find_network_type() { if echo "$1" | grep -q "$BRIDGE_NAME" then NET_TYPE="bridge" elif echo "$1" | grep -q "$NAT_NAME" then NET_TYPE="nat" elif echo "$1" | grep -q "$HOSTONLY_NAME" then NET_TYPE="hostonly" elif echo "$1" | grep -q "$ROUTE_NAME" then NET_TYPE="route" elif echo "$1" | grep -q "$NOHOST_NAME" then NET_TYPE="nohost" elif echo "$1" | grep -q "$EMPTY_NAME" then NET_TYPE="empty" fi } #***** Network Creation/Deletion Functions ******************************** create_network() { # The variable CMD_OPT must be set to one of the following before calling # this function: start, stop, status case $MODE in add) case $NET_TYPE in bridge) find_next_net_number $BRIDGE_NAME find_next_net_device $BRIDGE_NAME echo "Creating network of type: $NET_TYPE" echo " Named: $BRIDGE_NAME$NET_NUMBER" echo " On interface: $NET_DEV" echo " Switchport: vif0.$VIF_COUNT" # Create the network #--------------------------------------------------------------------- create_bridged_networks $NET_DEV $NET_NUMBER ;; nat|hostonly|route) if [ -z $NET_NUMBER ] then case $NET_TYPE in nat) find_next_net_number $NAT_NAME find_next_net_device $NAT_NAME ;; hostonly) find_next_net_number $HOSTONLY_NAME find_next_net_device $HOSTONLY_NAME ;; route) find_next_net_number $ROUTE_NAME find_next_net_device $ROUTE_NAME ;; esac fi if [ -z $NET_DEV_MAC ] then echo "No MAC address was not supplied. Generating MAC" NET_DEV_MAC="`gen_mac_addr`" fi if [ -z $NET_DEV_IP ] then echo "The IP address was not supplied. Generating IP" NET_DEV_IP="`gen_ip_addr`" fi echo "Creating network of type: $NET_TYPE" case $NET_TYPE in nat) echo " Named: $NAT_NAME$NET_NUMBER" ;; hostonly) echo " Named: $HOSTONLY_NAME$NET_NUMBER" ;; route) echo " Named: $ROUTE_NAME$NET_NUMBER" ;; esac echo " On interface: $NET_DEV" echo " Switchport: vif0.$VIF_COUNT" echo " MAC Addr: $NET_DEV_MAC" echo " IP Address: $NET_DEV_IP" echo " DHCP: $NET_DHCP_SRV" # Create the network #--------------------------------------------------------------------- create_local_networks $NET_DEV $NET_TYPE $NET_NUMBER $NET_DEV_MAC $NET_DEV_IP $NET_DHCP_SRV ;; nohost) if [ -z $NET_NUMBER ] then find_next_net_number $NOHOST_NAME fi find_next_net_device $NOHOST_NAME echo "Creating network of type: $NET_TYPE" echo " Named: $NOHOST_NAME$NET_NUMBER" echo " On interface: $NET_DEV" # Create the network #--------------------------------------------------------------------- create_nohost_networks $NET_DEV $NET_NUMBER ;; empty) if [ -z $NET_NUMBER ] then find_next_net_number $EMPTY_NAME fi echo "Creating network of type: $NET_TYPE" echo " Named: $EMPTY_NAME$NET_NUMBER" # Create the network #--------------------------------------------------------------------- create_empty_networks $NET_NUMBER ;; *) echo "Error: Incorrect Bridge Type: $NET_TYPE" exit 1 ;; esac ;; del) VIF_COUNT=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 2` NET_TYPE=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 3` NET_NUMBER=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 4` NET_DEV=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 5` NET_DEV_MAC=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 6` NET_DEV_IP=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 7` NET_DEV_DHCP_SRV=`grep $NET_NAME $NETWORK_SAVE_FILE | cut -d "," -f 8` echo "Removing network: $NET_NAME" # Remove the network #--------------------------------------------------------------------- case $NET_TYPE in bridge) create_bridged_networks $NET_DEV $NET_NUMBER ;; nat|hostonly|route) create_local_networks $NET_DEV $NET_TYPE $NET_NUMBER $NET_DEV_MAC $NET_DEV_IP $NET_DHCP_SRV ;; nohost) create_nohost_networks $NET_DEV $NET_NUMBER ;; empty) create_empty_networks $NET_NUMBER ;; esac ;; esac } #***** Network Renameing Functions **************************************** modify_network() { echo echo "Modifying networks is currently unsupported." echo } #***** Network Showing Functions ****************************************** show_networks() { ACTIVE_NETWORK_LIST=`ip addr show | grep "xen" | cut -d ":" -f 2 | cut -d " " -f 2` echo echo "--------------------------------------" echo " Active Virtual Networks" echo "--------------------------------------" for NET in $ACTIVE_NETWORK_LIST do echo $NET echo done } #### Main Code Body ####################################################### get_mode $* touch $NETWORK_SAVE_FILE case $MODE in add) CMD_OPT="start" create_network ;; del) CMD_OPT="stop" create_network ;; delall) CMD_OPT="stop" remove_all_networks mod) modify_network exit 0 ;; show) show_networks exit 0 ;; *) echo "Only the following modes are supported: add|del|delall|rename|show" ;; esac exit 0