2 # Common Functions used by OPNFV Apex
3 # author: Tim Rozet (trozet@redhat.com)
6 ##params: interface name
8 ip addr show $1 | grep -Eo '^\s+inet\s+[\.0-9]+' | awk '{print $2}'
11 ##finds subnet of ip and netmask
13 function find_subnet {
14 IFS=. read -r i1 i2 i3 i4 <<< "$1"
15 IFS=. read -r m1 m2 m3 m4 <<< "$2"
16 printf "%d.%d.%d.%d\n" "$((i1 & m1))" "$((i2 & m2))" "$((i3 & m3))" "$((i4 & m4))"
19 ##verify subnet has at least n IPs
20 ##params: subnet mask, n IPs
21 function verify_subnet_size {
22 IFS=. read -r i1 i2 i3 i4 <<< "$1"
25 ##this function assumes you would never need more than 254
26 ##we check here to make sure
27 if [ "$num_ips_required" -ge 254 ]; then
28 echo -e "\n\n${red}ERROR: allocating more than 254 IPs is unsupported...Exiting${reset}\n\n"
32 ##we just return if 3rd octet is not 255
33 ##because we know the subnet is big enough
34 if [ "$i3" -ne 255 ]; then
36 elif [ $((254-$i4)) -ge "$num_ips_required" ]; then
39 echo -e "\n\n${red}ERROR: Subnet is too small${reset}\n\n"
44 ##finds last usable ip (broadcast minus 1) of a subnet from an IP and netmask
45 ## Warning: This function only works for IPv4 at the moment.
47 function find_last_ip_subnet {
48 IFS=. read -r i1 i2 i3 i4 <<< "$1"
49 IFS=. read -r m1 m2 m3 m4 <<< "$2"
50 IFS=. read -r s1 s2 s3 s4 <<< "$((i1 & m1)).$((i2 & m2)).$((i3 & m3)).$((i4 & m4))"
51 printf "%d.%d.%d.%d\n" "$((255 - $m1 + $s1))" "$((255 - $m2 + $s2))" "$((255 - $m3 + $s3))" "$((255 - $m4 + $s4 - 1))"
54 ##increments subnet by a value
57 function increment_subnet {
58 IFS=. read -r i1 i2 i3 i4 <<< "$1"
59 printf "%d.%d.%d.%d\n" "$i1" "$i2" "$i3" "$((i4 | $2))"
62 ##finds netmask of interface
64 ##returns long format 255.255.x.x
65 function find_netmask {
66 ifconfig $1 | grep -Eo 'netmask\s+[\.0-9]+' | awk '{print $2}'
69 ##finds short netmask of interface
71 ##returns short format, ex: /21
72 function find_short_netmask {
73 echo "/$(ip addr show $1 | grep -Eo '^\s+inet\s+[\/\.0-9]+' | awk '{print $2}' | cut -d / -f2)"
78 ##assumes a /24 subnet
80 baseaddr="$(echo $1 | cut -d. -f1-3)"
81 lsv="$(echo $1 | cut -d. -f4)"
82 if [ "$lsv" -ge 254 ]; then
89 ##subtracts a value from an IP address
90 ##params: last ip, ip_count
91 ##assumes ip_count is less than the last octect of the address
93 IFS=. read -r i1 i2 i3 i4 <<< "$1"
95 if [ $i4 -lt $ip_count ]; then
96 echo -e "\n\n${red}ERROR: Can't subtract $ip_count from IP address $1 Exiting${reset}\n\n"
99 printf "%d.%d.%d.%d\n" "$i1" "$i2" "$i3" "$((i4 - $ip_count ))"
102 ##check if IP is in use
104 ##ping ip to get arp entry, then check arp
105 function is_ip_used {
106 ping -c 5 $1 > /dev/null 2>&1
107 arp -n | grep "$1 " | grep -iv incomplete > /dev/null 2>&1
110 ##find next usable IP
112 function next_usable_ip {
114 while [ "$new_ip" ]; do
115 if ! is_ip_used $new_ip; then
119 new_ip=$(next_ip $new_ip)
124 ##increment ip by value
125 ##params: ip, amount to increment by
126 ##increment_ip $next_private_ip 10
127 function increment_ip {
128 baseaddr="$(echo $1 | cut -d. -f1-3)"
129 lsv="$(echo $1 | cut -d. -f4)"
132 if [ "$lsv" -ge 254 ]; then
138 ##finds gateway on system
139 ##params: interface to validate gateway on (optional)
141 function find_gateway {
142 local gw gw_interface
146 gw=$(ip route | grep default | awk '{print $3}')
147 gw_interface=$(ip route get $gw | awk '{print $3}')
149 if [ "$gw_interface" == "$1" ]; then
155 ##finds subnet in CIDR notation for interface
156 ##params: interface to find CIDR
158 local cidr network ip netmask short_mask
163 netmask=$(find_netmask $1)
164 if [[ -z "$ip" || -z "$netmask" ]]; then
167 network=$(find_subnet ${ip} ${netamsk})
168 short_mask=$(find_short_netmask $1)
169 if [[ -z "$network" || -z "$short_mask" ]]; then
172 cidr="${subnet}'\'${short_mask}"
176 ##finds block of usable IP addresses for an interface
177 ##simply returns at the moment the correct format
178 ##after first 20 IPs, and leave 20 IPs at end of subnet (for floating ips, etc)
179 ##params: interface to find IP
180 function find_usable_ip_range {
181 local interface_ip subnet_mask first_block_ip last_block_ip
185 interface_ip=$(find_ip $1)
186 subnet_mask=$(find_netmask $1)
187 if [[ -z "$interface_ip" || -z "$subnet_mask" ]]; then
190 interface_ip=$(increment_ip ${interface_ip} 20)
191 first_block_ip=$(next_usable_ip ${interface_ip})
192 if [ -z "$first_block_ip" ]; then
195 last_block_ip=$(find_last_ip_subnet ${interface_ip} ${subnet_mask})
196 if [ -z "$last_block_ip" ]; then
199 last_block_ip=$(subtract_ip ${last_block_ip} 21)
200 echo "${first_block_ip},${last_block_ip}"
205 ##generates usable IP range in correct format based on CIDR
206 ##assumes the first 20 IPs are used (by instack or otherwise)
208 function generate_usable_ip_range {
209 local first_ip first_block_ip last_block_ip
210 #first_ip=$(ipcalc -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
211 first_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
212 first_ip=$(increment_ip ${first_ip} 1)
213 first_block_ip=$(increment_ip ${first_ip} 20)
214 #last_block_ip=$(ipcalc -nb $1 | grep HostMax: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
215 last_block_ip=$(ipcalc -nmpb $1 | grep BROADCAST= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
216 last_block_ip=$(subtract_ip ${last_block_ip} 1)
217 if [[ -z "$first_block_ip" || -z "$last_block_ip" ]]; then
220 last_block_ip=$(subtract_ip ${last_block_ip} 21)
221 echo "${first_block_ip},${last_block_ip}"
225 ##find the instack IP address
226 ##finds first usable IP on subnet
228 function find_provisioner_ip {
233 interface_ip=$(find_ip $1)
234 if [ -z "$interface_ip" ]; then
237 echo $(increment_ip ${interface_ip} 1)
240 ##generates instack IP address based on CIDR
242 function generate_provisioner_ip {
244 #provisioner_ip=$(ipcalc -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
245 provisioner_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
246 if [ -z "$provisioner_ip" ]; then
249 provisioner_ip=$(increment_ip ${provisioner_ip} 1)
250 echo "$provisioner_ip"
253 ##finds the dhcp range available via interface
254 ##uses first 8 IPs, after 2nd IP
256 function find_dhcp_range {
257 local dhcp_range_start dhcp_range_end interface_ip
261 interface_ip=$(find_ip $1)
262 if [ -z "$interface_ip" ]; then
265 dhcp_range_start=$(increment_ip ${interface_ip} 2)
266 dhcp_range_end=$(increment_ip ${dhcp_range_start} 8)
267 echo "${dhcp_range_start},${dhcp_range_end}"
270 ##generates the dhcp range available via CIDR
271 ##uses first 8 IPs, after 1st IP
273 function generate_dhcp_range {
274 local dhcp_range_start dhcp_range_end first_ip
275 #first_ip=$(ipcalc -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
276 first_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
277 if [ -z "$first_ip" ]; then
280 first_ip=$(increment_ip ${first_ip} 1)
281 dhcp_range_start=$(increment_ip ${first_ip} 1)
282 dhcp_range_end=$(increment_ip ${dhcp_range_start} 8)
283 echo "${dhcp_range_start},${dhcp_range_end}"
286 ##finds the introspection range available via interface
287 ##uses 8 IPs, after the first 10 IPs
289 function find_introspection_range {
290 local inspect_range_start inspect_range_end interface_ip
294 interface_ip=$(find_ip $1)
295 if [ -z "$interface_ip" ]; then
298 inspect_range_start=$(increment_ip ${interface_ip} 10)
299 inspect_range_end=$(increment_ip ${inspect_range_start} 8)
300 echo "${inspect_range_start},${inspect_range_end}"
303 ##generate the introspection range available via CIDR
304 ##uses 8 IPs, after the first 10 IPs
306 function generate_introspection_range {
307 local inspect_range_start inspect_range_end first_ip
308 #first_ip=$(ipcalc -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
309 first_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
310 if [ -z "$first_ip" ]; then
313 first_ip=$(increment_ip ${first_ip} 1)
314 inspect_range_start=$(increment_ip ${first_ip} 10)
315 inspect_range_end=$(increment_ip ${inspect_range_start} 8)
316 echo "${inspect_range_start},${inspect_range_end}"
319 ##finds the floating ip range available via interface
320 ##uses last 20 IPs of a subnet, minus last IP
322 function find_floating_ip_range {
323 local float_range_start float_range_end interface_ip subnet_mask
327 interface_ip=$(find_ip $1)
328 subnet_mask=$(find_netmask $1)
329 if [[ -z "$interface_ip" || -z "$subnet_mask" ]]; then
332 float_range_end=$(find_last_ip_subnet ${interface_ip} ${subnet_mask})
333 float_range_end=$(subtract_ip ${float_range_end} 1)
334 float_range_start=$(subtract_ip ${float_range_end} 19)
335 echo "${float_range_start},${float_range_end}"
338 ##generate the floating range available via CIDR
339 ##uses last 20 IPs of subnet, minus last IP
341 function generate_floating_ip_range {
342 local float_range_start float_range_end last_ip
343 #last_ip=$(ipcalc -nb $1 | grep HostMax: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
344 last_ip=$(ipcalc -nmpb $1 | grep BROADCAST= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
345 if [ -z "$last_ip" ]; then
348 last_ip=$(subtract_ip ${last_ip} 2)
349 float_range_start=$(subtract_ip ${last_ip} 19)
350 float_range_end=${last_ip}
351 echo "${float_range_start},${float_range_end}"
354 ##attach interface to OVS and set the network config correctly
355 ##params: bride to attach to, interface to attach, network type (optional)
356 ##public indicates attaching to a public interface
357 function attach_interface_to_ovs {
358 local bridge interface
359 local if_ip if_mask if_gw if_file ovs_file
361 if [[ -z "$1" || -z "$2" ]]; then
368 if ovs-vsctl list-ports ${bridge} | grep ${interface}; then
372 if_file=/etc/sysconfig/network-scripts/ifcfg-${interface}
373 ovs_file=/etc/sysconfig/network-scripts/ifcfg-${bridge}
375 if [ -e "$if_file" ]; then
376 if_ip=$(sed -n 's/^IPADDR=\(.*\)$/\1/p' ${if_file})
377 if_mask=$(sed -n 's/^NETMASK=\(.*\)$/\1/p' ${if_file})
378 if_gw=$(sed -n 's/^GATEWAY=\(.*\)$/\1/p' ${if_file})
380 echo "ERROR: ifcfg file missing for ${interface}"
384 if [[ -z "$if_ip" || -z "$if_mask" ]]; then
385 echo "ERROR: IPADDR or NETMASK missing for ${interface}"
387 elif [[ -z "$if_gw" && "$3" == "public_network" ]]; then
388 echo "ERROR: GATEWAY missing for ${interface}, which is public"
392 # move old config file to .orig
393 mv -f ${if_file} ${if_file}.orig
394 echo "DEVICE=${interface}
402 PROMISC=yes" > ${if_file}
404 if [ -z ${if_gw} ]; then
406 echo "DEVICE=${bridge}
414 PEERDNS=no" > ${ovs_file}
417 echo "DEVICE=${bridge}
426 PEERDNS=no" > ${ovs_file}
429 sudo systemctl restart network
432 ##detach interface from OVS and set the network config correctly
433 ##params: bridge to detach from
434 ##assumes only 1 real interface attached to OVS
435 function detach_interface_from_ovs {
437 local port_output ports_no_orig
439 local if_ip if_mask if_gw
441 net_path=/etc/sysconfig/network-scripts/
442 if [[ -z "$1" ]]; then
448 # if no interfaces attached then return
449 if ! ovs-vsctl list-ports ${bridge} | grep -Ev "vnet[0-9]*"; then
453 # look for .orig ifcfg files to use
454 port_output=$(ovs-vsctl list-ports ${bridge} | grep -Ev "vnet[0-9]*")
455 while read -r line; do
456 if [ -z "$line" ]; then
458 elif [ -e ${net_path}/ifcfg-${line}.orig ]; then
459 mv -f ${net_path}/ifcfg-${line}.orig ${net_path}/ifcfg-${line}
460 elif [ -e ${net_path}/ifcfg-${bridge} ]; then
461 if_ip=$(sed -n 's/^IPADDR=\(.*\)$/\1/p' ${if_file})
462 if_mask=$(sed -n 's/^NETMASK=\(.*\)$/\1/p' ${if_file})
463 if_gw=$(sed -n 's/^GATEWAY=\(.*\)$/\1/p' ${if_file})
465 if [[ -z "$if_ip" || -z "$if_mask" ]]; then
466 echo "ERROR: IPADDR or NETMASK missing for ${bridge} and no .orig file for interface ${line}"
470 if [ -z ${if_gw} ]; then
479 PEERDNS=no" > ${net_path}/ifcfg-${line}
489 PEERDNS=no" > ${net_path}/ifcfg-${line}
493 echo "ERROR: Real interface ${line} attached to bridge, but no interface or ${bridge} ifcfg file exists"
497 done <<< "$port_output"
499 # modify the bridge ifcfg file
500 # to remove IP params
501 sudo sed -i 's/IPADDR=.*//' ${net_path}/ifcfg-${bridge}
502 sudo sed -i 's/NETMASK=.*//' ${net_path}/ifcfg-${bridge}
503 sudo sed -i 's/GATEWAY=.*//' ${net_path}/ifcfg-${bridge}
505 sudo systemctl restart network