1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #13784 from mrjana/cnm_integ

libnetwork: Add garbage collection trigger
This commit is contained in:
Michael Crosby 2015-06-09 17:24:30 -07:00
commit 4750e1f77e
15 changed files with 132 additions and 14 deletions

View file

@ -1001,6 +1001,11 @@ func (daemon *Daemon) Shutdown() error {
} }
} }
group.Wait() group.Wait()
// trigger libnetwork GC only if it's initialized
if daemon.netController != nil {
daemon.netController.GC()
}
} }
return nil return nil

View file

@ -55,8 +55,8 @@ clone hg code.google.com/p/go.net 84a4013f96e0
clone hg code.google.com/p/gosqlite 74691fb6f837 clone hg code.google.com/p/gosqlite 74691fb6f837
#get libnetwork packages #get libnetwork packages
clone git github.com/docker/libnetwork f72ad20491e8c46d9664da3f32a0eddb301e7c8d clone git github.com/docker/libnetwork ace6b576239cd671d1645d82520b16791737f60d
clone git github.com/vishvananda/netns 008d17ae001344769b031375bdb38a86219154c6 clone git github.com/vishvananda/netns 5478c060110032f972e86a1f844fdb9a2f008f2c
clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c
# get distribution packages # get distribution packages

View file

@ -1217,6 +1217,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
if out, err := s.d.Cmd("run", "-ti", "-d", "--name", "test", "busybox"); err != nil { if out, err := s.d.Cmd("run", "-ti", "-d", "--name", "test", "busybox"); err != nil {
t.Fatal(out, err) t.Fatal(out, err)
} }
if err := s.d.Restart(); err != nil { if err := s.d.Restart(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1225,3 +1226,41 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
t.Fatal(out, err) t.Fatal(out, err)
} }
} }
func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
if err := s.d.StartWithBusybox(); err != nil {
c.Fatal(err)
}
out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top")
if err != nil {
c.Fatal(out, err)
}
if out, err := s.d.Cmd("stop", "netns"); err != nil {
c.Fatal(out, err)
}
// Construct netns file name from container id
out = strings.TrimSpace(out)
nsFile := out[:12]
// Test if the file still exists
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile))
out = strings.TrimSpace(out)
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
c.Assert(out, check.Equals, "/var/run/docker/netns/"+nsFile, check.Commentf("Output: %s", out))
// Remove the container and restart the daemon
if out, err := s.d.Cmd("rm", "netns"); err != nil {
c.Fatal(out, err)
}
if err := s.d.Restart(); err != nil {
c.Fatal(err)
}
// Test again and see now the netns file does not exist
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile))
out = strings.TrimSpace(out)
c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out))
// c.Assert(out, check.Equals, "", check.Commentf("Output: %s", out))
}

View file

@ -79,7 +79,7 @@
}, },
{ {
"ImportPath": "github.com/vishvananda/netns", "ImportPath": "github.com/vishvananda/netns",
"Rev": "008d17ae001344769b031375bdb38a86219154c6" "Rev": "5478c060110032f972e86a1f844fdb9a2f008f2c"
} }
] ]
} }

View file

@ -76,6 +76,9 @@ type NetworkController interface {
// NetworkByID returns the Network which has the passed id. If not found, the error ErrNoSuchNetwork is returned. // NetworkByID returns the Network which has the passed id. If not found, the error ErrNoSuchNetwork is returned.
NetworkByID(id string) (Network, error) NetworkByID(id string) (Network, error)
// GC triggers immediate garbage collection of resources which are garbage collected.
GC()
} }
// NetworkWalker is a client provided function which will be used to walk the Networks. // NetworkWalker is a client provided function which will be used to walk the Networks.
@ -299,3 +302,7 @@ func (c *controller) loadDriver(networkType string) (driverapi.Driver, error) {
} }
return d, nil return d, nil
} }
func (c *controller) GC() {
sandbox.GC()
}

View file

@ -24,6 +24,7 @@ var (
gpmLock sync.Mutex gpmLock sync.Mutex
gpmWg sync.WaitGroup gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
) )
// The networkNamespace type is the linux implementation of the Sandbox // The networkNamespace type is the linux implementation of the Sandbox
@ -55,7 +56,18 @@ func removeUnusedPaths() {
period := gpmCleanupPeriod period := gpmCleanupPeriod
gpmLock.Unlock() gpmLock.Unlock()
for range time.Tick(period) { ticker := time.NewTicker(period)
for {
var (
gc chan struct{}
gcOk bool
)
select {
case <-ticker.C:
case gc, gcOk = <-gpmChan:
}
gpmLock.Lock() gpmLock.Lock()
pathList := make([]string, 0, len(garbagePathMap)) pathList := make([]string, 0, len(garbagePathMap))
for path := range garbagePathMap { for path := range garbagePathMap {
@ -70,6 +82,9 @@ func removeUnusedPaths() {
} }
gpmWg.Done() gpmWg.Done()
if gcOk {
close(gc)
}
} }
} }
@ -85,6 +100,18 @@ func removeFromGarbagePaths(path string) {
gpmLock.Unlock() gpmLock.Unlock()
} }
// GC triggers garbage collection of namespace path right away
// and waits for it.
func GC() {
waitGC := make(chan struct{})
// Trigger GC now
gpmChan <- waitGC
// wait for gc to complete
<-waitGC
}
// GenerateKey generates a sandbox key based on the passed // GenerateKey generates a sandbox key based on the passed
// container id. // container id.
func GenerateKey(containerID string) string { func GenerateKey(containerID string) string {

View file

@ -144,9 +144,16 @@ func verifySandbox(t *testing.T, s Sandbox) {
} }
} }
func verifyCleanup(t *testing.T, s Sandbox) { func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
time.Sleep(time.Duration(gpmCleanupPeriod * 2)) if wait {
time.Sleep(time.Duration(gpmCleanupPeriod * 2))
}
if _, err := os.Stat(s.Key()); err == nil { if _, err := os.Stat(s.Key()); err == nil {
t.Fatalf("The sandbox path %s is not getting cleanup event after twice the cleanup period", s.Key()) 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())
}
} }
} }

View file

@ -54,7 +54,7 @@ func TestSandboxCreate(t *testing.T) {
verifySandbox(t, s) verifySandbox(t, s)
s.Destroy() s.Destroy()
verifyCleanup(t, s) verifyCleanup(t, s, true)
} }
func TestSandboxCreateTwice(t *testing.T) { func TestSandboxCreateTwice(t *testing.T) {
@ -77,6 +77,23 @@ func TestSandboxCreateTwice(t *testing.T) {
s.Destroy() s.Destroy()
} }
func TestSandboxGC(t *testing.T) {
key, err := newKey(t)
if err != nil {
t.Fatalf("Failed to obtain a key: %v", err)
}
s, err := NewSandbox(key, true)
if err != nil {
t.Fatalf("Failed to create a new sandbox: %v", err)
}
s.Destroy()
GC()
verifyCleanup(t, s, false)
}
func TestInterfaceEqual(t *testing.T) { func TestInterfaceEqual(t *testing.T) {
list := getInterfaceList() list := getInterfaceList()

View file

@ -12,6 +12,7 @@ import (
"fmt" "fmt"
"syscall" "syscall"
) )
// NsHandle is a handle to a network namespace. It can be cast directly // NsHandle is a handle to a network namespace. It can be cast directly
// to an int and used as a file descriptor. // to an int and used as a file descriptor.
type NsHandle int type NsHandle int

View file

@ -1,3 +1,5 @@
// +build linux
package netns package netns
import ( import (

View file

@ -1,3 +1,5 @@
// +build linux,386
package netns package netns
const ( const (

View file

@ -1,3 +1,5 @@
// +build linux,amd64
package netns package netns
const ( const (

View file

@ -1,3 +1,5 @@
// +build linux,arm
package netns package netns
const ( const (

View file

@ -0,0 +1,7 @@
// +build linux,ppc64le
package netns
const (
SYS_SETNS = 350
)

View file

@ -10,26 +10,26 @@ var (
ErrNotImplemented = errors.New("not implemented") ErrNotImplemented = errors.New("not implemented")
) )
func Set(ns Namespace) (err error) { func Set(ns NsHandle) (err error) {
return ErrNotImplemented return ErrNotImplemented
} }
func New() (ns Namespace, err error) { func New() (ns NsHandle, err error) {
return -1, ErrNotImplemented return -1, ErrNotImplemented
} }
func Get() (Namespace, error) { func Get() (NsHandle, error) {
return -1, ErrNotImplemented return -1, ErrNotImplemented
} }
func GetFromName(name string) (Namespace, error) { func GetFromName(name string) (NsHandle, error) {
return -1, ErrNotImplemented return -1, ErrNotImplemented
} }
func GetFromPid(pid int) (Namespace, error) { func GetFromPid(pid int) (NsHandle, error) {
return -1, ErrNotImplemented return -1, ErrNotImplemented
} }
func GetFromDocker(id string) (Namespace, error) { func GetFromDocker(id string) (NsHandle, error) {
return -1, ErrNotImplemented return -1, ErrNotImplemented
} }