diff --git a/api/server/server_experimental_unix.go b/api/server/server_experimental_unix.go index 20b3292cc6..b02e849a7f 100644 --- a/api/server/server_experimental_unix.go +++ b/api/server/server_experimental_unix.go @@ -14,4 +14,9 @@ func (s *Server) registerSubRouter() { subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) subrouter = s.router.PathPrefix("/services").Subrouter() subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) + + subrouter = s.router.PathPrefix("/v{version:[0-9.]+}/sandboxes").Subrouter() + subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) + subrouter = s.router.PathPrefix("/sandboxes").Subrouter() + subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) } diff --git a/hack/vendor.sh b/hack/vendor.sh index a06e1d9396..51ff8ca32f 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 dc52820147f40fe424c8959987af3b396f842639 +clone git github.com/docker/libnetwork 3e31cead05cba8ec20241630d051e6d73765b3a2 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/bitseq/sequence.go b/vendor/src/github.com/docker/libnetwork/bitseq/sequence.go index d71d76b3ec..68acc44afb 100644 --- a/vendor/src/github.com/docker/libnetwork/bitseq/sequence.go +++ b/vendor/src/github.com/docker/libnetwork/bitseq/sequence.go @@ -252,9 +252,8 @@ func (h *Handle) set(ordinal uint32, any bool, release bool) (uint32, error) { return ret, err } - // Create a private copy of h and work on it, also copy the current db index + // Create a private copy of h and work on it nh := h.getCopy() - ci := h.dbIndex h.Unlock() nh.head = pushReservation(bytePos, bitPos, nh.head, release) @@ -273,12 +272,9 @@ func (h *Handle) set(ordinal uint32, any bool, release bool) (uint32, error) { continue } - // Unless unexpected error, save private copy to local copy + // Previous atomic push was succesfull. Save private copy to local copy h.Lock() defer h.Unlock() - if h.dbIndex != ci { - return ret, fmt.Errorf("unexected database index change") - } h.unselected = nh.unselected h.head = nh.head h.dbExists = nh.dbExists diff --git a/vendor/src/github.com/docker/libnetwork/client/service.go b/vendor/src/github.com/docker/libnetwork/client/service.go index b2f4101629..6b8fa15c7b 100644 --- a/vendor/src/github.com/docker/libnetwork/client/service.go +++ b/vendor/src/github.com/docker/libnetwork/client/service.go @@ -268,14 +268,12 @@ func getBackendID(cli *NetworkCli, servID string) (string, error) { ) if obj, _, err = readBody(cli.call("GET", "/services/"+servID+"/backend", nil, nil)); err == nil { - var bkl []sandboxResource - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&bkl); err == nil { - if len(bkl) > 0 { - bk = bkl[0].ID - } + var sr sandboxResource + if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&sr); err == nil { + bk = sr.ContainerID } else { // Only print a message, don't make the caller cli fail for this - fmt.Fprintf(cli.out, "Failed to retrieve backend list for service %s (%v)", servID, err) + fmt.Fprintf(cli.out, "Failed to retrieve backend list for service %s (%v)\n", servID, err) } } 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 2d3f55ed4d..10a72d684c 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -98,6 +98,7 @@ type bridgeNetwork struct { type driver struct { config *configuration + configured bool network *bridgeNetwork natChain *iptables.ChainInfo filterChain *iptables.ChainInfo @@ -105,13 +106,10 @@ type driver struct { sync.Mutex } -func init() { - ipAllocator = ipallocator.New() -} - // New constructs a new bridge driver func newDriver() driverapi.Driver { - return &driver{networks: map[string]*bridgeNetwork{}} + ipAllocator = ipallocator.New() + return &driver{networks: map[string]*bridgeNetwork{}, config: &configuration{}} } // Init registers a new instance of bridge driver @@ -436,29 +434,26 @@ func (d *driver) Config(option map[string]interface{}) error { d.Lock() defer d.Unlock() - if d.config != nil { + if d.configured { return &ErrConfigExists{} } genericData, ok := option[netlabel.GenericData] - if ok && genericData != nil { - switch opt := genericData.(type) { - case options.Generic: - opaqueConfig, err := options.GenerateFromModel(opt, &configuration{}) - if err != nil { - return err - } - config = opaqueConfig.(*configuration) - case *configuration: - config = opt - default: - return &ErrInvalidDriverConfig{} - } + if !ok || genericData == nil { + return nil + } - d.config = config - } else { - config = &configuration{} - d.config = config + switch opt := genericData.(type) { + case options.Generic: + opaqueConfig, err := options.GenerateFromModel(opt, &configuration{}) + if err != nil { + return err + } + config = opaqueConfig.(*configuration) + case *configuration: + config = opt + default: + return &ErrInvalidDriverConfig{} } if config.EnableIPForwarding { @@ -470,9 +465,13 @@ func (d *driver) Config(option map[string]interface{}) error { if config.EnableIPTables { d.natChain, d.filterChain, err = setupIPChains(config) - return err + if err != nil { + return err + } } + d.configured = true + d.config = config return nil } @@ -569,12 +568,20 @@ func (d *driver) getNetworks() []*bridgeNetwork { // Create a new network using bridge plugin func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { - var err error + var ( + err error + configLocked bool + ) defer osl.InitOSContext()() // Sanity checks d.Lock() + if !d.configured { + configLocked = true + d.configured = true + } + if _, ok := d.networks[id]; ok { d.Unlock() return types.ForbiddenErrorf("network %s exists", id) @@ -613,6 +620,10 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { defer func() { if err != nil { d.Lock() + if configLocked { + d.configured = false + } + delete(d.networks, id) d.Unlock() } @@ -654,7 +665,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error { bridgeSetup.queueStep(setupBridgeIPv4) enableIPv6Forwarding := false - if d.config != nil && d.config.EnableIPForwarding && config.FixedCIDRv6 != nil { + if d.config.EnableIPForwarding && config.FixedCIDRv6 != nil { enableIPv6Forwarding = true } @@ -791,6 +802,18 @@ func (d *driver) DeleteNetwork(nid string) error { // Programming err = netlink.LinkDel(n.bridge.Link) + // Release ip addresses (ignore errors) + if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) { + if e := ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, n.bridge.gatewayIPv4); e != nil { + logrus.Warnf("Failed to release default gateway address %s: %v", n.bridge.gatewayIPv4.String(), e) + } + } + if config.FixedCIDR == nil || config.FixedCIDR.Contains(n.bridge.bridgeIPv4.IP) { + if e := ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, n.bridge.bridgeIPv4.IP); e != nil { + logrus.Warnf("Failed to release bridge IP %s: %v", n.bridge.bridgeIPv4.IP.String(), e) + } + } + return err } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go index c72e71e9a6..85073932c4 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go @@ -62,7 +62,7 @@ func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error { return err } - log.Debugf("Creating bridge interface %q with network %s", config.BridgeName, bridgeIPv4) + log.Debugf("Creating bridge interface %s with network %s", config.BridgeName, bridgeIPv4) if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: bridgeIPv4}); err != nil { return &IPv4AddrAddError{IP: bridgeIPv4, Err: err} } @@ -79,7 +79,9 @@ func allocateBridgeIP(config *networkConfiguration, i *bridgeInterface) error { // reserve bridge address only if it belongs to the container network // (if defined), no need otherwise if config.FixedCIDR == nil || config.FixedCIDR.Contains(i.bridgeIPv4.IP) { - ipAllocator.RequestIP(i.bridgeIPv4, i.bridgeIPv4.IP) + if _, err := ipAllocator.RequestIP(i.bridgeIPv4, i.bridgeIPv4.IP); err != nil { + return fmt.Errorf("failed to reserve bridge IP %s: %v", i.bridgeIPv4.IP.String(), err) + } } return nil } @@ -120,7 +122,7 @@ func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error { // (if defined), no need otherwise if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) { if _, err := ipAllocator.RequestIP(i.bridgeIPv4, config.DefaultGatewayIPv4); err != nil { - return err + return fmt.Errorf("failed to reserve default gateway %s: %v", config.DefaultGatewayIPv4.String(), err) } } 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 0d428b2b04..39e4634227 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/overlay/joinleave.go @@ -35,15 +35,31 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return err } + // Set the container interface and its peer MTU to 1450 to allow + // for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) + + // outer UDP(8) + vxlan header(8)) + veth, err := netlink.LinkByName(name1) + if err != nil { + return fmt.Errorf("cound not find link by name %s: %v", name1, err) + } + err = netlink.LinkSetMTU(veth, vxlanVethMTU) + if err != nil { + return err + } + if err := sbox.AddInterface(name1, "veth", sbox.InterfaceOptions().Master("bridge1")); err != nil { return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err) } - veth, err := netlink.LinkByName(name2) + veth, err = netlink.LinkByName(name2) if err != nil { return fmt.Errorf("could not find link by name %s: %v", name2, err) } + err = netlink.LinkSetMTU(veth, vxlanVethMTU) + if err != nil { + return err + } if err := netlink.LinkSetHardwareAddr(veth, ep.mac); err != nil { return fmt.Errorf("could not set mac address to the container interface: %v", err) diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go index 9bd63f558f..8f55ad6dca 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go @@ -21,6 +21,7 @@ const ( vxlanIDStart = 256 vxlanIDEnd = 1000 vxlanPort = 4789 + vxlanVethMTU = 1450 ) type driver struct { diff --git a/vendor/src/github.com/docker/libnetwork/netutils/test_utils.go b/vendor/src/github.com/docker/libnetwork/netutils/test_utils.go deleted file mode 100644 index 7ebc16e364..0000000000 --- a/vendor/src/github.com/docker/libnetwork/netutils/test_utils.go +++ /dev/null @@ -1,10 +0,0 @@ -package netutils - -import "flag" - -var runningInContainer = flag.Bool("incontainer", false, "Indicates if the test is running in a container") - -// IsRunningInContainer returns whether the test is running inside a container. -func IsRunningInContainer() bool { - return (*runningInContainer) -} diff --git a/vendor/src/github.com/docker/libnetwork/ns/init_linux.go b/vendor/src/github.com/docker/libnetwork/ns/init_linux.go new file mode 100644 index 0000000000..7595a5da17 --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/ns/init_linux.go @@ -0,0 +1,43 @@ +package ns + +import ( + "fmt" + "os" + "syscall" + + log "github.com/Sirupsen/logrus" + "github.com/vishvananda/netns" +) + +var initNs netns.NsHandle + +// Init initializes a new network namespace +func Init() { + var err error + initNs, err = netns.Get() + if err != nil { + log.Errorf("could not get initial namespace: %v", err) + } +} + +// SetNamespace sets the initial namespace handler +func SetNamespace() error { + if err := netns.Set(initNs); err != nil { + linkInfo, linkErr := getLink() + if linkErr != nil { + linkInfo = linkErr.Error() + } + + return fmt.Errorf("failed to set to initial namespace, %v, initns fd %d: %v", linkInfo, initNs, err) + } + return nil +} + +// ParseHandlerInt transforms the namespace handler into a integer +func ParseHandlerInt() int { + return int(initNs) +} + +func getLink() (string, error) { + return os.Readlink(fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())) +} 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 55e57a1fa2..fe4f79e4ac 100644 --- a/vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go +++ b/vendor/src/github.com/docker/libnetwork/osl/namespace_linux.go @@ -12,6 +12,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/reexec" + "github.com/docker/libnetwork/ns" "github.com/docker/libnetwork/types" "github.com/vishvananda/netlink" "github.com/vishvananda/netns" @@ -27,7 +28,6 @@ var ( gpmCleanupPeriod = 60 * time.Second gpmChan = make(chan chan struct{}) nsOnce sync.Once - initNs netns.NsHandle ) // The networkNamespace type is the linux implementation of the Sandbox @@ -244,30 +244,12 @@ func (n *networkNamespace) InvokeFunc(f func()) error { }) } -func getLink() (string, error) { - return os.Readlink(fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())) -} - -func nsInit() { - var err error - - if initNs, err = netns.Get(); err != nil { - log.Errorf("could not get initial namespace: %v", err) - } -} - // InitOSContext initializes OS context while configuring network resources func InitOSContext() func() { runtime.LockOSThread() - nsOnce.Do(nsInit) - if err := netns.Set(initNs); err != nil { - linkInfo, linkErr := getLink() - if linkErr != nil { - linkInfo = linkErr.Error() - } - - log.Errorf("failed to set to initial namespace, %v, initns fd %d: %v", - linkInfo, initNs, err) + nsOnce.Do(ns.Init) + if err := ns.SetNamespace(); err != nil { + log.Error(err) } return runtime.UnlockOSThread @@ -293,10 +275,10 @@ func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD if err = netns.Set(netns.NsHandle(nsFD)); err != nil { return err } - defer netns.Set(initNs) + defer ns.SetNamespace() // Invoked after the namespace switch. - return postfunc(int(initNs)) + return postfunc(ns.ParseHandlerInt()) } func (n *networkNamespace) nsPath() string {