From d0e0c13b603efaff14c0269d19ac7e3710307fab Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Mon, 14 Sep 2015 11:04:12 -0700 Subject: [PATCH] Vendor-in 2baa2ddc78b42f011f55633282ac63a72e1b09c1 for userns support Changes include : * libnetwork support for userns * driver api change to have 1 interface per endpoint Signed-off-by: Madhu Venugopal --- daemon/container_unix.go | 24 +-- daemon/daemon.go | 4 +- hack/vendor.sh | 2 +- .../github.com/docker/libnetwork/.gitignore | 1 + .../src/github.com/docker/libnetwork/Makefile | 25 ++- .../github.com/docker/libnetwork/api/api.go | 3 + .../github.com/docker/libnetwork/api/types.go | 1 + .../docker/libnetwork/client/service.go | 9 +- .../docker/libnetwork/config/config.go | 2 +- .../docker/libnetwork/controller.go | 37 ++-- .../docker/libnetwork/driverapi/driverapi.go | 36 ++-- .../libnetwork/drivers/bridge/bridge.go | 19 +- .../libnetwork/drivers/overlay/joinleave.go | 11 +- .../libnetwork/drivers/overlay/ov_endpoint.go | 8 +- .../libnetwork/drivers/remote/api/api.go | 15 +- .../libnetwork/drivers/remote/driver.go | 75 ++++--- .../github.com/docker/libnetwork/endpoint.go | 41 ++-- .../docker/libnetwork/endpoint_info.go | 68 +++---- .../github.com/docker/libnetwork/network.go | 3 +- .../docker/libnetwork/osl/namespace_linux.go | 43 ++-- .../libnetwork/osl/namespace_unsupported.go | 4 + .../libnetwork/osl/namespace_windows.go | 4 + .../github.com/docker/libnetwork/sandbox.go | 104 ++++++++-- .../docker/libnetwork/sandbox_externalkey.go | 185 ++++++++++++++++++ .../docker/libnetwork/types/types.go | 12 +- 25 files changed, 490 insertions(+), 246 deletions(-) create mode 100644 vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go diff --git a/daemon/container_unix.go b/daemon/container_unix.go index 4eca92ed30..bdeaa190ca 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -580,13 +580,11 @@ func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSet return networkSettings, nil } - ifaceList := epInfo.InterfaceList() - if len(ifaceList) == 0 { + iface := epInfo.Iface() + if iface == nil { return networkSettings, nil } - iface := ifaceList[0] - ones, _ := iface.Address().Mask.Size() networkSettings.IPAddress = iface.Address().IP.String() networkSettings.IPPrefixLen = ones @@ -597,24 +595,6 @@ func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSet networkSettings.GlobalIPv6PrefixLen = onesv6 } - if len(ifaceList) == 1 { - return networkSettings, nil - } - - networkSettings.SecondaryIPAddresses = make([]network.Address, 0, len(ifaceList)-1) - networkSettings.SecondaryIPv6Addresses = make([]network.Address, 0, len(ifaceList)-1) - for _, iface := range ifaceList[1:] { - ones, _ := iface.Address().Mask.Size() - addr := network.Address{Addr: iface.Address().IP.String(), PrefixLen: ones} - networkSettings.SecondaryIPAddresses = append(networkSettings.SecondaryIPAddresses, addr) - - if iface.AddressIPv6().IP.To16() != nil { - onesv6, _ := iface.AddressIPv6().Mask.Size() - addrv6 := network.Address{Addr: iface.AddressIPv6().IP.String(), PrefixLen: onesv6} - networkSettings.SecondaryIPv6Addresses = append(networkSettings.SecondaryIPv6Addresses, addrv6) - } - } - return networkSettings, nil } diff --git a/daemon/daemon.go b/daemon/daemon.go index 3dcf93b629..1ed7273226 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -820,9 +820,9 @@ func (daemon *Daemon) Shutdown() error { } group.Wait() - // trigger libnetwork GC only if it's initialized + // trigger libnetwork Stop only if it's initialized if daemon.netController != nil { - daemon.netController.GC() + daemon.netController.Stop() } } diff --git a/hack/vendor.sh b/hack/vendor.sh index b84f1b14b1..0f49839385 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -20,7 +20,7 @@ clone git github.com/tchap/go-patricia v2.1.0 clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git #get libnetwork packages -clone git github.com/docker/libnetwork 3e31cead05cba8ec20241630d051e6d73765b3a2 +clone git github.com/docker/libnetwork 2baa2ddc78b42f011f55633282ac63a72e1b09c1 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/vendor/src/github.com/docker/libnetwork/.gitignore b/vendor/src/github.com/docker/libnetwork/.gitignore index c03c9653ab..0f3e6e30dd 100644 --- a/vendor/src/github.com/docker/libnetwork/.gitignore +++ b/vendor/src/github.com/docker/libnetwork/.gitignore @@ -4,6 +4,7 @@ *.so # Folders +integration-tmp/ _obj _test diff --git a/vendor/src/github.com/docker/libnetwork/Makefile b/vendor/src/github.com/docker/libnetwork/Makefile index 830a75b046..e9d06e5e8f 100644 --- a/vendor/src/github.com/docker/libnetwork/Makefile +++ b/vendor/src/github.com/docker/libnetwork/Makefile @@ -1,4 +1,4 @@ -.PHONY: all all-local build build-local check check-code check-format run-tests check-local install-deps coveralls circle-ci +.PHONY: all all-local build build-local check check-code check-format run-tests check-local integration-tests install-deps coveralls circle-ci SHELL=/bin/bash build_image=libnetwork-build dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork @@ -7,8 +7,15 @@ docker = docker run --rm -it ${dockerargs} ${container_env} ${build_image} ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true" cidocker = docker run ${ciargs} ${dockerargs} golang:1.4 -all: ${build_image}.created - ${docker} ./wrapmake.sh all-local +all: ${build_image}.created build check integration-tests + +integration-tests: + @if [ ! -d ./integration-tmp ]; then \ + mkdir -p ./integration-tmp; \ + git clone https://github.com/sstephenson/bats.git ./integration-tmp/bats; \ + ./integration-tmp/bats/install.sh ./integration-tmp; \ + fi + @./integration-tmp/bin/bats ./test/integration/dnet all-local: check-local build-local @@ -19,13 +26,16 @@ ${build_image}.created: touch ${build_image}.created build: ${build_image}.created - ${docker} ./wrapmake.sh build-local + @echo "Building code... " + @${docker} ./wrapmake.sh build-local + @echo "Done building code" build-local: - $(shell which godep) go build -tags libnetwork_discovery ./... + @$(shell which godep) go build -tags libnetwork_discovery ./... + @$(shell which godep) go build -o ./cmd/dnet/dnet ./cmd/dnet check: ${build_image}.created - ${docker} ./wrapmake.sh check-local + @${docker} ./wrapmake.sh check-local check-code: @echo "Checking code... " @@ -76,4 +86,5 @@ coveralls: # The following target is a workaround for this circle-ci: - @${cidocker} make install-deps check-local coveralls + @${cidocker} make install-deps build-local check-local coveralls + make integration-tests diff --git a/vendor/src/github.com/docker/libnetwork/api/api.go b/vendor/src/github.com/docker/libnetwork/api/api.go index 07ebf8bf59..5f48531998 100644 --- a/vendor/src/github.com/docker/libnetwork/api/api.go +++ b/vendor/src/github.com/docker/libnetwork/api/api.go @@ -249,6 +249,9 @@ func (sc *sandboxCreate) parseOptions() []libnetwork.SandboxOption { if sc.UseDefaultSandbox { setFctList = append(setFctList, libnetwork.OptionUseDefaultSandbox()) } + if sc.UseExternalKey { + setFctList = append(setFctList, libnetwork.OptionUseExternalKey()) + } if sc.DNS != nil { for _, d := range sc.DNS { setFctList = append(setFctList, libnetwork.OptionDNS(d)) diff --git a/vendor/src/github.com/docker/libnetwork/api/types.go b/vendor/src/github.com/docker/libnetwork/api/types.go index d734a97c0e..6218932d00 100644 --- a/vendor/src/github.com/docker/libnetwork/api/types.go +++ b/vendor/src/github.com/docker/libnetwork/api/types.go @@ -57,6 +57,7 @@ type sandboxCreate struct { DNS []string `json:"dns"` ExtraHosts []extraHost `json:"extra_hosts"` UseDefaultSandbox bool `json:"use_default_sandbox"` + UseExternalKey bool `json:"use_external_key"` } // endpointJoin represents the expected body of the "join endpoint" or "leave endpoint" http request messages diff --git a/vendor/src/github.com/docker/libnetwork/client/service.go b/vendor/src/github.com/docker/libnetwork/client/service.go index 6b8fa15c7b..36564977fb 100644 --- a/vendor/src/github.com/docker/libnetwork/client/service.go +++ b/vendor/src/github.com/docker/libnetwork/client/service.go @@ -115,7 +115,7 @@ func lookupContainerID(cli *NetworkCli, cnNameID string) (string, error) { } func lookupSandboxID(cli *NetworkCli, containerID string) (string, error) { - obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/sandboxes?container-id=%s", containerID), nil, nil)) + obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/sandboxes?partial-container-id=%s", containerID), nil, nil)) if err != nil { return "", err } @@ -360,12 +360,17 @@ func (cli *NetworkCli) CmdServiceDetach(chain string, args ...string) error { return err } + sandboxID, err := lookupSandboxID(cli, containerID) + if err != nil { + return err + } + serviceID, err := lookupServiceID(cli, nn, sn) if err != nil { return err } - _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID+"/backend/"+containerID, nil, nil)) + _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID+"/backend/"+sandboxID, nil, nil)) if err != nil { return err } diff --git a/vendor/src/github.com/docker/libnetwork/config/config.go b/vendor/src/github.com/docker/libnetwork/config/config.go index bb93d981b1..1935e1657b 100644 --- a/vendor/src/github.com/docker/libnetwork/config/config.go +++ b/vendor/src/github.com/docker/libnetwork/config/config.go @@ -109,7 +109,7 @@ func (c *Config) ProcessOptions(options ...Option) { // IsValidName validates configuration objects supported by libnetwork func IsValidName(name string) bool { - if name == "" || strings.Contains(name, ".") { + if strings.TrimSpace(name) == "" || strings.Contains(name, ".") { return false } return true diff --git a/vendor/src/github.com/docker/libnetwork/controller.go b/vendor/src/github.com/docker/libnetwork/controller.go index 178c57b7da..83f30e75f1 100644 --- a/vendor/src/github.com/docker/libnetwork/controller.go +++ b/vendor/src/github.com/docker/libnetwork/controller.go @@ -65,6 +65,9 @@ import ( // NetworkController provides the interface for controller instance which manages // networks. type NetworkController interface { + // ID provides an unique identity for the controller + ID() string + // ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type ConfigureNetworkDriver(networkType string, options map[string]interface{}) error @@ -99,8 +102,8 @@ type NetworkController interface { // SandboxByID returns the Sandbox which has the passed id. If not found, a types.NotFoundError is returned. SandboxByID(id string) (Sandbox, error) - // GC triggers immediate garbage collection of resources which are garbage collected. - GC() + // Stop network controller + Stop() } // NetworkWalker is a client provided function which will be used to walk the Networks. @@ -122,11 +125,13 @@ type endpointTable map[string]*endpoint type sandboxTable map[string]*sandbox type controller struct { - networks networkTable - drivers driverTable - sandboxes sandboxTable - cfg *config.Config - store datastore.DataStore + id string + networks networkTable + drivers driverTable + sandboxes sandboxTable + cfg *config.Config + store datastore.DataStore + extKeyListener net.Listener sync.Mutex } @@ -138,6 +143,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { cfg.ProcessOptions(cfgOptions...) } c := &controller{ + id: stringid.GenerateRandomID(), cfg: cfg, networks: networkTable{}, sandboxes: sandboxTable{}, @@ -159,9 +165,17 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { } } + if err := c.startExternalKeyListener(); err != nil { + return nil, err + } + return c, nil } +func (c *controller) ID() string { + return c.id +} + func (c *controller) validateHostDiscoveryConfig() bool { if c.cfg == nil || c.cfg.Cluster.Discovery == "" || c.cfg.Cluster.Address == "" { return false @@ -204,11 +218,11 @@ func (c *controller) ConfigureNetworkDriver(networkType string, options map[stri } func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver, capability driverapi.Capability) error { - c.Lock() if !config.IsValidName(networkType) { - c.Unlock() return ErrInvalidName(networkType) } + + c.Lock() if _, ok := c.drivers[networkType]; ok { c.Unlock() return driverapi.ErrActiveRegistration(networkType) @@ -414,7 +428,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S return nil, err } - if sb.osSbox == nil { + if sb.osSbox == nil && !sb.config.useExternalKey { if sb.osSbox, err = osl.NewSandbox(sb.Key(), !sb.config.useDefaultSandBox); err != nil { return nil, fmt.Errorf("failed to create new osl sandbox: %v", err) } @@ -514,6 +528,7 @@ func (c *controller) isDriverGlobalScoped(networkType string) (bool, error) { return false, nil } -func (c *controller) GC() { +func (c *controller) Stop() { + c.stopExternalKeyListener() osl.GC() } diff --git a/vendor/src/github.com/docker/libnetwork/driverapi/driverapi.go b/vendor/src/github.com/docker/libnetwork/driverapi/driverapi.go index 97813a9824..bfe44be469 100644 --- a/vendor/src/github.com/docker/libnetwork/driverapi/driverapi.go +++ b/vendor/src/github.com/docker/libnetwork/driverapi/driverapi.go @@ -45,18 +45,16 @@ type Driver interface { // EndpointInfo provides a go interface to fetch or populate endpoint assigned network resources. type EndpointInfo interface { - // Interfaces returns a list of interfaces bound to the endpoint. - // If the list is not empty the driver is only expected to consume the interfaces. - // It is an error to try to add interfaces to a non-empty list. - // If the list is empty the driver is expected to populate with 0 or more interfaces. - Interfaces() []InterfaceInfo + // Interface returns the interface bound to the endpoint. + // If the value is not nil the driver is only expected to consume the interface. + // It is an error to try to add interface if the passed down value is non-nil + // If the value is nil the driver is expected to add an interface + Interface() InterfaceInfo - // AddInterface is used by the driver to add an interface to the interface list. - // This method will return an error if the driver attempts to add interfaces - // if the Interfaces() method returned a non-empty list. - // ID field need only have significance within the endpoint so it can be a simple - // monotonically increasing number - AddInterface(ID int, mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error + // AddInterface is used by the driver to add an interface for the endpoint. + // This method will return an error if the driver attempts to add interface + // if the Interface() method returned a non-nil value. + AddInterface(mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error } // InterfaceInfo provides a go interface for drivers to retrive @@ -70,10 +68,6 @@ type InterfaceInfo interface { // AddressIPv6 returns the IPv6 address. AddressIPv6() net.IPNet - - // ID returns the numerical id of the interface and has significance only within - // the endpoint. - ID() int } // InterfaceNameInfo provides a go interface for the drivers to assign names @@ -81,18 +75,14 @@ type InterfaceInfo interface { type InterfaceNameInfo interface { // SetNames method assigns the srcName and dstPrefix for the interface. SetNames(srcName, dstPrefix string) error - - // ID returns the numerical id that was assigned to the interface by the driver - // CreateEndpoint. - ID() int } // JoinInfo represents a set of resources that the driver has the ability to provide during // join time. type JoinInfo interface { - // InterfaceNames returns a list of InterfaceNameInfo go interface to facilitate - // setting the names for the interfaces. - InterfaceNames() []InterfaceNameInfo + // InterfaceName returns a InterfaceNameInfo go interface to facilitate + // setting the names for the interface. + InterfaceName() InterfaceNameInfo // SetGateway sets the default IPv4 gateway when a container joins the endpoint. SetGateway(net.IP) error @@ -102,7 +92,7 @@ type JoinInfo interface { // AddStaticRoute adds a routes to the sandbox. // It may be used in addtion to or instead of a default gateway (as above). - AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP, interfaceID int) error + AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error } // DriverCallback provides a Callback interface for Drivers into LibNetwork diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go index 10a72d684c..127fe7ceec 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -32,7 +32,6 @@ const ( vethLen = 7 containerVethPrefix = "eth" maxAllocatePortAttempts = 10 - ifaceID = 1 ) var ( @@ -883,8 +882,8 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, return errors.New("invalid endpoint info passed") } - if len(epInfo.Interfaces()) != 0 { - return errors.New("non empty interface list passed to bridge(local) driver") + if epInfo.Interface() != nil { + return errors.New("non-nil interface passed to bridge(local) driver") } // Get the network handler and make sure it exists @@ -1070,7 +1069,7 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, endpoint.addrv6 = ipv6Addr } - err = epInfo.AddInterface(ifaceID, endpoint.macAddress, *ipv4Addr, *ipv6Addr) + err = epInfo.AddInterface(endpoint.macAddress, *ipv4Addr, *ipv6Addr) if err != nil { return err } @@ -1244,14 +1243,10 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return EndpointNotFoundError(eid) } - for _, iNames := range jinfo.InterfaceNames() { - // Make sure to set names on the correct interface ID. - if iNames.ID() == ifaceID { - err = iNames.SetNames(endpoint.srcName, containerVethPrefix) - if err != nil { - return err - } - } + iNames := jinfo.InterfaceName() + err = iNames.SetNames(endpoint.srcName, containerVethPrefix) + if err != nil { + return err } err = jinfo.SetGateway(network.bridge.gatewayIPv4) diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go index 39e4634227..97083234e7 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go @@ -65,13 +65,10 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf("could not set mac address to the container interface: %v", err) } - for _, iNames := range jinfo.InterfaceNames() { - // Make sure to set names on the correct interface ID. - if iNames.ID() == 1 { - err = iNames.SetNames(name2, "eth") - if err != nil { - return err - } + if iNames := jinfo.InterfaceName(); iNames != nil { + err = iNames.SetNames(name2, "eth") + if err != nil { + return err } } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go index ed9658e3c8..71e73c4e0a 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go @@ -51,10 +51,10 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, id: eid, } - if epInfo != nil && (len(epInfo.Interfaces()) > 0) { - addr := epInfo.Interfaces()[0].Address() + if epInfo != nil && epInfo.Interface() != nil { + addr := epInfo.Interface().Address() ep.addr = &addr - ep.mac = epInfo.Interfaces()[0].MacAddress() + ep.mac = epInfo.Interface().MacAddress() n.addEndpoint(ep) return nil } @@ -74,7 +74,7 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, ep.mac = netutils.GenerateMACFromIP(ep.addr.IP) - err = epInfo.AddInterface(1, ep.mac, *ep.addr, net.IPNet{}) + err = epInfo.AddInterface(ep.mac, *ep.addr, net.IPNet{}) if err != nil { return fmt.Errorf("could not add interface to endpoint info: %v", err) } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go b/vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go index 35ad2bfe15..2a0d297ce5 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/remote/api/api.go @@ -48,13 +48,12 @@ type CreateEndpointRequest struct { NetworkID string // The ID of the endpoint for later reference. EndpointID string - Interfaces []*EndpointInterface + Interface *EndpointInterface Options map[string]interface{} } // EndpointInterface represents an interface endpoint. type EndpointInterface struct { - ID int Address string AddressIPv6 string MacAddress string @@ -63,12 +62,11 @@ type EndpointInterface struct { // CreateEndpointResponse is the response to the CreateEndpoint action. type CreateEndpointResponse struct { Response - Interfaces []*EndpointInterface + Interface *EndpointInterface } // Interface is the representation of a linux interface. type Interface struct { - ID int Address *net.IPNet AddressIPv6 *net.IPNet MacAddress net.HardwareAddr @@ -118,16 +116,15 @@ type StaticRoute struct { Destination string RouteType int NextHop string - InterfaceID int } // JoinResponse is the response to a JoinRequest. type JoinResponse struct { Response - InterfaceNames []*InterfaceName - Gateway string - GatewayIPv6 string - StaticRoutes []StaticRoute + InterfaceName *InterfaceName + Gateway string + GatewayIPv6 string + StaticRoutes []StaticRoute } // LeaveRequest describes the API for detaching an endpoint from a sandbox. diff --git a/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go b/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go index 88827e5d75..88afd53903 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/remote/driver.go @@ -71,16 +71,17 @@ func (d *driver) DeleteNetwork(nid string) error { } func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error { + var reqIface *api.EndpointInterface + if epInfo == nil { return fmt.Errorf("must not be called with nil EndpointInfo") } - reqIfaces := make([]*api.EndpointInterface, len(epInfo.Interfaces())) - for i, iface := range epInfo.Interfaces() { + iface := epInfo.Interface() + if iface != nil { addr4 := iface.Address() addr6 := iface.AddressIPv6() - reqIfaces[i] = &api.EndpointInterface{ - ID: iface.ID(), + reqIface = &api.EndpointInterface{ Address: addr4.String(), AddressIPv6: addr6.String(), MacAddress: iface.MacAddress().String(), @@ -89,7 +90,7 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, create := &api.CreateEndpointRequest{ NetworkID: nid, EndpointID: eid, - Interfaces: reqIfaces, + Interface: reqIface, Options: epOptions, } var res api.CreateEndpointResponse @@ -97,25 +98,26 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, return err } - ifaces, err := parseInterfaces(res) + inIface, err := parseInterface(res) if err != nil { return err } - if len(reqIfaces) > 0 && len(ifaces) > 0 { - // We're not supposed to add interfaces if there already are - // some. Attempt to roll back - return errorWithRollback("driver attempted to add more interfaces", d.DeleteEndpoint(nid, eid)) + if reqIface != nil && inIface != nil { + // We're not supposed to add interface if there is already + // one. Attempt to roll back + return errorWithRollback("driver attempted to add interface ignoring the one provided", d.DeleteEndpoint(nid, eid)) } - for _, iface := range ifaces { + + if inIface != nil { var addr4, addr6 net.IPNet - if iface.Address != nil { - addr4 = *(iface.Address) + if inIface.Address != nil { + addr4 = *(inIface.Address) } - if iface.AddressIPv6 != nil { - addr6 = *(iface.AddressIPv6) + if inIface.AddressIPv6 != nil { + addr6 = *(inIface.AddressIPv6) } - if err := epInfo.AddInterface(iface.ID, iface.MacAddress, addr4, addr6); err != nil { - return errorWithRollback(fmt.Sprintf("failed to AddInterface %v: %s", iface, err), d.DeleteEndpoint(nid, eid)) + if err := epInfo.AddInterface(inIface.MacAddress, addr4, addr6); err != nil { + return errorWithRollback(fmt.Sprintf("failed to AddInterface %v: %s", inIface, err), d.DeleteEndpoint(nid, eid)) } } return nil @@ -165,18 +167,13 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return err } - // Expect each interface ID given by CreateEndpoint to have an - // entry at that index in the names supplied here. In other words, - // if you supply 0..n interfaces with IDs 0..n above, you should - // supply the names in the same order. - ifaceNames := res.InterfaceNames - for _, iface := range jinfo.InterfaceNames() { - i := iface.ID() - if i >= len(ifaceNames) || i < 0 { - return fmt.Errorf("no correlating interface %d in supplied interface names", i) - } - supplied := ifaceNames[i] - if err := iface.SetNames(supplied.SrcName, supplied.DstPrefix); err != nil { + ifaceName := res.InterfaceName + if ifaceName == nil { + return fmt.Errorf("no interface name information received") + } + + if iface := jinfo.InterfaceName(); iface != nil { + if err := iface.SetNames(ifaceName.SrcName, ifaceName.DstPrefix); err != nil { return errorWithRollback(fmt.Sprintf("failed to set interface name: %s", err), d.Leave(nid, eid)) } } @@ -204,7 +201,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return err } for _, route := range routes { - if jinfo.AddStaticRoute(route.Destination, route.RouteType, route.NextHop, route.InterfaceID) != nil { + if jinfo.AddStaticRoute(route.Destination, route.RouteType, route.NextHop) != nil { return errorWithRollback(fmt.Sprintf("failed to set static route: %v", route), d.Leave(nid, eid)) } } @@ -229,7 +226,7 @@ func parseStaticRoutes(r api.JoinResponse) ([]*types.StaticRoute, error) { var routes = make([]*types.StaticRoute, len(r.StaticRoutes)) for i, inRoute := range r.StaticRoutes { var err error - outRoute := &types.StaticRoute{InterfaceID: inRoute.InterfaceID, RouteType: inRoute.RouteType} + outRoute := &types.StaticRoute{RouteType: inRoute.RouteType} if inRoute.Destination != "" { if outRoute.Destination, err = toAddr(inRoute.Destination); err != nil { @@ -250,13 +247,13 @@ func parseStaticRoutes(r api.JoinResponse) ([]*types.StaticRoute, error) { } // parseInterfaces validates all the parameters of an Interface and returns them. -func parseInterfaces(r api.CreateEndpointResponse) ([]*api.Interface, error) { - var ( - Interfaces = make([]*api.Interface, len(r.Interfaces)) - ) - for i, inIf := range r.Interfaces { +func parseInterface(r api.CreateEndpointResponse) (*api.Interface, error) { + var outIf *api.Interface + + inIf := r.Interface + if inIf != nil { var err error - outIf := &api.Interface{ID: inIf.ID} + outIf = &api.Interface{} if inIf.Address != "" { if outIf.Address, err = toAddr(inIf.Address); err != nil { return nil, err @@ -272,9 +269,9 @@ func parseInterfaces(r api.CreateEndpointResponse) ([]*api.Interface, error) { return nil, err } } - Interfaces[i] = outIf } - return Interfaces, nil + + return outIf, nil } func toAddr(ipAddr string) (*net.IPNet, error) { diff --git a/vendor/src/github.com/docker/libnetwork/endpoint.go b/vendor/src/github.com/docker/libnetwork/endpoint.go index 0ec9f1d798..a8b3acd032 100644 --- a/vendor/src/github.com/docker/libnetwork/endpoint.go +++ b/vendor/src/github.com/docker/libnetwork/endpoint.go @@ -1,6 +1,7 @@ package libnetwork import ( + "container/heap" "encoding/json" "fmt" "net" @@ -49,7 +50,7 @@ type endpoint struct { name string id string network *network - iFaces []*endpointInterface + iface *endpointInterface joinInfo *endpointJoinInfo sandboxID string exposedPorts []types.TransportPort @@ -67,7 +68,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) { epMap := make(map[string]interface{}) epMap["name"] = ep.name epMap["id"] = ep.id - epMap["ep_iface"] = ep.iFaces + epMap["ep_iface"] = ep.iface epMap["exposed_ports"] = ep.exposedPorts epMap["generic"] = ep.generic epMap["sandbox"] = ep.sandboxID @@ -86,12 +87,7 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) { ep.id = epMap["id"].(string) ib, _ := json.Marshal(epMap["ep_iface"]) - var ifaces []endpointInterface - json.Unmarshal(ib, &ifaces) - ep.iFaces = make([]*endpointInterface, 0) - for _, iface := range ifaces { - ep.iFaces = append(ep.iFaces, &iface) - } + json.Unmarshal(ib, ep.iface) tb, _ := json.Marshal(epMap["exposed_ports"]) var tPorts []types.TransportPort @@ -289,10 +285,25 @@ func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error { return err } + sb.Lock() + heap.Push(&sb.endpoints, ep) + sb.Unlock() + defer func() { + if err != nil { + for i, e := range sb.getConnectedEndpoints() { + if e == ep { + sb.Lock() + heap.Remove(&sb.endpoints, i) + sb.Unlock() + return + } + } + } + }() + if err = sb.populateNetworkResources(ep); err != nil { return err } - return nil } @@ -300,13 +311,7 @@ func (ep *endpoint) hasInterface(iName string) bool { ep.Lock() defer ep.Unlock() - for _, iface := range ep.iFaces { - if iface.srcName == iName { - return true - } - } - - return false + return ep.iface != nil && ep.iface.srcName == iName } func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error { @@ -463,8 +468,8 @@ func (ep *endpoint) getFirstInterfaceAddress() net.IP { ep.Lock() defer ep.Unlock() - if len(ep.iFaces) != 0 && ep.iFaces[0] != nil { - return ep.iFaces[0].addr.IP + if ep.iface != nil { + return ep.iface.addr.IP } return nil diff --git a/vendor/src/github.com/docker/libnetwork/endpoint_info.go b/vendor/src/github.com/docker/libnetwork/endpoint_info.go index d6b528b533..ffc4787318 100644 --- a/vendor/src/github.com/docker/libnetwork/endpoint_info.go +++ b/vendor/src/github.com/docker/libnetwork/endpoint_info.go @@ -10,9 +10,11 @@ import ( // EndpointInfo provides an interface to retrieve network resources bound to the endpoint. type EndpointInfo interface { - // InterfaceList returns an interface list which were assigned to the endpoint - // by the driver. This can be used after the endpoint has been created. - InterfaceList() []InterfaceInfo + // Iface returns InterfaceInfo, go interface that can be used + // to get more information on the interface which was assigned to + // the endpoint by the driver. This can be used after the + // endpoint has been created. + Iface() InterfaceInfo // Gateway returns the IPv4 gateway assigned by the driver. // This will only return a valid value if a container has joined the endpoint. @@ -39,7 +41,6 @@ type InterfaceInfo interface { } type endpointInterface struct { - id int mac net.HardwareAddr addr net.IPNet addrv6 net.IPNet @@ -50,7 +51,6 @@ type endpointInterface struct { func (epi *endpointInterface) MarshalJSON() ([]byte, error) { epMap := make(map[string]interface{}) - epMap["id"] = epi.id epMap["mac"] = epi.mac.String() epMap["addr"] = epi.addr.String() epMap["addrv6"] = epi.addrv6.String() @@ -69,7 +69,6 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) (err error) { if err := json.Unmarshal(b, &epMap); err != nil { return err } - epi.id = int(epMap["id"].(float64)) mac, _ := net.ParseMAC(epMap["mac"].(string)) epi.mac = mac @@ -128,51 +127,42 @@ func (ep *endpoint) DriverInfo() (map[string]interface{}, error) { return driver.EndpointOperInfo(nid, epid) } -func (ep *endpoint) InterfaceList() []InterfaceInfo { +func (ep *endpoint) Iface() InterfaceInfo { ep.Lock() defer ep.Unlock() - iList := make([]InterfaceInfo, len(ep.iFaces)) - - for i, iface := range ep.iFaces { - iList[i] = iface + if ep.iface != nil { + return ep.iface } - return iList + return nil } -func (ep *endpoint) Interfaces() []driverapi.InterfaceInfo { +func (ep *endpoint) Interface() driverapi.InterfaceInfo { ep.Lock() defer ep.Unlock() - iList := make([]driverapi.InterfaceInfo, len(ep.iFaces)) - - for i, iface := range ep.iFaces { - iList[i] = iface + if ep.iface != nil { + return ep.iface } - return iList + return nil } -func (ep *endpoint) AddInterface(id int, mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error { +func (ep *endpoint) AddInterface(mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error { ep.Lock() defer ep.Unlock() iface := &endpointInterface{ - id: id, addr: *types.GetIPNetCopy(&ipv4), addrv6: *types.GetIPNetCopy(&ipv6), } iface.mac = types.GetMacCopy(mac) - ep.iFaces = append(ep.iFaces, iface) + ep.iface = iface return nil } -func (epi *endpointInterface) ID() int { - return epi.id -} - func (epi *endpointInterface) MacAddress() net.HardwareAddr { return types.GetMacCopy(epi.mac) } @@ -191,24 +181,22 @@ func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error { return nil } -func (ep *endpoint) InterfaceNames() []driverapi.InterfaceNameInfo { +func (ep *endpoint) InterfaceName() driverapi.InterfaceNameInfo { ep.Lock() defer ep.Unlock() - iList := make([]driverapi.InterfaceNameInfo, len(ep.iFaces)) - - for i, iface := range ep.iFaces { - iList[i] = iface + if ep.iface != nil { + return ep.iface } - return iList + return nil } -func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP, interfaceID int) error { +func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error { ep.Lock() defer ep.Unlock() - r := types.StaticRoute{Destination: destination, RouteType: routeType, NextHop: nextHop, InterfaceID: interfaceID} + r := types.StaticRoute{Destination: destination, RouteType: routeType, NextHop: nextHop} if routeType == types.NEXTHOP { // If the route specifies a next-hop, then it's loosely routed (i.e. not bound to a particular interface). @@ -223,14 +211,12 @@ func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHo } func (ep *endpoint) addInterfaceRoute(route *types.StaticRoute) error { - for _, iface := range ep.iFaces { - if iface.id == route.InterfaceID { - iface.routes = append(iface.routes, route.Destination) - return nil - } - } - return types.BadRequestErrorf("Interface with ID %d doesn't exist.", - route.InterfaceID) + ep.Lock() + defer ep.Unlock() + + iface := ep.iface + iface.routes = append(iface.routes, route.Destination) + return nil } func (ep *endpoint) Sandbox() Sandbox { diff --git a/vendor/src/github.com/docker/libnetwork/network.go b/vendor/src/github.com/docker/libnetwork/network.go index ab95292cea..e667e2f46d 100644 --- a/vendor/src/github.com/docker/libnetwork/network.go +++ b/vendor/src/github.com/docker/libnetwork/network.go @@ -305,7 +305,6 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi } ep := &endpoint{name: name, - iFaces: []*endpointInterface{}, generic: make(map[string]interface{})} ep.id = stringid.GenerateRandomID() ep.network = n @@ -409,7 +408,7 @@ func (n *network) isGlobalScoped() (bool, error) { func (n *network) updateSvcRecord(ep *endpoint, isAdd bool) { n.Lock() var recs []etchosts.Record - for _, iface := range ep.InterfaceList() { + if iface := ep.Iface(); iface != nil { if isAdd { n.svcRecords[ep.Name()] = iface.Address().IP n.svcRecords[ep.Name()+"."+n.name] = iface.Address().IP diff --git a/vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go b/vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go index fe4f79e4ac..9b2c82eda6 100644 --- a/vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go +++ b/vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go @@ -157,30 +157,43 @@ func (n *networkNamespace) NeighborOptions() NeighborOptionSetter { return n } +func mountNetworkNamespace(basePath string, lnPath string) error { + if err := syscall.Mount(basePath, lnPath, "bind", syscall.MS_BIND, ""); err != nil { + return err + } + + if err := loopbackUp(); err != nil { + return err + } + return nil +} + +// GetSandboxForExternalKey returns sandbox object for the supplied path +func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) { + var err error + if err = createNamespaceFile(key); err != nil { + return nil, err + } + n := &networkNamespace{path: basePath} + n.InvokeFunc(func() { + err = mountNetworkNamespace(basePath, key) + }) + if err != nil { + return nil, err + } + return &networkNamespace{path: key}, nil +} + func reexecCreateNamespace() { if len(os.Args) < 2 { log.Fatal("no namespace path provided") } - - if err := syscall.Mount("/proc/self/ns/net", os.Args[1], "bind", syscall.MS_BIND, ""); err != nil { - log.Fatal(err) - } - - if err := loopbackUp(); err != nil { + if err := mountNetworkNamespace("/proc/self/ns/net", os.Args[1]); err != nil { log.Fatal(err) } } func createNetworkNamespace(path string, osCreate bool) error { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - origns, err := netns.Get() - if err != nil { - return err - } - defer origns.Close() - if err := createNamespaceFile(path); err != nil { return err } diff --git a/vendor/src/github.com/docker/libnetwork/osl/namespace_unsupported.go b/vendor/src/github.com/docker/libnetwork/osl/namespace_unsupported.go index 77f286e5ea..dbd8d9d35d 100644 --- a/vendor/src/github.com/docker/libnetwork/osl/namespace_unsupported.go +++ b/vendor/src/github.com/docker/libnetwork/osl/namespace_unsupported.go @@ -6,3 +6,7 @@ package osl // and waits for it. func GC() { } + +func GetSandboxForExternalKey(path string, key string) (Sandbox, error) { + return nil, nil +} diff --git a/vendor/src/github.com/docker/libnetwork/osl/namespace_windows.go b/vendor/src/github.com/docker/libnetwork/osl/namespace_windows.go index 36bd6c8002..912d4a2e9f 100644 --- a/vendor/src/github.com/docker/libnetwork/osl/namespace_windows.go +++ b/vendor/src/github.com/docker/libnetwork/osl/namespace_windows.go @@ -19,6 +19,10 @@ func NewSandbox(key string, osCreate bool) (Sandbox, error) { return nil, nil } +func GetSandboxForExternalKey(path string, key string) (Sandbox, error) { + return nil, nil +} + // GC triggers garbage collection of namespace path right away // and waits for it. func GC() { diff --git a/vendor/src/github.com/docker/libnetwork/sandbox.go b/vendor/src/github.com/docker/libnetwork/sandbox.go index 8972abc4d5..bd473947aa 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox.go @@ -32,6 +32,8 @@ type Sandbox interface { // Refresh leaves all the endpoints, resets and re-apply the options, // re-joins all the endpoints without destroying the osl sandbox Refresh(options ...SandboxOption) error + // SetKey updates the Sandbox Key + SetKey(key string) error // Delete destroys this container after detaching it from all connected endpoints. Delete() error } @@ -102,6 +104,7 @@ type containerConfig struct { resolvConfPathConfig generic map[string]interface{} useDefaultSandBox bool + useExternalKey bool prio int // higher the value, more the priority } @@ -241,8 +244,14 @@ func (sb *sandbox) getConnectedEndpoints() []*endpoint { } func (sb *sandbox) updateGateway(ep *endpoint) error { - sb.osSbox.UnsetGateway() - sb.osSbox.UnsetGatewayIPv6() + sb.Lock() + osSbox := sb.osSbox + sb.Unlock() + if osSbox == nil { + return nil + } + osSbox.UnsetGateway() + osSbox.UnsetGatewayIPv6() if ep == nil { return nil @@ -252,24 +261,66 @@ func (sb *sandbox) updateGateway(ep *endpoint) error { joinInfo := ep.joinInfo ep.Unlock() - if err := sb.osSbox.SetGateway(joinInfo.gw); err != nil { + if err := osSbox.SetGateway(joinInfo.gw); err != nil { return fmt.Errorf("failed to set gateway while updating gateway: %v", err) } - if err := sb.osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil { + if err := osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil { return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err) } return nil } +func (sb *sandbox) SetKey(basePath string) error { + var err error + if basePath == "" { + return types.BadRequestErrorf("invalid sandbox key") + } + + sb.Lock() + if sb.osSbox != nil { + sb.Unlock() + return types.ForbiddenErrorf("failed to set sandbox key : already assigned") + } + sb.Unlock() + osSbox, err := osl.GetSandboxForExternalKey(basePath, sb.Key()) + if err != nil { + return err + } + sb.Lock() + sb.osSbox = osSbox + sb.Unlock() + defer func() { + if err != nil { + sb.Lock() + sb.osSbox = nil + sb.Unlock() + } + }() + + for _, ep := range sb.getConnectedEndpoints() { + if err = sb.populateNetworkResources(ep); err != nil { + return err + } + } + return nil +} + func (sb *sandbox) populateNetworkResources(ep *endpoint) error { + sb.Lock() + if sb.osSbox == nil { + sb.Unlock() + return nil + } + sb.Unlock() + ep.Lock() joinInfo := ep.joinInfo - ifaces := ep.iFaces + i := ep.iface ep.Unlock() - for _, i := range ifaces { + if i != nil { var ifaceOptions []osl.IfaceOption ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(&i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes)) @@ -292,7 +343,6 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error { } sb.Lock() - heap.Push(&sb.endpoints, ep) highEp := sb.endpoints[0] sb.Unlock() if ep == highEp { @@ -305,24 +355,28 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error { } func (sb *sandbox) clearNetworkResources(ep *endpoint) error { - - for _, i := range sb.osSbox.Info().Interfaces() { - // Only remove the interfaces owned by this endpoint from the sandbox. - if ep.hasInterface(i.SrcName()) { - if err := i.Remove(); err != nil { - log.Debugf("Remove interface failed: %v", err) + sb.Lock() + osSbox := sb.osSbox + sb.Unlock() + if osSbox != nil { + for _, i := range osSbox.Info().Interfaces() { + // Only remove the interfaces owned by this endpoint from the sandbox. + if ep.hasInterface(i.SrcName()) { + if err := i.Remove(); err != nil { + log.Debugf("Remove interface failed: %v", err) + } } } - } - ep.Lock() - joinInfo := ep.joinInfo - ep.Unlock() + ep.Lock() + joinInfo := ep.joinInfo + ep.Unlock() - // Remove non-interface routes. - for _, r := range joinInfo.StaticRoutes { - if err := sb.osSbox.RemoveStaticRoute(r); err != nil { - log.Debugf("Remove route failed: %v", err) + // Remove non-interface routes. + for _, r := range joinInfo.StaticRoutes { + if err := osSbox.RemoveStaticRoute(r); err != nil { + log.Debugf("Remove route failed: %v", err) + } } } @@ -670,6 +724,14 @@ func OptionUseDefaultSandbox() SandboxOption { } } +// OptionUseExternalKey function returns an option setter for using provided namespace +// instead of creating one. +func OptionUseExternalKey() SandboxOption { + return func(sb *sandbox) { + sb.config.useExternalKey = true + } +} + // OptionGeneric function returns an option setter for Generic configuration // that is not managed by libNetwork but can be used by the Drivers during the call to // net container creation method. Container Labels are a good example. diff --git a/vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go b/vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go new file mode 100644 index 0000000000..fe863495ab --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go @@ -0,0 +1,185 @@ +package libnetwork + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net" + "os" + + "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/reexec" + "github.com/docker/libnetwork/types" + "github.com/opencontainers/runc/libcontainer" + "github.com/opencontainers/runc/libcontainer/configs" +) + +type setKeyData struct { + ContainerID string + Key string +} + +func init() { + reexec.Register("libnetwork-setkey", processSetKeyReexec) +} + +const udsBase = "/var/lib/docker/network/files/" +const success = "success" + +// processSetKeyReexec is a private function that must be called only on an reexec path +// It expects 3 args { [0] = "libnetwork-setkey", [1] = , [2] = } +// It also expects libcontainer.State as a json string in +// Refer to https://github.com/opencontainers/runc/pull/160/ for more information +func processSetKeyReexec() { + var err error + + // Return a failure to the calling process via ExitCode + defer func() { + if err != nil { + logrus.Fatalf("%v", err) + } + }() + + // expecting 3 args {[0]="libnetwork-setkey", [1]=, [2]= } + if len(os.Args) < 3 { + err = fmt.Errorf("Re-exec expects 3 args, received : %d", len(os.Args)) + return + } + containerID := os.Args[1] + + // We expect libcontainer.State as a json string in + stateBuf, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return + } + var state libcontainer.State + if err = json.Unmarshal(stateBuf, &state); err != nil { + return + } + + controllerID := os.Args[2] + key := state.NamespacePaths[configs.NamespaceType("NEWNET")] + + err = SetExternalKey(controllerID, containerID, key) + return +} + +// SetExternalKey provides a convenient way to set an External key to a sandbox +func SetExternalKey(controllerID string, containerID string, key string) error { + keyData := setKeyData{ + ContainerID: containerID, + Key: key} + + c, err := net.Dial("unix", udsBase+controllerID+".sock") + if err != nil { + return err + } + defer c.Close() + + if err = sendKey(c, keyData); err != nil { + return fmt.Errorf("sendKey failed with : %v", err) + } + return processReturn(c) +} + +func sendKey(c net.Conn, data setKeyData) error { + var err error + defer func() { + if err != nil { + c.Close() + } + }() + + var b []byte + if b, err = json.Marshal(data); err != nil { + return err + } + + _, err = c.Write(b) + return err +} + +func processReturn(r io.Reader) error { + buf := make([]byte, 1024) + n, err := r.Read(buf[:]) + if err != nil { + return fmt.Errorf("failed to read buf in processReturn : %v", err) + } + if string(buf[0:n]) != success { + return fmt.Errorf(string(buf[0:n])) + } + return nil +} + +func (c *controller) startExternalKeyListener() error { + if err := os.MkdirAll(udsBase, 0600); err != nil { + return err + } + uds := udsBase + c.id + ".sock" + l, err := net.Listen("unix", uds) + if err != nil { + return err + } + if err := os.Chmod(uds, 0600); err != nil { + l.Close() + return err + } + c.Lock() + c.extKeyListener = l + c.Unlock() + + go c.acceptClientConnections(uds, l) + return nil +} + +func (c *controller) acceptClientConnections(sock string, l net.Listener) { + for { + conn, err := l.Accept() + if err != nil { + if _, err1 := os.Stat(sock); os.IsNotExist(err1) { + logrus.Warnf("Unix socket %s doesnt exist. cannot accept client connections", sock) + return + } + logrus.Errorf("Error accepting connection %v", err) + continue + } + go func() { + err := c.processExternalKey(conn) + ret := success + if err != nil { + ret = err.Error() + } + + _, err = conn.Write([]byte(ret)) + if err != nil { + logrus.Errorf("Error returning to the client %v", err) + } + }() + } +} + +func (c *controller) processExternalKey(conn net.Conn) error { + buf := make([]byte, 1280) + nr, err := conn.Read(buf) + if err != nil { + return err + } + var s setKeyData + if err = json.Unmarshal(buf[0:nr], &s); err != nil { + return err + } + + var sandbox Sandbox + search := SandboxContainerWalker(&sandbox, s.ContainerID) + c.WalkSandboxes(search) + if sandbox == nil { + return types.BadRequestErrorf("no sandbox present for %s", s.ContainerID) + } + + return sandbox.SetKey(s.Key) +} + +func (c *controller) stopExternalKeyListener() { + c.extKeyListener.Close() +} diff --git a/vendor/src/github.com/docker/libnetwork/types/types.go b/vendor/src/github.com/docker/libnetwork/types/types.go index 176f40d0f1..9df1af50b1 100644 --- a/vendor/src/github.com/docker/libnetwork/types/types.go +++ b/vendor/src/github.com/docker/libnetwork/types/types.go @@ -266,12 +266,6 @@ type StaticRoute struct { // NextHop will be resolved by the kernel (i.e. as a loose hop). NextHop net.IP - - // InterfaceID must refer to a defined interface on the - // Endpoint to which the routes are specified. Routes specified this way - // are interpreted as directly connected to the specified interface (no - // next hop will be used). - InterfaceID int } // GetCopy returns a copy of this StaticRoute structure @@ -279,9 +273,9 @@ func (r *StaticRoute) GetCopy() *StaticRoute { d := GetIPNetCopy(r.Destination) nh := GetIPCopy(r.NextHop) return &StaticRoute{Destination: d, - RouteType: r.RouteType, - NextHop: nh, - InterfaceID: r.InterfaceID} + RouteType: r.RouteType, + NextHop: nh, + } } /******************************