Merge "Moving parser functions to a sourced file"
[apex.git] / lib / common-functions.sh
1 #!/usr/bin/env bash
2 ##############################################################################
3 # Copyright (c) 2015 Tim Rozet (Red Hat), Dan Radez (Red Hat) and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10
11 # Common Functions used by  OPNFV Apex
12 # author: Tim Rozet (trozet@redhat.com)
13
14 ##converts subnet mask to prefix
15 ##params: subnet mask
16 function prefix2mask {
17   # Number of args to shift, 255..255, first non-255 byte, zeroes
18    set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
19    [ $1 -gt 1 ] && shift $1 || shift
20    echo ${1-0}.${2-0}.${3-0}.${4-0}
21 }
22
23 ##find ip of interface
24 ##params: interface name
25 function find_ip {
26   if [[ -z "$1" ]]; then
27     return 1
28   fi
29
30   python3.4 -B $LIB/python/apex_python_utils.py find-ip -i $1
31 }
32
33 ##attach interface to OVS and set the network config correctly
34 ##params: bride to attach to, interface to attach, network type (optional)
35 ##public indicates attaching to a public interface
36 function attach_interface_to_ovs {
37   local bridge interface
38   local if_ip if_mask if_gw if_file ovs_file if_prefix
39   local if_metric if_dns1 if_dns2
40
41   if [[ -z "$1" || -z "$2" ]]; then
42     return 1
43   else
44     bridge=$1
45     interface=$2
46   fi
47
48   if ovs-vsctl list-ports ${bridge} | grep ${interface}; then
49     return 0
50   fi
51
52   if_file=/etc/sysconfig/network-scripts/ifcfg-${interface}
53   ovs_file=/etc/sysconfig/network-scripts/ifcfg-${bridge}
54
55   if [ -e "$if_file" ]; then
56     if_ip=$(sed -n 's/^IPADDR=\(.*\)$/\1/p' ${if_file})
57     if_mask=$(sed -n 's/^NETMASK=\(.*\)$/\1/p' ${if_file})
58     if_gw=$(sed -n 's/^GATEWAY=\(.*\)$/\1/p' ${if_file})
59     if_metric=$(sed -n 's/^METRIC=\(.*\)$/\1/p' ${if_file})
60     if_dns1=$(sed -n 's/^DNS1=\(.*\)$/\1/p' ${if_file})
61     if_dns2=$(sed -n 's/^DNS2=\(.*\)$/\1/p' ${if_file})
62   else
63     echo "ERROR: ifcfg file missing for ${interface}"
64     return 1
65   fi
66
67   if [ -z "$if_mask" ]; then
68     # we can look for PREFIX here, then convert it to NETMASK
69     if_prefix=$(sed -n 's/^PREFIX=\(.*\)$/\1/p' ${if_file})
70     if_mask=$(prefix2mask ${if_prefix})
71   fi
72
73   if [[ -z "$if_ip" || -z "$if_mask" ]]; then
74     echo "ERROR: IPADDR or NETMASK/PREFIX missing for ${interface}"
75     return 1
76   elif [[ -z "$if_gw" && "$3" == "public_network" ]]; then
77     echo "ERROR: GATEWAY missing for ${interface}, which is public"
78     return 1
79   fi
80
81   # move old config file to .orig
82   mv -f ${if_file} ${if_file}.orig
83   echo "DEVICE=${interface}
84 DEVICETYPE=ovs
85 TYPE=OVSPort
86 PEERDNS=no
87 BOOTPROTO=static
88 NM_CONTROLLED=no
89 ONBOOT=yes
90 OVS_BRIDGE=${bridge}
91 PROMISC=yes" > ${if_file}
92
93
94   # create bridge cfg
95   echo "DEVICE=${bridge}
96 DEVICETYPE=ovs
97 IPADDR=${if_ip}
98 NETMASK=${if_mask}
99 BOOTPROTO=static
100 ONBOOT=yes
101 TYPE=OVSBridge
102 PROMISC=yes
103 PEERDNS=no" > ${ovs_file}
104
105   if [ -n "$if_gw" ]; then
106     echo "GATEWAY=${if_gw}" >> ${ovs_file}
107   fi
108
109   if [ -n "$if_metric" ]; then
110     echo "METRIC=${if_metric}" >> ${ovs_file}
111   fi
112
113   if [[ -n "$if_dns1" || -n "$if_dns2" ]]; then
114     sed -i '/PEERDNS/c\PEERDNS=yes' ${ovs_file}
115
116     if [ -n "$if_dns1" ]; then
117       echo "DNS1=${if_dns1}" >> ${ovs_file}
118     fi
119
120     if [ -n "$if_dns2" ]; then
121       echo "DNS2=${if_dns2}" >> ${ovs_file}
122     fi
123   fi
124
125   sudo systemctl restart network
126 }
127
128 ##detach interface from OVS and set the network config correctly
129 ##params: bridge to detach from
130 ##assumes only 1 real interface attached to OVS
131 function detach_interface_from_ovs {
132   local bridge
133   local port_output ports_no_orig
134   local net_path
135   local if_ip if_mask if_gw if_prefix
136   local if_metric if_dns1 if_dns2
137
138   net_path=/etc/sysconfig/network-scripts/
139   if [[ -z "$1" ]]; then
140     return 1
141   else
142     bridge=$1
143   fi
144
145   # if no interfaces attached then return
146   if ! ovs-vsctl list-ports ${bridge} | grep -Ev "vnet[0-9]*"; then
147     return 0
148   fi
149
150   # look for .orig ifcfg files  to use
151   port_output=$(ovs-vsctl list-ports ${bridge} | grep -Ev "vnet[0-9]*")
152   while read -r line; do
153     if [ -z "$line" ]; then
154       continue
155     elif [ -e ${net_path}/ifcfg-${line}.orig ]; then
156       mv -f ${net_path}/ifcfg-${line}.orig ${net_path}/ifcfg-${line}
157     elif [ -e ${net_path}/ifcfg-${bridge} ]; then
158       if_ip=$(sed -n 's/^IPADDR=\(.*\)$/\1/p' ${net_path}/ifcfg-${bridge})
159       if_mask=$(sed -n 's/^NETMASK=\(.*\)$/\1/p' ${net_path}/ifcfg-${bridge})
160       if_gw=$(sed -n 's/^GATEWAY=\(.*\)$/\1/p' ${net_path}/ifcfg-${bridge})
161       if_metric=$(sed -n 's/^METRIC=\(.*\)$/\1/p' ${net_path}/ifcfg-${bridge})
162       if_dns1=$(sed -n 's/^DNS1=\(.*\)$/\1/p' ${net_path}/ifcfg-${bridge})
163       if_dns2=$(sed -n 's/^DNS2=\(.*\)$/\1/p' ${net_path}/ifcfg-${bridge})
164
165       if [ -z "$if_mask" ]; then
166         if_prefix=$(sed -n 's/^PREFIX=[^0-9]*\([0-9][0-9]*\)[^0-9]*$/\1/p' ${net_path}/ifcfg-${bridge})
167         if_mask=$(prefix2mask ${if_prefix})
168       fi
169
170       if [[ -z "$if_ip" || -z "$if_mask" ]]; then
171         echo "ERROR: IPADDR or PREFIX/NETMASK missing for ${bridge} and no .orig file for interface ${line}"
172         return 1
173       fi
174
175       # create if cfg
176       echo "DEVICE=${line}
177 IPADDR=${if_ip}
178 NETMASK=${if_mask}
179 BOOTPROTO=static
180 ONBOOT=yes
181 TYPE=Ethernet
182 NM_CONTROLLED=no
183 PEERDNS=no" > ${net_path}/ifcfg-${line}
184
185       if [ -n "$if_gw" ]; then
186         echo "GATEWAY=${if_gw}" >> ${net_path}/ifcfg-${line}
187       fi
188
189       if [ -n "$if_metric" ]; then
190         echo "METRIC=${if_metric}" >> ${net_path}/ifcfg-${line}
191       fi
192
193       if [[ -n "$if_dns1" || -n "$if_dns2" ]]; then
194         sed -i '/PEERDNS/c\PEERDNS=yes' ${net_path}/ifcfg-${line}
195
196         if [ -n "$if_dns1" ]; then
197           echo "DNS1=${if_dns1}" >> ${net_path}/ifcfg-${line}
198         fi
199
200         if [ -n "$if_dns2" ]; then
201           echo "DNS2=${if_dns2}" >> ${net_path}/ifcfg-${line}
202         fi
203       fi
204       break
205     else
206       echo "ERROR: Real interface ${line} attached to bridge, but no interface or ${bridge} ifcfg file exists"
207       return 1
208     fi
209
210   done <<< "$port_output"
211
212   # modify the bridge ifcfg file
213   # to remove IP params
214   sudo sed -i 's/IPADDR=.*//' ${net_path}/ifcfg-${bridge}
215   sudo sed -i 's/NETMASK=.*//' ${net_path}/ifcfg-${bridge}
216   sudo sed -i 's/GATEWAY=.*//' ${net_path}/ifcfg-${bridge}
217   sudo sed -i 's/DNS1=.*//' ${net_path}/ifcfg-${bridge}
218   sudo sed -i 's/DNS2=.*//' ${net_path}/ifcfg-${bridge}
219   sudo sed -i 's/METRIC=.*//' ${net_path}/ifcfg-${bridge}
220   sudo sed -i 's/PEERDNS=.*//' ${net_path}/ifcfg-${bridge}
221
222   sudo systemctl restart network
223 }
224
225 # Update iptables rule for external network reach internet
226 # for virtual deployments
227 # params: external_cidr
228 function configure_undercloud_nat {
229   local external_cidr
230   if [[ -z "$1" ]]; then
231     return 1
232   else
233     external_cidr=$1
234   fi
235
236   ssh -T ${SSH_OPTIONS[@]} "root@$UNDERCLOUD" <<EOI
237 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
238 iptables -t nat -A POSTROUTING -s ${external_cidr} -o eth0 -j MASQUERADE
239 iptables -A FORWARD -i eth2 -j ACCEPT
240 iptables -A FORWARD -s ${external_cidr} -m state --state ESTABLISHED,RELATED -j ACCEPT
241 service iptables save
242 EOI
243 }
244
245 # Interactive prompt handler
246 # params: step stage, ex. deploy, undercloud install, etc
247 function prompt_user {
248   while [ 1 ]; do
249     echo -n "Would you like to proceed with ${1}? (y/n) "
250     read response
251     if [ "$response" == 'y' ]; then
252       return 0
253     elif [ "$response" == 'n' ]; then
254       return 1
255     else
256       continue
257     fi
258   done
259 }