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:
commit
4750e1f77e
15 changed files with 132 additions and 14 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
|
2
vendor/src/github.com/docker/libnetwork/Godeps/Godeps.json
generated
vendored
2
vendor/src/github.com/docker/libnetwork/Godeps/Godeps.json
generated
vendored
|
@ -79,7 +79,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/vishvananda/netns",
|
"ImportPath": "github.com/vishvananda/netns",
|
||||||
"Rev": "008d17ae001344769b031375bdb38a86219154c6"
|
"Rev": "5478c060110032f972e86a1f844fdb9a2f008f2c"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
if wait {
|
||||||
time.Sleep(time.Duration(gpmCleanupPeriod * 2))
|
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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
package netns
|
package netns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build linux,386
|
||||||
|
|
||||||
package netns
|
package netns
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build linux,amd64
|
||||||
|
|
||||||
package netns
|
package netns
|
||||||
|
|
||||||
const (
|
const (
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build linux,arm
|
||||||
|
|
||||||
package netns
|
package netns
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
7
vendor/src/github.com/vishvananda/netns/netns_linux_ppc64le.go
vendored
Normal file
7
vendor/src/github.com/vishvananda/netns/netns_linux_ppc64le.go
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// +build linux,ppc64le
|
||||||
|
|
||||||
|
package netns
|
||||||
|
|
||||||
|
const (
|
||||||
|
SYS_SETNS = 350
|
||||||
|
)
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue