
Right now the namespace paths are cleaned up every garbage collection period. But if the daemon is restarted before all the namespace paths of removed containers are garbage collected they will remain there forever. The fix is to provide a GC() api so that garbage collection can be triggered immediately. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
168 lines
3.8 KiB
Go
168 lines
3.8 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/docker/libnetwork/netutils"
|
|
"github.com/vishvananda/netlink"
|
|
"github.com/vishvananda/netns"
|
|
)
|
|
|
|
const (
|
|
vethName1 = "wierdlongname1"
|
|
vethName2 = "wierdlongname2"
|
|
vethName3 = "wierdlongname3"
|
|
vethName4 = "wierdlongname4"
|
|
sboxIfaceName = "containername"
|
|
)
|
|
|
|
func newKey(t *testing.T) (string, error) {
|
|
name, err := netutils.GenerateRandomName("netns", 12)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
name = filepath.Join("/tmp", name)
|
|
if _, err := os.Create(name); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Set the rpmCleanupPeriod to be low to make the test run quicker
|
|
gpmLock.Lock()
|
|
gpmCleanupPeriod = 2 * time.Second
|
|
gpmLock.Unlock()
|
|
|
|
return name, nil
|
|
}
|
|
|
|
func newInfo(t *testing.T) (*Info, error) {
|
|
veth := &netlink.Veth{
|
|
LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0},
|
|
PeerName: vethName2}
|
|
if err := netlink.LinkAdd(veth); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store the sandbox side pipe interface
|
|
// This is needed for cleanup on DeleteEndpoint()
|
|
intf1 := &Interface{}
|
|
intf1.SrcName = vethName2
|
|
intf1.DstName = sboxIfaceName
|
|
|
|
ip4, addr, err := net.ParseCIDR("192.168.1.100/24")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf1.Address = addr
|
|
intf1.Address.IP = ip4
|
|
|
|
// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
|
|
ip6, addrv6, err := net.ParseCIDR("fe80::2/64")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf1.AddressIPv6 = addrv6
|
|
intf1.AddressIPv6.IP = ip6
|
|
|
|
_, route, err := net.ParseCIDR("192.168.2.1/32")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
intf1.Routes = []*net.IPNet{route}
|
|
|
|
veth = &netlink.Veth{
|
|
LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0},
|
|
PeerName: vethName4}
|
|
|
|
if err := netlink.LinkAdd(veth); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
intf2 := &Interface{}
|
|
intf2.SrcName = vethName4
|
|
intf2.DstName = sboxIfaceName
|
|
|
|
ip4, addr, err = net.ParseCIDR("192.168.2.100/24")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf2.Address = addr
|
|
intf2.Address.IP = ip4
|
|
|
|
// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
|
|
ip6, addrv6, err = net.ParseCIDR("fe80::3/64")
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
intf2.AddressIPv6 = addrv6
|
|
intf2.AddressIPv6.IP = ip6
|
|
|
|
sinfo := &Info{Interfaces: []*Interface{intf1, intf2}}
|
|
|
|
sinfo.Gateway = net.ParseIP("192.168.1.1")
|
|
// sinfo.GatewayIPv6 = net.ParseIP("2001:DB8::1")
|
|
sinfo.GatewayIPv6 = net.ParseIP("fe80::1")
|
|
|
|
return sinfo, nil
|
|
}
|
|
|
|
func verifySandbox(t *testing.T, s Sandbox) {
|
|
_, ok := s.(*networkNamespace)
|
|
if !ok {
|
|
t.Fatalf("The sandox interface returned is not of type networkNamespace")
|
|
}
|
|
|
|
origns, err := netns.Get()
|
|
if err != nil {
|
|
t.Fatalf("Could not get the current netns: %v", err)
|
|
}
|
|
defer origns.Close()
|
|
|
|
f, err := os.OpenFile(s.Key(), os.O_RDONLY, 0)
|
|
if err != nil {
|
|
t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err)
|
|
}
|
|
defer f.Close()
|
|
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
nsFD := f.Fd()
|
|
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)
|
|
|
|
_, err = netlink.LinkByName(sboxIfaceName + "0")
|
|
if err != nil {
|
|
t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+"0",
|
|
err)
|
|
}
|
|
|
|
_, err = netlink.LinkByName(sboxIfaceName + "1")
|
|
if err != nil {
|
|
t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+"1",
|
|
err)
|
|
}
|
|
}
|
|
|
|
func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
|
|
if wait {
|
|
time.Sleep(time.Duration(gpmCleanupPeriod * 2))
|
|
}
|
|
|
|
if _, err := os.Stat(s.Key()); err == nil {
|
|
if wait {
|
|
t.Fatalf("The sandbox path %s is not getting cleaned up even after twice the cleanup period", s.Key())
|
|
} else {
|
|
t.Fatalf("The sandbox path %s is not cleaned up after running gc", s.Key())
|
|
}
|
|
}
|
|
}
|