diff --git a/components/engine/daemon/container_unix.go b/components/engine/daemon/container_unix.go index fb6695cc3e..c005347f14 100644 --- a/components/engine/daemon/container_unix.go +++ b/components/engine/daemon/container_unix.go @@ -680,6 +680,10 @@ func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwor return networkSettings, nil } + if iface.MacAddress() != nil { + networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() + } + if iface.Address() != nil { ones, _ := iface.Address().Mask.Size() networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() @@ -692,23 +696,14 @@ func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwor networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6 } - driverInfo, err := ep.DriverInfo() - if err != nil { - return nil, err - } - - if driverInfo == nil { - // It is not an error for epInfo to be nil - return networkSettings, nil - } - if mac, ok := driverInfo[netlabel.MacAddress]; ok { - networkSettings.Networks[n.Name()].MacAddress = mac.(net.HardwareAddr).String() - } - return networkSettings, nil } func (container *Container) updateJoinInfo(n libnetwork.Network, ep libnetwork.Endpoint) error { + if _, err := container.buildPortMapInfo(ep, container.NetworkSettings); err != nil { + return err + } + epInfo := ep.Info() if epInfo == nil { // It is not an error to get an empty endpoint info @@ -754,12 +749,7 @@ func (container *Container) updateNetworkSettings(n libnetwork.Network) error { } func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error { - networkSettings, err := container.buildPortMapInfo(ep, container.NetworkSettings) - if err != nil { - return err - } - - networkSettings, err = container.buildEndpointInfo(n, ep, networkSettings) + networkSettings, err := container.buildEndpointInfo(n, ep, container.NetworkSettings) if err != nil { return err } diff --git a/components/engine/hack/vendor.sh b/components/engine/hack/vendor.sh index c28e677220..67ff012691 100755 --- a/components/engine/hack/vendor.sh +++ b/components/engine/hack/vendor.sh @@ -21,7 +21,7 @@ clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git #get libnetwork packages -clone git github.com/docker/libnetwork abc0807d72e309f53155ec4f6374a77fd6613849 +clone git github.com/docker/libnetwork 20351a84241aa1278493d74492db947336989be6 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4 diff --git a/components/engine/integration-cli/docker_cli_network_unix_test.go b/components/engine/integration-cli/docker_cli_network_unix_test.go index d4a7eb337f..432c40abda 100644 --- a/components/engine/integration-cli/docker_cli_network_unix_test.go +++ b/components/engine/integration-cli/docker_cli_network_unix_test.go @@ -20,6 +20,7 @@ import ( remoteipam "github.com/docker/libnetwork/ipams/remote/api" "github.com/docker/libnetwork/netlabel" "github.com/go-check/check" + "github.com/vishvananda/netlink" ) const dummyNetworkDriver = "dummy-network-driver" @@ -79,6 +80,36 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) { fmt.Fprintf(w, "null") }) + mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + fmt.Fprintf(w, `{"Interface":{"MacAddress":"a0:b1:c2:d3:e4:f5"}}`) + }) + + mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + + veth := &netlink.Veth{ + LinkAttrs: netlink.LinkAttrs{Name: "randomIfName", TxQLen: 0}, PeerName: "cnt0"} + if err := netlink.LinkAdd(veth); err != nil { + fmt.Fprintf(w, `{"Error":"failed to add veth pair: `+err.Error()+`"}`) + } else { + fmt.Fprintf(w, `{"InterfaceName":{ "SrcName":"cnt0", "DstPrefix":"veth"}}`) + } + }) + + mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + fmt.Fprintf(w, "null") + }) + + mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") + if link, err := netlink.LinkByName("cnt0"); err == nil { + netlink.LinkDel(link) + } + fmt.Fprintf(w, "null") + }) + // Ipam Driver implementation var ( poolRequest remoteipam.RequestPoolRequest @@ -566,3 +597,44 @@ func (s *DockerNetworkSuite) TestDockerNetworkLinkOndefaultNetworkOnly(c *check. dockerCmd(c, "network", "connect", "bridge", cnt2) dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top") } + +func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) { + // Verify exposed ports are present in ps output when running a container on + // a network managed by a driver which does not provide the default gateway + // for the container + nwn := "ov" + ctn := "bb" + port1 := 80 + port2 := 443 + expose1 := fmt.Sprintf("--expose=%d", port1) + expose2 := fmt.Sprintf("--expose=%d", port2) + + dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn) + assertNwIsAvailable(c, nwn) + + dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, expose1, expose2, "busybox", "top") + + // Check docker ps o/p for last created container reports the unpublished ports + unpPort1 := fmt.Sprintf("%d/tcp", port1) + unpPort2 := fmt.Sprintf("%d/tcp", port2) + out, _ := dockerCmd(c, "ps", "-n=1") + // Missing unpublished ports in docker ps output + c.Assert(out, checker.Contains, unpPort1) + // Missing unpublished ports in docker ps output + c.Assert(out, checker.Contains, unpPort2) +} + +func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) { + // Verify endpoint MAC address is correctly populated in container's network settings + nwn := "ov" + ctn := "bb" + + dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn) + assertNwIsAvailable(c, nwn) + + dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, "busybox", "top") + + mac, err := inspectField(ctn, "NetworkSettings.Networks."+nwn+".MacAddress") + c.Assert(err, checker.IsNil) + c.Assert(mac, checker.Equals, "a0:b1:c2:d3:e4:f5") +} diff --git a/components/engine/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go b/components/engine/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go index 05d08683c6..6124ccb6cb 100644 --- a/components/engine/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/components/engine/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -338,16 +338,11 @@ func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridge } func (d *driver) configure(option map[string]interface{}) error { - var config *configuration - var err error - - err = d.initStore(option) - if err != nil { - return err - } - - d.Lock() - defer d.Unlock() + var ( + config *configuration + err error + natChain, filterChain *iptables.ChainInfo + ) genericData, ok := option[netlabel.GenericData] if !ok || genericData == nil { @@ -375,13 +370,23 @@ func (d *driver) configure(option map[string]interface{}) error { } if config.EnableIPTables { - d.natChain, d.filterChain, err = setupIPChains(config) + natChain, filterChain, err = setupIPChains(config) if err != nil { return err } } + d.Lock() + d.natChain = natChain + d.filterChain = filterChain d.config = config + d.Unlock() + + err = d.initStore(option) + if err != nil { + return err + } + return nil } diff --git a/components/engine/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_serf.go b/components/engine/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_serf.go index 894cb582ca..a10bbf8e33 100644 --- a/components/engine/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_serf.go +++ b/components/engine/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_serf.go @@ -48,6 +48,7 @@ func (d *driver) serfInit() error { config.UserQuiescentPeriod = 50 * time.Millisecond config.LogOutput = &logWriter{} + config.MemberlistConfig.LogOutput = config.LogOutput s, err := serf.Create(config) if err != nil { diff --git a/components/engine/vendor/src/github.com/docker/libnetwork/endpoint_info.go b/components/engine/vendor/src/github.com/docker/libnetwork/endpoint_info.go index 3ca6b2b834..db23eb738f 100644 --- a/components/engine/vendor/src/github.com/docker/libnetwork/endpoint_info.go +++ b/components/engine/vendor/src/github.com/docker/libnetwork/endpoint_info.go @@ -163,6 +163,17 @@ func (ep *endpoint) Info() EndpointInfo { } func (ep *endpoint) DriverInfo() (map[string]interface{}, error) { + ep, err := ep.retrieveFromStore() + if err != nil { + return nil, err + } + + if sb, ok := ep.getSandbox(); ok { + if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() { + return gwep.DriverInfo() + } + } + n, err := ep.getNetworkFromStore() if err != nil { return nil, fmt.Errorf("could not find network in store for driver info: %v", err) @@ -317,3 +328,11 @@ func (ep *endpoint) SetGatewayIPv6(gw6 net.IP) error { ep.joinInfo.gw6 = types.GetIPCopy(gw6) return nil } + +func (ep *endpoint) retrieveFromStore() (*endpoint, error) { + n, err := ep.getNetworkFromStore() + if err != nil { + return nil, fmt.Errorf("could not find network in store to get latest endpoint %s: %v", ep.Name(), err) + } + return n.getEndpointFromStore(ep.ID()) +} diff --git a/components/engine/vendor/src/github.com/docker/libnetwork/store.go b/components/engine/vendor/src/github.com/docker/libnetwork/store.go index 299e83ad6d..1ea2f7ae89 100644 --- a/components/engine/vendor/src/github.com/docker/libnetwork/store.go +++ b/components/engine/vendor/src/github.com/docker/libnetwork/store.go @@ -265,6 +265,7 @@ func (c *controller) networkWatchLoop(nw *netWatch, ep *endpoint, ecCh <-chan da var addEp []*endpoint delEpMap := make(map[string]*endpoint) + renameEpMap := make(map[string]bool) for k, v := range nw.remoteEps { delEpMap[k] = v } @@ -285,10 +286,20 @@ func (c *controller) networkWatchLoop(nw *netWatch, ep *endpoint, ecCh <-chan da delete(delEpMap, lEp.ID()) continue } + renameEpMap[lEp.ID()] = true } nw.remoteEps[lEp.ID()] = lEp addEp = append(addEp, lEp) } + + // EPs whose name are to be deleted from the svc records + // should also be removed from nw's remote EP list, except + // the ones that are getting renamed. + for _, lEp := range delEpMap { + if !renameEpMap[lEp.ID()] { + delete(nw.remoteEps, lEp.ID()) + } + } c.Unlock() for _, lEp := range delEpMap {