mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #21396 from aboch/vnn
Vendoring libnetwork v0.7.0-dev.10
This commit is contained in:
commit
506fb9810c
6 changed files with 155 additions and 66 deletions
|
@ -29,7 +29,7 @@ clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
|
|||
clone git github.com/imdario/mergo 0.2.1
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork v0.7.0-dev.9
|
||||
clone git github.com/docker/libnetwork v0.7.0-dev.10
|
||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
||||
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
||||
|
|
|
@ -1144,10 +1144,10 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContaine
|
|||
|
||||
func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) {
|
||||
// create two networks
|
||||
dockerCmd(c, "network", "create", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")
|
||||
dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")
|
||||
assertNwIsAvailable(c, "n0")
|
||||
|
||||
dockerCmd(c, "network", "create", "--subnet=172.30.0.0/16", "--ip-range=172.30.5.0/24", "--subnet=2001:db8:abcd::/64", "--ip-range=2001:db8:abcd::/80", "n1")
|
||||
dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--ip-range=172.30.5.0/24", "--subnet=2001:db8:abcd::/64", "--ip-range=2001:db8:abcd::/80", "n1")
|
||||
assertNwIsAvailable(c, "n1")
|
||||
|
||||
// run a container on first network specifying the ip addresses
|
||||
|
@ -1183,7 +1183,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIPStoppedContainer
|
|||
dockerCmd(c, "create", "--name", "c0", "busybox", "top")
|
||||
|
||||
// create a network
|
||||
dockerCmd(c, "network", "create", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0")
|
||||
dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0")
|
||||
assertNwIsAvailable(c, "n0")
|
||||
|
||||
// connect the container to the network specifying an ip addresses
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## 0.7.0-dev.10 (2016-03-21)
|
||||
- Add IPv6 service discovery (AAAA records) in embedded DNS server
|
||||
- Honor enableIPv6 flag in network create for the IP allocation
|
||||
- Avoid V6 queries in docker domain going to external nameservers
|
||||
|
||||
## 0.7.0-dev.9 (2016-03-18)
|
||||
- Support labels on networks
|
||||
|
||||
|
|
107
vendor/src/github.com/docker/libnetwork/network.go
vendored
107
vendor/src/github.com/docker/libnetwork/network.go
vendored
|
@ -71,8 +71,9 @@ type NetworkInfo interface {
|
|||
type EndpointWalker func(ep Endpoint) bool
|
||||
|
||||
type svcInfo struct {
|
||||
svcMap map[string][]net.IP
|
||||
ipMap map[string]string
|
||||
svcMap map[string][]net.IP
|
||||
svcIPv6Map map[string][]net.IP
|
||||
ipMap map[string]string
|
||||
}
|
||||
|
||||
// IpamConf contains all the ipam related configurations for a network
|
||||
|
@ -489,6 +490,10 @@ func (n *network) UnmarshalJSON(b []byte) (err error) {
|
|||
if v, ok := netMap["inDelete"]; ok {
|
||||
n.inDelete = v.(bool)
|
||||
}
|
||||
// Reconcile old networks with the recently added `--ipv6` flag
|
||||
if !n.enableIPv6 {
|
||||
n.enableIPv6 = len(n.ipamV6Info) > 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -779,7 +784,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
|
|||
ep.ipamOptions[netlabel.MacAddress] = ep.iface.mac.String()
|
||||
}
|
||||
|
||||
if err = ep.assignAddress(ipam.driver, true, !n.postIPv6); err != nil {
|
||||
if err = ep.assignAddress(ipam.driver, true, n.enableIPv6 && !n.postIPv6); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
|
@ -799,7 +804,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
|
|||
}
|
||||
}()
|
||||
|
||||
if err = ep.assignAddress(ipam.driver, false, n.postIPv6); err != nil {
|
||||
if err = ep.assignAddress(ipam.driver, false, n.enableIPv6 && n.postIPv6); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -890,68 +895,103 @@ func (n *network) EndpointByID(id string) (Endpoint, error) {
|
|||
}
|
||||
|
||||
func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool) {
|
||||
var ipv6 net.IP
|
||||
epName := ep.Name()
|
||||
if iface := ep.Iface(); iface.Address() != nil {
|
||||
myAliases := ep.MyAliases()
|
||||
if iface.AddressIPv6() != nil {
|
||||
ipv6 = iface.AddressIPv6().IP
|
||||
}
|
||||
|
||||
if isAdd {
|
||||
// If anonymous endpoint has an alias use the first alias
|
||||
// for ip->name mapping. Not having the reverse mapping
|
||||
// breaks some apps
|
||||
if ep.isAnonymous() {
|
||||
if len(myAliases) > 0 {
|
||||
n.addSvcRecords(myAliases[0], iface.Address().IP, true)
|
||||
n.addSvcRecords(myAliases[0], iface.Address().IP, ipv6, true)
|
||||
}
|
||||
} else {
|
||||
n.addSvcRecords(epName, iface.Address().IP, true)
|
||||
n.addSvcRecords(epName, iface.Address().IP, ipv6, true)
|
||||
}
|
||||
for _, alias := range myAliases {
|
||||
n.addSvcRecords(alias, iface.Address().IP, false)
|
||||
n.addSvcRecords(alias, iface.Address().IP, ipv6, false)
|
||||
}
|
||||
} else {
|
||||
if ep.isAnonymous() {
|
||||
if len(myAliases) > 0 {
|
||||
n.deleteSvcRecords(myAliases[0], iface.Address().IP, true)
|
||||
n.deleteSvcRecords(myAliases[0], iface.Address().IP, ipv6, true)
|
||||
}
|
||||
} else {
|
||||
n.deleteSvcRecords(epName, iface.Address().IP, true)
|
||||
n.deleteSvcRecords(epName, iface.Address().IP, ipv6, true)
|
||||
}
|
||||
for _, alias := range myAliases {
|
||||
n.deleteSvcRecords(alias, iface.Address().IP, false)
|
||||
n.deleteSvcRecords(alias, iface.Address().IP, ipv6, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) addSvcRecords(name string, epIP net.IP, ipMapUpdate bool) {
|
||||
func addIPToName(ipMap map[string]string, name string, ip net.IP) {
|
||||
reverseIP := netutils.ReverseIP(ip.String())
|
||||
if _, ok := ipMap[reverseIP]; !ok {
|
||||
ipMap[reverseIP] = name
|
||||
}
|
||||
}
|
||||
|
||||
func addNameToIP(svcMap map[string][]net.IP, name string, epIP net.IP) {
|
||||
ipList := svcMap[name]
|
||||
for _, ip := range ipList {
|
||||
if ip.Equal(epIP) {
|
||||
return
|
||||
}
|
||||
}
|
||||
svcMap[name] = append(svcMap[name], epIP)
|
||||
}
|
||||
|
||||
func delNameToIP(svcMap map[string][]net.IP, name string, epIP net.IP) {
|
||||
ipList := svcMap[name]
|
||||
for i, ip := range ipList {
|
||||
if ip.Equal(epIP) {
|
||||
ipList = append(ipList[:i], ipList[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
svcMap[name] = ipList
|
||||
|
||||
if len(ipList) == 0 {
|
||||
delete(svcMap, name)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) addSvcRecords(name string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool) {
|
||||
c := n.getController()
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
sr, ok := c.svcDb[n.ID()]
|
||||
if !ok {
|
||||
sr = svcInfo{
|
||||
svcMap: make(map[string][]net.IP),
|
||||
ipMap: make(map[string]string),
|
||||
svcMap: make(map[string][]net.IP),
|
||||
svcIPv6Map: make(map[string][]net.IP),
|
||||
ipMap: make(map[string]string),
|
||||
}
|
||||
c.svcDb[n.ID()] = sr
|
||||
}
|
||||
|
||||
if ipMapUpdate {
|
||||
reverseIP := netutils.ReverseIP(epIP.String())
|
||||
if _, ok := sr.ipMap[reverseIP]; !ok {
|
||||
sr.ipMap[reverseIP] = name
|
||||
addIPToName(sr.ipMap, name, epIP)
|
||||
if epIPv6 != nil {
|
||||
addIPToName(sr.ipMap, name, epIPv6)
|
||||
}
|
||||
}
|
||||
|
||||
ipList := sr.svcMap[name]
|
||||
for _, ip := range ipList {
|
||||
if ip.Equal(epIP) {
|
||||
return
|
||||
}
|
||||
addNameToIP(sr.svcMap, name, epIP)
|
||||
if epIPv6 != nil {
|
||||
addNameToIP(sr.svcIPv6Map, name, epIPv6)
|
||||
}
|
||||
sr.svcMap[name] = append(sr.svcMap[name], epIP)
|
||||
}
|
||||
|
||||
func (n *network) deleteSvcRecords(name string, epIP net.IP, ipMapUpdate bool) {
|
||||
func (n *network) deleteSvcRecords(name string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool) {
|
||||
c := n.getController()
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
@ -962,19 +1002,16 @@ func (n *network) deleteSvcRecords(name string, epIP net.IP, ipMapUpdate bool) {
|
|||
|
||||
if ipMapUpdate {
|
||||
delete(sr.ipMap, netutils.ReverseIP(epIP.String()))
|
||||
}
|
||||
|
||||
ipList := sr.svcMap[name]
|
||||
for i, ip := range ipList {
|
||||
if ip.Equal(epIP) {
|
||||
ipList = append(ipList[:i], ipList[i+1:]...)
|
||||
break
|
||||
if epIPv6 != nil {
|
||||
delete(sr.ipMap, netutils.ReverseIP(epIPv6.String()))
|
||||
}
|
||||
}
|
||||
sr.svcMap[name] = ipList
|
||||
|
||||
if len(ipList) == 0 {
|
||||
delete(sr.svcMap, name)
|
||||
delNameToIP(sr.svcMap, name, epIP)
|
||||
|
||||
if epIPv6 != nil {
|
||||
delNameToIP(sr.svcIPv6Map, name, epIPv6)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1033,6 +1070,10 @@ func (n *network) ipamAllocate() error {
|
|||
}
|
||||
}()
|
||||
|
||||
if !n.enableIPv6 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return n.ipamAllocateVersion(6, ipam)
|
||||
}
|
||||
|
||||
|
@ -1153,7 +1194,7 @@ func (n *network) ipamReleaseVersion(ipVer int, ipam ipamapi.Ipam) {
|
|||
return
|
||||
}
|
||||
|
||||
if *infoList == nil {
|
||||
if len(*infoList) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
|
@ -185,27 +186,46 @@ func shuffleAddr(addr []net.IP) []net.IP {
|
|||
return addr
|
||||
}
|
||||
|
||||
func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) {
|
||||
addr := r.sb.ResolveName(name)
|
||||
func createRespMsg(query *dns.Msg) *dns.Msg {
|
||||
resp := new(dns.Msg)
|
||||
resp.SetReply(query)
|
||||
setCommonFlags(resp)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.Msg, error) {
|
||||
addr, ipv6Miss := r.sb.ResolveName(name, ipType)
|
||||
if addr == nil && ipv6Miss {
|
||||
// Send a reply without any Answer sections
|
||||
log.Debugf("Lookup name %s present without IPv6 address", name)
|
||||
resp := createRespMsg(query)
|
||||
return resp, nil
|
||||
}
|
||||
if addr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
log.Debugf("Lookup for %s: IP %v", name, addr)
|
||||
|
||||
resp := new(dns.Msg)
|
||||
resp.SetReply(query)
|
||||
setCommonFlags(resp)
|
||||
|
||||
resp := createRespMsg(query)
|
||||
if len(addr) > 1 {
|
||||
addr = shuffleAddr(addr)
|
||||
}
|
||||
|
||||
for _, ip := range addr {
|
||||
rr := new(dns.A)
|
||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||
rr.A = ip
|
||||
resp.Answer = append(resp.Answer, rr)
|
||||
if ipType == netutils.IPv4 {
|
||||
for _, ip := range addr {
|
||||
rr := new(dns.A)
|
||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||
rr.A = ip
|
||||
resp.Answer = append(resp.Answer, rr)
|
||||
}
|
||||
} else {
|
||||
for _, ip := range addr {
|
||||
rr := new(dns.AAAA)
|
||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: respTTL}
|
||||
rr.AAAA = ip
|
||||
resp.Answer = append(resp.Answer, rr)
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
@ -264,7 +284,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
}
|
||||
name := query.Question[0].Name
|
||||
if query.Question[0].Qtype == dns.TypeA {
|
||||
resp, err = r.handleIPv4Query(name, query)
|
||||
resp, err = r.handleIPQuery(name, query, netutils.IPv4)
|
||||
} else if query.Question[0].Qtype == dns.TypeAAAA {
|
||||
resp, err = r.handleIPQuery(name, query, netutils.IPv6)
|
||||
} else if query.Question[0].Qtype == dns.TypePTR {
|
||||
resp, err = r.handlePTRQuery(name, query)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -36,9 +37,11 @@ type Sandbox interface {
|
|||
Rename(name string) error
|
||||
// Delete destroys this container after detaching it from all connected endpoints.
|
||||
Delete() error
|
||||
// ResolveName searches for the service name in the networks to which the sandbox
|
||||
// is connected to.
|
||||
ResolveName(name string) []net.IP
|
||||
// ResolveName resolves a service name to an IPv4 or IPv6 address by searching
|
||||
// the networks the sandbox is connected to. For IPv6 queries, second return
|
||||
// value will be true if the name exists in docker domain but doesn't have an
|
||||
// IPv6 address. Such queries shouldn't be forwarded to external nameservers.
|
||||
ResolveName(name string, iplen int) ([]net.IP, bool)
|
||||
// ResolveIP returns the service name for the passed in IP. IP is in reverse dotted
|
||||
// notation; the format used for DNS PTR records
|
||||
ResolveIP(name string) string
|
||||
|
@ -418,9 +421,7 @@ func (sb *sandbox) execFunc(f func()) {
|
|||
sb.osSbox.InvokeFunc(f)
|
||||
}
|
||||
|
||||
func (sb *sandbox) ResolveName(name string) []net.IP {
|
||||
var ip []net.IP
|
||||
|
||||
func (sb *sandbox) ResolveName(name string, ipType int) ([]net.IP, bool) {
|
||||
// Embedded server owns the docker network domain. Resolution should work
|
||||
// for both container_name and container_name.network_name
|
||||
// We allow '.' in service name and network name. For a name a.b.c.d the
|
||||
|
@ -453,21 +454,29 @@ func (sb *sandbox) ResolveName(name string) []net.IP {
|
|||
log.Debugf("To resolve: %v in %v", reqName[i], networkName[i])
|
||||
|
||||
// First check for local container alias
|
||||
ip = sb.resolveName(reqName[i], networkName[i], epList, true)
|
||||
ip, ipv6Miss := sb.resolveName(reqName[i], networkName[i], epList, true, ipType)
|
||||
if ip != nil {
|
||||
return ip
|
||||
return ip, false
|
||||
}
|
||||
if ipv6Miss {
|
||||
return ip, ipv6Miss
|
||||
}
|
||||
|
||||
// Resolve the actual container name
|
||||
ip = sb.resolveName(reqName[i], networkName[i], epList, false)
|
||||
ip, ipv6Miss = sb.resolveName(reqName[i], networkName[i], epList, false, ipType)
|
||||
if ip != nil {
|
||||
return ip
|
||||
return ip, false
|
||||
}
|
||||
if ipv6Miss {
|
||||
return ip, ipv6Miss
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool) []net.IP {
|
||||
func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool, ipType int) ([]net.IP, bool) {
|
||||
var ipv6Miss bool
|
||||
|
||||
for _, ep := range epList {
|
||||
name := req
|
||||
n := ep.getNetwork()
|
||||
|
@ -504,14 +513,26 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
|
|||
continue
|
||||
}
|
||||
|
||||
var ip []net.IP
|
||||
n.Lock()
|
||||
ip, ok := sr.svcMap[name]
|
||||
ip, ok = sr.svcMap[name]
|
||||
|
||||
if ipType == netutils.IPv6 {
|
||||
// If the name resolved to v4 address then its a valid name in
|
||||
// the docker network domain. If the network is not v6 enabled
|
||||
// set ipv6Miss to filter the DNS query from going to external
|
||||
// resolvers.
|
||||
if ok && n.enableIPv6 == false {
|
||||
ipv6Miss = true
|
||||
}
|
||||
ip = sr.svcIPv6Map[name]
|
||||
}
|
||||
n.Unlock()
|
||||
if ok {
|
||||
return ip
|
||||
if ip != nil {
|
||||
return ip, false
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return nil, ipv6Miss
|
||||
}
|
||||
|
||||
func (sb *sandbox) SetKey(basePath string) error {
|
||||
|
|
Loading…
Reference in a new issue