summaryrefslogtreecommitdiffstats
path: root/roles/openshift_node/files/networkmanager/99-origin-dns.sh
blob: 8c597a65be535605aeb919a42993319d77c128b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/bin/bash -x
# -*- mode: sh; sh-indentation: 2 -*-

# This NetworkManager dispatcher script replicates the functionality of
# NetworkManager's dns=dnsmasq  however, rather than hardcoding the listening
# address and /etc/resolv.conf to 127.0.0.1 it pulls the IP address from the
# interface that owns the default route. This enables us to then configure pods
# to use this IP address as their only resolver, where as using 127.0.0.1 inside
# a pod would fail.
#
# To use this,
# - If this host is also a master, reconfigure master dnsConfig to listen on
#   8053 to avoid conflicts on port 53 and open port 8053 in the firewall
# - Drop this script in /etc/NetworkManager/dispatcher.d/
# - systemctl restart NetworkManager
# - Configure node-config.yaml to set dnsIP: to the ip address of this
#   node
#
# Test it:
# host kubernetes.default.svc.cluster.local
# host google.com
#
# TODO: I think this would be easy to add as a config option in NetworkManager
# natively, look at hacking that up

cd /etc/sysconfig/network-scripts
. ./network-functions

[ -f ../network ] && . ../network

if [[ $2 =~ ^(up|dhcp4-change|dhcp6-change)$ ]]; then
  # If the origin-upstream-dns config file changed we need to restart
  NEEDS_RESTART=0
  UPSTREAM_DNS='/etc/dnsmasq.d/origin-upstream-dns.conf'
  # We'll regenerate the dnsmasq origin config in a temp file first
  UPSTREAM_DNS_TMP=`mktemp`
  UPSTREAM_DNS_TMP_SORTED=`mktemp`
  CURRENT_UPSTREAM_DNS_SORTED=`mktemp`
  NEW_RESOLV_CONF=`mktemp`
  NEW_NODE_RESOLV_CONF=`mktemp`


  ######################################################################
  # couldn't find an existing method to determine if the interface owns the
  # default route
  #SDS
  #def_route=$(/sbin/ip route list match 0.0.0.0/0 | awk '{print $3 }')
  #def_route_int=$(/sbin/ip route get to ${def_route} | awk '{print $3}')
  #def_route_ip=$(/sbin/ip route get to ${def_route} | awk '{print $5}')
  #EDS
  def_route_ip=$(cat /etc/hosts | grep openshift_dns_ip | awk '{ print $1 }')
  [ -n "$def_route_ip" ] && def_route_int=$(ip -o addr show | grep ${def_route_ip} | awk '{ print $2 }')
  if [ -z "$def_route_ip" -o -z "$def_route_int" ]; then
    def_route=$(/sbin/ip route list match 0.0.0.0/0 | awk '{print $3 }')
    def_route_int=$(/sbin/ip route get to ${def_route} | awk '{print $3}' | head -n 1)
    def_route_ip=$(/sbin/ip -f inet addr show dev ${def_route_int} scope global up | grep -Po 'inet \K[\d.]+' | head -n 1)
  fi

  def_routes=$(/sbin/ip route list match 0.0.0.0/0 | awk '{print $3 }')
  def_routes_int=$(for r in ${def_routes}; do /sbin/ip route get to ${r} | awk '{print $3}'; done)
  interfaces="${def_route_int} ${def_routes_int}"

  nsconf=$(grep -P ^nameserver /etc/resolv.conf | wc -l)
  if [[ $nsconf -gt 0 &&  "${interfaces}" =~ (^|[[:space:]])${DEVICE_IFACE}($|[[:space:]]) ]]; then
#  if [[ ${DEVICE_IFACE} == ${def_route_int} ]]; then
    if [ ! -f /etc/dnsmasq.d/origin-dns.conf ]; then
      cat << EOF > /etc/dnsmasq.d/origin-dns.conf
no-resolv
domain-needed
server=/cluster.local/172.30.0.1
server=/30.172.in-addr.arpa/172.30.0.1
enable-dbus
dns-forward-max=5000
cache-size=5000
EOF
      # New config file, must restart
      NEEDS_RESTART=1
    fi

    # If network manager doesn't know about the nameservers then the best
    # we can do is grab them from /etc/resolv.conf but only if we've got no
    # watermark
    if ! grep -q '99-origin-dns.sh' /etc/resolv.conf; then
      if [[ -z "${IP4_NAMESERVERS}" || "${IP4_NAMESERVERS}" == "${def_route_ip}" ]]; then
            IP4_NAMESERVERS=`grep '^nameserver ' /etc/resolv.conf | awk '{ print $2 }'`
      fi
      ######################################################################
      # Write out default nameservers for /etc/dnsmasq.d/origin-upstream-dns.conf
      # and /etc/origin/node/resolv.conf in their respective formats
      for ns in ${IP4_NAMESERVERS}; do
        if [[ ! -z $ns ]]; then
          echo "server=${ns}" >> $UPSTREAM_DNS_TMP
          echo "nameserver ${ns}" >> $NEW_NODE_RESOLV_CONF
        fi
      done
      # Sort it in case DNS servers arrived in a different order
      sort $UPSTREAM_DNS_TMP > $UPSTREAM_DNS_TMP_SORTED
      sort $UPSTREAM_DNS > $CURRENT_UPSTREAM_DNS_SORTED
      # Compare to the current config file (sorted)
      NEW_DNS_SUM=`md5sum ${UPSTREAM_DNS_TMP_SORTED} | awk '{print $1}'`
      CURRENT_DNS_SUM=`md5sum ${CURRENT_UPSTREAM_DNS_SORTED} | awk '{print $1}'`
      if [ "${NEW_DNS_SUM}" != "${CURRENT_DNS_SUM}" ]; then
        # DNS has changed, copy the temp file to the proper location (-Z
        # sets default selinux context) and set the restart flag
        cp -Z $UPSTREAM_DNS_TMP $UPSTREAM_DNS
        NEEDS_RESTART=1
      fi
      # compare /etc/origin/node/resolv.conf checksum and replace it if different
      NEW_NODE_RESOLV_CONF_MD5=`md5sum ${NEW_NODE_RESOLV_CONF}`
      OLD_NODE_RESOLV_CONF_MD5=`md5sum /etc/origin/node/resolv.conf`
      if [ "${NEW_NODE_RESOLV_CONF_MD5}" != "${OLD_NODE_RESOLV_CONF_MD5}" ]; then
        cp -Z $NEW_NODE_RESOLV_CONF /etc/origin/node/resolv.conf
      fi
    fi

    if ! `systemctl -q is-active dnsmasq.service`; then
      NEEDS_RESTART=1
    fi

    ######################################################################
    if [ "${NEEDS_RESTART}" -eq "1" ]; then
      systemctl restart dnsmasq
    fi

    # Only if dnsmasq is running properly make it our only nameserver and place
    # a watermark on /etc/resolv.conf
    if `systemctl -q is-active dnsmasq.service`; then
      if ! grep -q '99-origin-dns.sh' /etc/resolv.conf; then
          echo "# nameserver updated by /etc/NetworkManager/dispatcher.d/99-origin-dns.sh" >> ${NEW_RESOLV_CONF}
      fi
      sed -e '/^nameserver.*$/d' /etc/resolv.conf >> ${NEW_RESOLV_CONF}
      echo "nameserver "${def_route_ip}"" >> ${NEW_RESOLV_CONF}
      if ! grep -qw search ${NEW_RESOLV_CONF}; then
        echo 'search cluster.local' >> ${NEW_RESOLV_CONF}
      elif ! grep -q 'search cluster.local' ${NEW_RESOLV_CONF}; then
        # cluster.local should be in first three DNS names so that glibc resolver would work
        sed -i -e 's/^search \(.\+\)\( cluster\.local\)\{0,1\}$/search cluster.local \1/' ${NEW_RESOLV_CONF}
      fi
      cp -Z ${NEW_RESOLV_CONF} /etc/resolv.conf
    fi
  fi

  # Clean up after yourself
  rm -f $UPSTREAM_DNS_TMP $UPSTREAM_DNS_TMP_SORTED $CURRENT_UPSTREAM_DNS_SORTED $NEW_RESOLV_CONF
fi