mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
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 <madhu@docker.com>
This commit is contained in:
parent
d25dada639
commit
d0e0c13b60
25 changed files with 490 additions and 246 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*.so
|
||||
|
||||
# Folders
|
||||
integration-tmp/
|
||||
_obj
|
||||
_test
|
||||
|
||||
|
|
25
vendor/src/github.com/docker/libnetwork/Makefile
vendored
25
vendor/src/github.com/docker/libnetwork/Makefile
vendored
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -6,3 +6,7 @@ package osl
|
|||
// and waits for it.
|
||||
func GC() {
|
||||
}
|
||||
|
||||
func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
104
vendor/src/github.com/docker/libnetwork/sandbox.go
vendored
104
vendor/src/github.com/docker/libnetwork/sandbox.go
vendored
|
@ -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.
|
||||
|
|
185
vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go
vendored
Normal file
185
vendor/src/github.com/docker/libnetwork/sandbox_externalkey.go
vendored
Normal file
|
@ -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] = <container-id>, [2] = <controller-id> }
|
||||
// It also expects libcontainer.State as a json string in <stdin>
|
||||
// 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]=<container-id>, [2]=<controller-id> }
|
||||
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 <stdin>
|
||||
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()
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
/******************************
|
||||
|
|
Loading…
Reference in a new issue