فهرست منبع

Merge pull request #13784 from mrjana/cnm_integ

libnetwork: Add garbage collection trigger
Michael Crosby 10 سال پیش
والد
کامیت
4750e1f77e

+ 5 - 0
daemon/daemon.go

@@ -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

+ 2 - 2
hack/vendor.sh

@@ -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

+ 39 - 0
integration-cli/docker_cli_daemon_test.go

@@ -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))
+}

+ 1 - 1
vendor/src/github.com/docker/libnetwork/Godeps/Godeps.json

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

+ 7 - 0
vendor/src/github.com/docker/libnetwork/controller.go

@@ -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()
+}

+ 28 - 1
vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go

@@ -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 {

+ 10 - 3
vendor/src/github.com/docker/libnetwork/sandbox/sandbox_linux_test.go

@@ -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())
+		}
 	}
 }

+ 18 - 1
vendor/src/github.com/docker/libnetwork/sandbox/sandbox_test.go

@@ -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()
 

+ 1 - 0
vendor/src/github.com/vishvananda/netns/netns.go

@@ -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

+ 2 - 0
vendor/src/github.com/vishvananda/netns/netns_linux.go

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

+ 2 - 0
vendor/src/github.com/vishvananda/netns/netns_linux_386.go

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

+ 2 - 0
vendor/src/github.com/vishvananda/netns/netns_linux_amd.go → vendor/src/github.com/vishvananda/netns/netns_linux_amd64.go

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

+ 2 - 0
vendor/src/github.com/vishvananda/netns/netns_linux_arm.go

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

+ 7 - 0
vendor/src/github.com/vishvananda/netns/netns_linux_ppc64le.go

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

+ 6 - 6
vendor/src/github.com/vishvananda/netns/netns_unspecified.go

@@ -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
 }