Browse code

Vendor in libnetwork v0.6.0-rc2

Signed-off-by: Santhosh Manohar <santhosh@docker.com>

Santhosh Manohar authored on 2016/01/22 13:46:28
Showing 6 changed files
... ...
@@ -27,7 +27,7 @@ clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
27 27
 clone git github.com/imdario/mergo 0.2.1
28 28
 
29 29
 #get libnetwork packages
30
-clone git github.com/docker/libnetwork v0.6.0-rc1
30
+clone git github.com/docker/libnetwork v0.6.0-rc2
31 31
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
32 32
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
33 33
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
... ...
@@ -1,5 +1,11 @@
1 1
 # Changelog
2 2
 
3
+## 0.6.0-rc2 (2016-01-21)
4
+- Fixes docker/docker#19376
5
+- Fixes docker/docker#15819
6
+- Fixes libnetwork/#885, Not filter v6 DNS servers from resolv.conf
7
+- Fixes docker/docker #19448, also handles the . in service and network names correctly.
8
+
3 9
 ## 0.6.0-rc1 (2016-01-14)
4 10
 - Fixes docker/docker#19404
5 11
 - Fixes the ungraceful daemon restart issue in systemd with remote network plugin 
... ...
@@ -14,6 +14,13 @@ import (
14 14
 	"github.com/docker/libnetwork/types"
15 15
 )
16 16
 
17
+// constants for the IP address type
18
+const (
19
+	IP = iota // IPv4 and IPv6
20
+	IPv4
21
+	IPv6
22
+)
23
+
17 24
 var (
18 25
 	// ErrNetworkOverlapsWithNameservers preformatted error
19 26
 	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
... ...
@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 	"github.com/Sirupsen/logrus"
12 12
 	"github.com/docker/docker/pkg/ioutils"
13
+	"github.com/docker/libnetwork/netutils"
13 14
 	"github.com/docker/libnetwork/resolvconf/dns"
14 15
 )
15 16
 
... ...
@@ -29,6 +30,8 @@ var (
29 29
 	localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`)
30 30
 	nsIPv6Regexp      = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`)
31 31
 	nsRegexp          = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
32
+	nsIPv6Regexpmatch = regexp.MustCompile(`^\s*nameserver\s*((` + ipv6Address + `))\s*$`)
33
+	nsIPv4Regexpmatch = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `))\s*$`)
32 34
 	searchRegexp      = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
33 35
 	optionsRegexp     = regexp.MustCompile(`^\s*options\s*(([^\s]+\s*)*)$`)
34 36
 )
... ...
@@ -119,7 +122,7 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) {
119 119
 	}
120 120
 	// if the resulting resolvConf has no more nameservers defined, add appropriate
121 121
 	// default DNS servers for IPv4 and (optionally) IPv6
122
-	if len(GetNameservers(cleanedResolvConf)) == 0 {
122
+	if len(GetNameservers(cleanedResolvConf, netutils.IP)) == 0 {
123 123
 		logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns)
124 124
 		dns := defaultIPv4Dns
125 125
 		if ipv6Enabled {
... ...
@@ -151,10 +154,17 @@ func getLines(input []byte, commentMarker []byte) [][]byte {
151 151
 }
152 152
 
153 153
 // GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
154
-func GetNameservers(resolvConf []byte) []string {
154
+func GetNameservers(resolvConf []byte, kind int) []string {
155 155
 	nameservers := []string{}
156 156
 	for _, line := range getLines(resolvConf, []byte("#")) {
157
-		var ns = nsRegexp.FindSubmatch(line)
157
+		var ns [][]byte
158
+		if kind == netutils.IP {
159
+			ns = nsRegexp.FindSubmatch(line)
160
+		} else if kind == netutils.IPv4 {
161
+			ns = nsIPv4Regexpmatch.FindSubmatch(line)
162
+		} else if kind == netutils.IPv6 {
163
+			ns = nsIPv6Regexpmatch.FindSubmatch(line)
164
+		}
158 165
 		if len(ns) > 0 {
159 166
 			nameservers = append(nameservers, string(ns[1]))
160 167
 		}
... ...
@@ -167,7 +177,7 @@ func GetNameservers(resolvConf []byte) []string {
167 167
 // This function's output is intended for net.ParseCIDR
168 168
 func GetNameserversAsCIDR(resolvConf []byte) []string {
169 169
 	nameservers := []string{}
170
-	for _, nameserver := range GetNameservers(resolvConf) {
170
+	for _, nameserver := range GetNameservers(resolvConf, netutils.IP) {
171 171
 		nameservers = append(nameservers, nameserver+"/32")
172 172
 	}
173 173
 	return nameservers
... ...
@@ -36,6 +36,7 @@ const (
36 36
 	ptrIPv4domain = ".in-addr.arpa."
37 37
 	ptrIPv6domain = ".ip6.arpa."
38 38
 	respTTL       = 1800
39
+	maxExtDNS     = 3 //max number of external servers to try
39 40
 )
40 41
 
41 42
 // resolver implements the Resolver interface
... ...
@@ -188,15 +189,24 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
188 188
 		if len(r.extDNS) == 0 {
189 189
 			return
190 190
 		}
191
-		log.Debugf("Querying ext dns %s for %s[%d]", r.extDNS[0], name, query.Question[0].Qtype)
192 191
 
193
-		c := &dns.Client{Net: "udp"}
194
-		addr := fmt.Sprintf("%s:%d", r.extDNS[0], 53)
192
+		num := maxExtDNS
193
+		if len(r.extDNS) < maxExtDNS {
194
+			num = len(r.extDNS)
195
+		}
196
+		for i := 0; i < num; i++ {
197
+			log.Debugf("Querying ext dns %s for %s[%d]", r.extDNS[i], name, query.Question[0].Qtype)
195 198
 
196
-		// TODO: iterate over avilable servers in case of error
197
-		resp, _, err = c.Exchange(query, addr)
198
-		if err != nil {
199
+			c := &dns.Client{Net: "udp"}
200
+			addr := fmt.Sprintf("%s:%d", r.extDNS[i], 53)
201
+
202
+			resp, _, err = c.Exchange(query, addr)
203
+			if err == nil {
204
+				break
205
+			}
199 206
 			log.Errorf("external resolution failed, %s", err)
207
+		}
208
+		if resp == nil {
200 209
 			return
201 210
 		}
202 211
 	}
... ...
@@ -14,6 +14,7 @@ import (
14 14
 
15 15
 	log "github.com/Sirupsen/logrus"
16 16
 	"github.com/docker/libnetwork/etchosts"
17
+	"github.com/docker/libnetwork/netutils"
17 18
 	"github.com/docker/libnetwork/osl"
18 19
 	"github.com/docker/libnetwork/resolvconf"
19 20
 	"github.com/docker/libnetwork/types"
... ...
@@ -322,11 +323,15 @@ func (sb *sandbox) startResolver() {
322 322
 			}
323 323
 		}()
324 324
 
325
-		sb.rebuildDNS()
325
+		err = sb.rebuildDNS()
326
+		if err != nil {
327
+			log.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err)
328
+			return
329
+		}
326 330
 		sb.resolver.SetExtServers(sb.extDNS)
327 331
 
328 332
 		sb.osSbox.InvokeFunc(sb.resolver.SetupFunc())
329
-		if err := sb.resolver.Start(); err != nil {
333
+		if err = sb.resolver.Start(); err != nil {
330 334
 			log.Errorf("Resolver Setup/Start failed for container %s, %q", sb.ContainerID(), err)
331 335
 		}
332 336
 	})
... ...
@@ -427,23 +432,51 @@ func (sb *sandbox) ResolveIP(ip string) string {
427 427
 
428 428
 func (sb *sandbox) ResolveName(name string) net.IP {
429 429
 	var ip net.IP
430
-	parts := strings.Split(name, ".")
431
-	log.Debugf("To resolve %v", parts)
432 430
 
433
-	reqName := parts[0]
434
-	networkName := ""
435
-	if len(parts) > 1 {
436
-		networkName = parts[1]
431
+	// Embedded server owns the docker network domain. Resolution should work
432
+	// for both container_name and container_name.network_name
433
+	// We allow '.' in service name and network name. For a name a.b.c.d the
434
+	// following have to tried;
435
+	// {a.b.c.d in the networks container is connected to}
436
+	// {a.b.c in network d},
437
+	// {a.b in network c.d},
438
+	// {a in network b.c.d},
439
+
440
+	name = strings.TrimSuffix(name, ".")
441
+	reqName := []string{name}
442
+	networkName := []string{""}
443
+
444
+	if strings.Contains(name, ".") {
445
+		var i int
446
+		dup := name
447
+		for {
448
+			if i = strings.LastIndex(dup, "."); i == -1 {
449
+				break
450
+			}
451
+			networkName = append(networkName, name[i+1:])
452
+			reqName = append(reqName, name[:i])
453
+
454
+			dup = dup[:i]
455
+		}
437 456
 	}
457
+
438 458
 	epList := sb.getConnectedEndpoints()
439
-	// First check for local container alias
440
-	ip = sb.resolveName(reqName, networkName, epList, true)
441
-	if ip != nil {
442
-		return ip
443
-	}
459
+	for i := 0; i < len(reqName); i++ {
460
+		log.Debugf("To resolve: %v in %v", reqName[i], networkName[i])
444 461
 
445
-	// Resolve the actual container name
446
-	return sb.resolveName(reqName, networkName, epList, false)
462
+		// First check for local container alias
463
+		ip = sb.resolveName(reqName[i], networkName[i], epList, true)
464
+		if ip != nil {
465
+			return ip
466
+		}
467
+
468
+		// Resolve the actual container name
469
+		ip = sb.resolveName(reqName[i], networkName[i], epList, false)
470
+		if ip != nil {
471
+			return ip
472
+		}
473
+	}
474
+	return nil
447 475
 }
448 476
 
449 477
 func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool) net.IP {
... ...
@@ -823,7 +856,7 @@ func (sb *sandbox) setupDNS() error {
823 823
 	if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
824 824
 		var (
825 825
 			err            error
826
-			dnsList        = resolvconf.GetNameservers(currRC.Content)
826
+			dnsList        = resolvconf.GetNameservers(currRC.Content, netutils.IP)
827 827
 			dnsSearchList  = resolvconf.GetSearchDomains(currRC.Content)
828 828
 			dnsOptionsList = resolvconf.GetOptions(currRC.Content)
829 829
 		)
... ...
@@ -865,6 +898,11 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
865 865
 		hashFile = sb.config.resolvConfHashFile
866 866
 	)
867 867
 
868
+	// This is for the host mode networking
869
+	if sb.config.originResolvConfPath != "" {
870
+		return nil
871
+	}
872
+
868 873
 	if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
869 874
 		return nil
870 875
 	}
... ...
@@ -897,36 +935,21 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
897 897
 	if err != nil {
898 898
 		return err
899 899
 	}
900
-
901
-	// for atomic updates to these files, use temporary files with os.Rename:
902
-	dir := path.Dir(sb.config.resolvConfPath)
903
-	tmpHashFile, err := ioutil.TempFile(dir, "hash")
904
-	if err != nil {
905
-		return err
906
-	}
907
-	tmpResolvFile, err := ioutil.TempFile(dir, "resolv")
900
+	err = ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, 0644)
908 901
 	if err != nil {
909 902
 		return err
910 903
 	}
911 904
 
912
-	// Change the perms to filePerm (0644) since ioutil.TempFile creates it by default as 0600
913
-	if err := os.Chmod(tmpResolvFile.Name(), filePerm); err != nil {
905
+	// write the new hash in a temp file and rename it to make the update atomic
906
+	dir := path.Dir(sb.config.resolvConfPath)
907
+	tmpHashFile, err := ioutil.TempFile(dir, "hash")
908
+	if err != nil {
914 909
 		return err
915 910
 	}
916
-
917
-	// write the updates to the temp files
918 911
 	if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newRC.Hash), filePerm); err != nil {
919 912
 		return err
920 913
 	}
921
-	if err = ioutil.WriteFile(tmpResolvFile.Name(), newRC.Content, filePerm); err != nil {
922
-		return err
923
-	}
924
-
925
-	// rename the temp files for atomic replace
926
-	if err = os.Rename(tmpHashFile.Name(), hashFile); err != nil {
927
-		return err
928
-	}
929
-	return os.Rename(tmpResolvFile.Name(), sb.config.resolvConfPath)
914
+	return os.Rename(tmpHashFile.Name(), hashFile)
930 915
 }
931 916
 
932 917
 // Embedded DNS server has to be enabled for this sandbox. Rebuild the container's
... ...
@@ -941,7 +964,8 @@ func (sb *sandbox) rebuildDNS() error {
941 941
 	}
942 942
 
943 943
 	// localhost entries have already been filtered out from the list
944
-	sb.extDNS = resolvconf.GetNameservers(currRC.Content)
944
+	// retain only the v4 servers in sb for forwarding the DNS queries
945
+	sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4)
945 946
 
946 947
 	var (
947 948
 		dnsList        = []string{sb.resolver.NameServer()}
... ...
@@ -949,26 +973,14 @@ func (sb *sandbox) rebuildDNS() error {
949 949
 		dnsSearchList  = resolvconf.GetSearchDomains(currRC.Content)
950 950
 	)
951 951
 
952
+	// external v6 DNS servers has to be listed in resolv.conf
953
+	dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...)
954
+
952 955
 	// Resolver returns the options in the format resolv.conf expects
953 956
 	dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...)
954 957
 
955
-	dir := path.Dir(sb.config.resolvConfPath)
956
-	tmpResolvFile, err := ioutil.TempFile(dir, "resolv")
957
-	if err != nil {
958
-		return err
959
-	}
960
-
961
-	// Change the perms to filePerm (0644) since ioutil.TempFile creates it by default as 0600
962
-	if err := os.Chmod(tmpResolvFile.Name(), filePerm); err != nil {
963
-		return err
964
-	}
965
-
966
-	_, err = resolvconf.Build(tmpResolvFile.Name(), dnsList, dnsSearchList, dnsOptionsList)
967
-	if err != nil {
968
-		return err
969
-	}
970
-
971
-	return os.Rename(tmpResolvFile.Name(), sb.config.resolvConfPath)
958
+	_, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
959
+	return err
972 960
 }
973 961
 
974 962
 // joinLeaveStart waits to ensure there are no joins or leaves in progress and