Fix race conditions between containers
[apex-tripleo-heat-templates.git] / network / scripts / run-os-net-config.sh
1 #!/bin/bash
2 # The following environment variables may be set to substitute in a
3 # custom bridge or interface name.  Normally these are provided by the calling
4 # SoftwareConfig resource, but they may also be set manually for testing.
5 # $bridge_name : The bridge device name to apply
6 # $interface_name : The interface name to apply
7 #
8 # Also this token is replaced via a str_replace in the SoftwareConfig running
9 # the script - in future we may extend this to also work with a variable, e.g
10 # a deployment input via input_values
11 # $network_config : the json serialized os-net-config config to apply
12 #
13 set -eux
14
15 function get_metadata_ip() {
16
17   local METADATA_IP
18
19   # Look for a variety of Heat transports
20   # FIXME: Heat should provide a way to obtain this in a single place
21   for URL in os-collect-config.cfn.metadata_url os-collect-config.heat.auth_url os-collect-config.request.metadata_url os-collect-config.zaqar.auth_url; do
22     METADATA_IP=$(os-apply-config --key $URL --key-default '' --type raw 2>/dev/null | sed -e 's|http.*://\([^:]*\).*|\1|')
23     [ -n "$METADATA_IP" ] && break
24   done
25
26   echo $METADATA_IP
27
28 }
29
30 function is_local_ip() {
31   local IP_TO_CHECK=$1
32   if ip -o a | grep "inet6\? $IP_TO_CHECK/" &>/dev/null; then
33     return 0
34   else
35     return 1
36   fi
37 }
38
39 function ping_metadata_ip() {
40   local METADATA_IP=$(get_metadata_ip)
41
42   if [ -n "$METADATA_IP" ] && ! is_local_ip $METADATA_IP; then
43
44     echo -n "Trying to ping metadata IP ${METADATA_IP}..."
45
46     local COUNT=0
47     until ping -c 1 $METADATA_IP &> /dev/null; do
48       COUNT=$(( $COUNT + 1 ))
49       if [ $COUNT -eq 10 ]; then
50         echo "FAILURE"
51         echo "$METADATA_IP is not pingable." >&2
52         exit 1
53       fi
54     done
55     echo "SUCCESS"
56
57   else
58     echo "No metadata IP found. Skipping."
59   fi
60 }
61
62 function configure_safe_defaults() {
63
64 [[ $? == 0 ]] && return 0
65
66 cat > /etc/os-net-config/dhcp_all_interfaces.yaml <<EOF_CAT
67 # This file is an autogenerated safe defaults file for os-net-config
68 # which runs DHCP on all discovered interfaces to ensure connectivity
69 # back to the undercloud for updates
70 network_config:
71 EOF_CAT
72
73     for iface in $(ls /sys/class/net | grep -v ^lo$); do
74         local mac_addr_type="$(cat /sys/class/net/${iface}/addr_assign_type)"
75         if [ "$mac_addr_type" != "0" ]; then
76             echo "Device has generated MAC, skipping."
77         else
78             ip link set dev $iface up &>/dev/null
79             HAS_LINK="$(cat /sys/class/net/${iface}/carrier)"
80
81             TRIES=10
82             while [ "$HAS_LINK" == "0" -a $TRIES -gt 0 ]; do
83                 HAS_LINK="$(cat /sys/class/net/${iface}/carrier)"
84                 if [ "$HAS_LINK" == "1" ]; then
85                     break
86                 else
87                     sleep 1
88                 fi
89                 TRIES=$(( TRIES - 1 ))
90             done
91             if [ "$HAS_LINK" == "1" ] ; then
92 cat >> /etc/os-net-config/dhcp_all_interfaces.yaml <<EOF_CAT
93   -
94     type: interface
95     name: $iface
96     use_dhcp: true
97 EOF_CAT
98             fi
99         fi
100     done
101     set +e
102     os-net-config -c /etc/os-net-config/dhcp_all_interfaces.yaml -v --detailed-exit-codes --cleanup
103     RETVAL=$?
104     set -e
105     if [[ $RETVAL == 2 ]]; then
106         ping_metadata_ip
107     elif [[ $RETVAL != 0 ]]; then
108         echo "ERROR: configuration of safe defaults failed."
109     fi
110 }
111
112 if [ -n '$network_config' ]; then
113     if [ -z "${disable_configure_safe_defaults:-''}" ]; then
114         trap configure_safe_defaults EXIT
115     fi
116
117     mkdir -p /etc/os-net-config
118     # Note these variables come from the calling heat SoftwareConfig
119     echo '$network_config' > /etc/os-net-config/config.json
120
121     if [ "$(type -t network_config_hook)" = "function" ]; then
122         network_config_hook
123     fi
124
125     sed -i "s/bridge_name/${bridge_name:-''}/" /etc/os-net-config/config.json
126     sed -i "s/interface_name/${interface_name:-''}/" /etc/os-net-config/config.json
127
128     set +e
129     os-net-config -c /etc/os-net-config/config.json -v --detailed-exit-codes
130     RETVAL=$?
131     set -e
132
133     if [[ $RETVAL == 2 ]]; then
134         ping_metadata_ip
135
136         #NOTE: dprince this udev rule can apparently leak DHCP processes?
137         # https://bugs.launchpad.net/tripleo/+bug/1538259
138         # until we discover the root cause we can simply disable the
139         # rule because networking has already been configured at this point
140         if [ -f /etc/udev/rules.d/99-dhcp-all-interfaces.rules ]; then
141             rm /etc/udev/rules.d/99-dhcp-all-interfaces.rules
142         fi
143
144     elif [[ $RETVAL != 0 ]]; then
145         echo "ERROR: os-net-config configuration failed." >&2
146         exit 1
147     fi
148 fi