Explorar o código

- Fixed an assortment of bugs in sandbox
- Added more test coverage to sandbox

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>

Jana Radhakrishnan %!s(int64=10) %!d(string=hai) anos
pai
achega
c6fd92a565

+ 29 - 2
libnetwork/sandbox/configure_linux.go

@@ -3,8 +3,11 @@ package sandbox
 import (
 	"fmt"
 	"net"
+	"os"
+	"runtime"
 
 	"github.com/vishvananda/netlink"
+	"github.com/vishvananda/netns"
 )
 
 func configureInterface(iface netlink.Link, settings *Interface) error {
@@ -26,7 +29,28 @@ func configureInterface(iface netlink.Link, settings *Interface) error {
 	return nil
 }
 
-func setGatewayIP(gw net.IP) error {
+func setGatewayIP(path string, gw net.IP) error {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	origns, err := netns.Get()
+	if err != nil {
+		return err
+	}
+	defer origns.Close()
+
+	f, err := os.OpenFile(path, os.O_RDONLY, 0)
+	if err != nil {
+		return fmt.Errorf("failed get network namespace %q: %v", path, err)
+	}
+	defer f.Close()
+
+	nsFD := f.Fd()
+	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
+		return err
+	}
+	defer netns.Set(origns)
+
 	return netlink.RouteAdd(&netlink.Route{
 		Scope: netlink.SCOPE_UNIVERSE,
 		Gw:    gw,
@@ -39,7 +63,10 @@ func setInterfaceIP(iface netlink.Link, settings *Interface) error {
 }
 
 func setInterfaceIPv6(iface netlink.Link, settings *Interface) error {
-	ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""}
+	if settings.AddressIPv6 == nil {
+		return nil
+	}
+	ipAddr := &netlink.Addr{IPNet: settings.AddressIPv6, Label: ""}
 	return netlink.AddrAdd(iface, ipAddr)
 }
 

+ 17 - 4
libnetwork/sandbox/namespace_linux.go

@@ -50,11 +50,15 @@ func createNetworkNamespace(path string) (Sandbox, error) {
 		return nil, err
 	}
 
-	if err := syscall.Mount("/proc/self/ns/net", path, "bind", syscall.MS_BIND, ""); err != nil {
+	procNet := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())
+
+	if err := syscall.Mount(procNet, path, "bind", syscall.MS_BIND, ""); err != nil {
 		return nil, err
 	}
 
-	return &networkNamespace{path: path}, nil
+	interfaces := []*Interface{}
+	sinfo := &Info{Interfaces: interfaces}
+	return &networkNamespace{path: path, sinfo: sinfo}, nil
 }
 
 func createNamespaceFile(path string) (err error) {
@@ -106,6 +110,11 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
 	}
 	defer netns.Set(origns)
 
+	// Down the interface before configuring
+	if err := netlink.LinkSetDown(iface); err != nil {
+		return err
+	}
+
 	// Configure the interface now this is moved in the proper namespace.
 	if err := configureInterface(iface, i); err != nil {
 		return err
@@ -121,7 +130,7 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
 }
 
 func (n *networkNamespace) SetGateway(gw net.IP) error {
-	err := setGatewayIP(gw)
+	err := setGatewayIP(n.path, gw)
 	if err == nil {
 		n.sinfo.Gateway = gw
 	}
@@ -130,7 +139,11 @@ func (n *networkNamespace) SetGateway(gw net.IP) error {
 }
 
 func (n *networkNamespace) SetGatewayIPv6(gw net.IP) error {
-	err := setGatewayIP(gw)
+	if len(gw) == 0 {
+		return nil
+	}
+
+	err := setGatewayIP(n.path, gw)
 	if err == nil {
 		n.sinfo.GatewayIPv6 = gw
 	}

+ 3 - 0
libnetwork/sandbox/sandbox.go

@@ -28,6 +28,9 @@ type Sandbox interface {
 
 	// Set default IPv6 gateway for the sandbox
 	SetGatewayIPv6(gw net.IP) error
+
+	// Destroy the sandbox
+	Destroy() error
 }
 
 // Info represents all possible information that

+ 50 - 1
libnetwork/sandbox/sandbox_linux_test.go

@@ -1,15 +1,23 @@
 package sandbox
 
 import (
+	"net"
 	"os"
 	"path/filepath"
 	"runtime"
 	"testing"
 
 	"github.com/docker/libnetwork/netutils"
+	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netns"
 )
 
+const (
+	vethName1     = "wierdlongname1"
+	vethName2     = "wierdlongname2"
+	sboxIfaceName = "containername"
+)
+
 func newKey(t *testing.T) (string, error) {
 	name, err := netutils.GenerateRandomName("netns", 12)
 	if err != nil {
@@ -24,6 +32,42 @@ func newKey(t *testing.T) (string, error) {
 	return name, nil
 }
 
+func newInfo(t *testing.T) (*Info, error) {
+	veth := &netlink.Veth{
+		LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0},
+		PeerName:  vethName2}
+	err := netlink.LinkAdd(veth)
+	if err != nil {
+		return nil, err
+	}
+
+	// Store the sandbox side pipe interface
+	// This is needed for cleanup on DeleteEndpoint()
+	intf := &Interface{}
+	intf.SrcName = vethName2
+	intf.DstName = sboxIfaceName
+
+	ip4, addr, err := net.ParseCIDR("192.168.1.100/24")
+	if err != nil {
+		return nil, err
+	}
+	intf.Address = addr
+	intf.Address.IP = ip4
+
+	ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
+	if err != nil {
+		return nil, err
+	}
+	intf.AddressIPv6 = addrv6
+	intf.AddressIPv6.IP = ip6
+
+	sinfo := &Info{Interfaces: []*Interface{intf}}
+	sinfo.Gateway = net.ParseIP("192.168.1.1")
+	sinfo.GatewayIPv6 = net.ParseIP("2001:DB8::1")
+
+	return sinfo, nil
+}
+
 func verifySandbox(t *testing.T, s Sandbox) {
 	_, ok := s.(*networkNamespace)
 	if !ok {
@@ -49,6 +93,11 @@ func verifySandbox(t *testing.T, s Sandbox) {
 	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
 		t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", s.Key(), err)
 	}
+	defer netns.Set(origns)
 
-	netns.Set(origns)
+	_, err = netlink.LinkByName(sboxIfaceName)
+	if err != nil {
+		t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName,
+			err)
+	}
 }

+ 23 - 0
libnetwork/sandbox/sandbox_test.go

@@ -20,7 +20,30 @@ func TestSandboxCreate(t *testing.T) {
 		t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key)
 	}
 
+	info, err := newInfo(t)
+	if err != nil {
+		t.Fatalf("Failed to generate new sandbox info: %v", err)
+	}
+
+	for _, i := range info.Interfaces {
+		err = s.AddInterface(i)
+		if err != nil {
+			t.Fatalf("Failed to add interfaces to sandbox: %v", err)
+		}
+	}
+
+	err = s.SetGateway(info.Gateway)
+	if err != nil {
+		t.Fatalf("Failed to set gateway to sandbox: %v", err)
+	}
+
+	err = s.SetGatewayIPv6(info.GatewayIPv6)
+	if err != nil {
+		t.Fatalf("Failed to set ipv6 gateway to sandbox: %v", err)
+	}
+
 	verifySandbox(t, s)
+	s.Destroy()
 }
 
 func TestInterfaceEqual(t *testing.T) {