summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/container_easyjson.go2
-rw-r--r--libpod/container_internal_linux.go10
-rw-r--r--libpod/networking_linux.go22
-rw-r--r--test/e2e/checkpoint_test.go45
5 files changed, 69 insertions, 15 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 44992c534..d0eb6a992 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -128,6 +128,11 @@ type Container struct {
rootlessSlirpSyncR *os.File
rootlessSlirpSyncW *os.File
+
+ // A restored container should have the same IP address as before
+ // being checkpointed. If requestedIP is set it will be used instead
+ // of config.StaticIP.
+ requestedIP net.IP
}
// containerState contains the current state of the container
diff --git a/libpod/container_easyjson.go b/libpod/container_easyjson.go
index 50741df11..f1cb09bcc 100644
--- a/libpod/container_easyjson.go
+++ b/libpod/container_easyjson.go
@@ -1,6 +1,6 @@
// +build seccomp ostree selinux varlink exclude_graphdriver_devicemapper
-// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
+// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT
package libpod
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index c66be1061..582a4c3e7 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -549,10 +549,8 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
}
}
if IP != nil {
- env := fmt.Sprintf("IP=%s", IP)
// Tell CNI which IP address we want.
- os.Setenv("CNI_ARGS", env)
- logrus.Debugf("Restoring container with %s", env)
+ c.requestedIP = IP
}
}
@@ -568,12 +566,6 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return err
}
- // TODO: use existing way to request static IPs, once it is merged in ocicni
- // https://github.com/cri-o/ocicni/pull/23/
-
- // CNI_ARGS was used to request a certain IP address. Unconditionally remove it.
- os.Unsetenv("CNI_ARGS")
-
// Read config
jsonPath := filepath.Join(c.bundlePath(), "config.json")
logrus.Debugf("generate.NewFromFile at %v", jsonPath)
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 43d0a61a4..a343bee6a 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -50,7 +50,16 @@ func (r *Runtime) getPodNetwork(id, name, nsPath string, networks []string, port
// Create and configure a new network namespace for a container
func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Result, error) {
- podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, ctr.config.StaticIP)
+ var requestedIP net.IP
+ if ctr.requestedIP != nil {
+ requestedIP = ctr.requestedIP
+ // cancel request for a specific IP in case the container is reused later
+ ctr.requestedIP = nil
+ } else {
+ requestedIP = ctr.config.StaticIP
+ }
+
+ podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP)
results, err := r.netPlugin.SetUpPod(podNetwork)
if err != nil {
@@ -258,7 +267,16 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID())
- podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, ctr.config.StaticIP)
+ var requestedIP net.IP
+ if ctr.requestedIP != nil {
+ requestedIP = ctr.requestedIP
+ // cancel request for a specific IP in case the container is reused later
+ ctr.requestedIP = nil
+ } else {
+ requestedIP = ctr.config.StaticIP
+ }
+
+ podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP)
// The network may have already been torn down, so don't fail here, just log
if err := r.netPlugin.TearDownPod(podNetwork); err != nil {
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 4e892d11c..ca2f35fc9 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -199,14 +199,17 @@ var _ = Describe("Podman checkpoint", func() {
})
It("podman checkpoint container with established tcp connections", func() {
- Skip("Seems to not work (yet) in CI")
podmanTest.RestoreArtifact(redis)
- session := podmanTest.Podman([]string{"run", "-it", "--security-opt", "seccomp=unconfined", "--network", "host", "-d", redis})
+ session := podmanTest.Podman([]string{"run", "-it", "--security-opt", "seccomp=unconfined", "-d", redis})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
+ IP := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
+ IP.WaitWithDefaultTimeout()
+ Expect(IP.ExitCode()).To(Equal(0))
+
// Open a network connection to the redis server
- conn, err := net.Dial("tcp", "127.0.0.1:6379")
+ conn, err := net.Dial("tcp", IP.OutputToString()+":6379")
if err != nil {
os.Exit(1)
}
@@ -287,4 +290,40 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
+ It("podman checkpoint and restore container with same IP", func() {
+ session := podmanTest.Podman([]string{"run", "-it", "--security-opt", "seccomp=unconfined", "--name", "test_name", "-d", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ IPBefore := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
+ IPBefore.WaitWithDefaultTimeout()
+ Expect(IPBefore.ExitCode()).To(Equal(0))
+
+ result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
+
+ result = podmanTest.Podman([]string{"container", "restore", "test_name"})
+ result.WaitWithDefaultTimeout()
+
+ IPAfter := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
+ IPAfter.WaitWithDefaultTimeout()
+ Expect(IPAfter.ExitCode()).To(Equal(0))
+
+ // Check that IP address did not change between checkpointing and restoring
+ Expect(IPBefore.OutputToString()).To(Equal(IPAfter.OutputToString()))
+
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ result = podmanTest.Podman([]string{"rm", "-fa"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ })
+
})