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()
// trigger libnetwork GC only if it's initialized
if daemon.netController != nil {
daemon.netController.GC()
}
}
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
#get libnetwork packages
clone git github.com/docker/libnetwork f72ad20491e8c46d9664da3f32a0eddb301e7c8d
clone git github.com/vishvananda/netns 008d17ae001344769b031375bdb38a86219154c6
clone git github.com/docker/libnetwork ace6b576239cd671d1645d82520b16791737f60d
clone git github.com/vishvananda/netns 5478c060110032f972e86a1f844fdb9a2f008f2c
clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c
# 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 {
t.Fatal(out, err)
}
if err := s.d.Restart(); err != nil {
t.Fatal(err)
}
@ -1225,3 +1226,41 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
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",
"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(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.
@ -299,3 +302,7 @@ func (c *controller) loadDriver(networkType string) (driverapi.Driver, error) {
}
return d, nil
}
func (c *controller) GC() {
sandbox.GC()
}

View file

@ -24,6 +24,7 @@ var (
gpmLock sync.Mutex
gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
)
// The networkNamespace type is the linux implementation of the Sandbox
@ -55,7 +56,18 @@ func removeUnusedPaths() {
period := gpmCleanupPeriod
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()
pathList := make([]string, 0, len(garbagePathMap))
for path := range garbagePathMap {
@ -70,6 +82,9 @@ func removeUnusedPaths() {
}
gpmWg.Done()
if gcOk {
close(gc)
}
}
}
@ -85,6 +100,18 @@ func removeFromGarbagePaths(path string) {
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
// container id.
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) {
time.Sleep(time.Duration(gpmCleanupPeriod * 2))
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 {
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)
s.Destroy()
verifyCleanup(t, s)
verifyCleanup(t, s, true)
}
func TestSandboxCreateTwice(t *testing.T) {
@ -77,6 +77,23 @@ func TestSandboxCreateTwice(t *testing.T) {
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) {
list := getInterfaceList()

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,5 @@
// +build linux,arm
package netns
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")
)
func Set(ns Namespace) (err error) {
func Set(ns NsHandle) (err error) {
return ErrNotImplemented
}
func New() (ns Namespace, err error) {
func New() (ns NsHandle, err error) {
return -1, ErrNotImplemented
}
func Get() (Namespace, error) {
func Get() (NsHandle, error) {
return -1, ErrNotImplemented
}
func GetFromName(name string) (Namespace, error) {
func GetFromName(name string) (NsHandle, error) {
return -1, ErrNotImplemented
}
func GetFromPid(pid int) (Namespace, error) {
func GetFromPid(pid int) (NsHandle, error) {
return -1, ErrNotImplemented
}
func GetFromDocker(id string) (Namespace, error) {
func GetFromDocker(id string) (NsHandle, error) {
return -1, ErrNotImplemented
}