From ea06836d6cf1a723b862f61a75439b1bc6dafaa1 Mon Sep 17 00:00:00 2001 From: Saied Kazemi Date: Tue, 9 Feb 2016 22:00:37 -0800 Subject: [PATCH] Restore network connectivity after container restore This is a work-in-progress implementation of restoring network connectivty after container restore. Its main purpose is for testing and starting a conversation for a production-quality implementation. Signed-off-by: Saied Kazemi --- daemon/daemon.go | 3 +++ daemon/execdriver/driver.go | 1 + daemon/execdriver/native/driver.go | 13 +++++++++++++ .../github.com/vishvananda/netlink/link_linux.go | 12 ++++++++++++ 4 files changed, 29 insertions(+) diff --git a/daemon/daemon.go b/daemon/daemon.go index 38e90cfe8289d..e3cb0eff8b108 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -1028,6 +1028,9 @@ func (daemon *Daemon) Checkpoint(c *container.Container, opts *types.CriuConfig) func (daemon *Daemon) Restore(c *container.Container, pipes *execdriver.Pipes, restoreCallback execdriver.DriverCallback, opts *types.CriuConfig, forceRestore bool) (execdriver.ExitStatus, error) { hooks := execdriver.Hooks{ Restore: restoreCallback, + PostRestore: func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error { + return daemon.setNetworkNamespaceKey(c.ID, pid) + }, } exitCode, err := daemon.execDriver.Restore(c.Command, pipes, hooks, opts, forceRestore) diff --git a/daemon/execdriver/driver.go b/daemon/execdriver/driver.go index 374de6daebc98..f29467098e078 100644 --- a/daemon/execdriver/driver.go +++ b/daemon/execdriver/driver.go @@ -40,6 +40,7 @@ type Hooks struct { PostStop []DriverCallback // Restore is called after the container is restored Restore DriverCallback + PostRestore DriverCallback } // Info is driver specific information based on diff --git a/daemon/execdriver/native/driver.go b/daemon/execdriver/native/driver.go index e62c67458f87f..1e1bf11001fc9 100644 --- a/daemon/execdriver/native/driver.go +++ b/daemon/execdriver/native/driver.go @@ -393,7 +393,20 @@ func (d *Driver) Restore(c *execdriver.Command, pipes *execdriver.Pipes, hooks e return execdriver.ExitStatus{ExitCode: -1}, err } + if err := d.createNetwork(&config, c, hooks); err != nil { + return execdriver.ExitStatus{ExitCode: -1}, err + } + oom := notifyOnOOM(cont) + if hooks.PostRestore != nil { + pid, err := p.Pid() + if err != nil { + p.Signal(os.Kill) + p.Wait() + return execdriver.ExitStatus{ExitCode: -1}, err + } + hooks.PostRestore(&c.ProcessConfig, pid, oom) + } if hooks.Restore != nil { pid, err := p.Pid() if err != nil { diff --git a/vendor/src/github.com/vishvananda/netlink/link_linux.go b/vendor/src/github.com/vishvananda/netlink/link_linux.go index 08262857f19c1..94e9fefca0318 100644 --- a/vendor/src/github.com/vishvananda/netlink/link_linux.go +++ b/vendor/src/github.com/vishvananda/netlink/link_linux.go @@ -103,6 +103,18 @@ func LinkSetName(link Link, name string) error { req.AddData(data) _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + if err != nil && os.IsExist(err) && name == "eth0" { + // XXX Temporary hack. + // If we are called after a container has been restored, + // we need to delete eth0 and try again. + // The right solution is to tell CRIU not create network + // devices. + l := &Device{LinkAttrs: LinkAttrs{Name: name}} + if e := LinkDel(l); e != nil { + return e + } + _, err = req.Execute(syscall.NETLINK_ROUTE, 0) + } return err }