Skip to content

Commit

Permalink
Merge pull request containers#2061 from adrianreber/static-ip
Browse files Browse the repository at this point in the history
Use existing interface to request IP address during restore
  • Loading branch information
openshift-merge-robot authored Jan 9, 2019
2 parents 5061081 + 2553dad commit 7b9d4f1
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 15 deletions.
5 changes: 5 additions & 0 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libpod/container_easyjson.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 1 addition & 9 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand All @@ -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)
Expand Down
22 changes: 20 additions & 2 deletions libpod/networking_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
45 changes: 42 additions & 3 deletions test/e2e/checkpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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))
})

})

0 comments on commit 7b9d4f1

Please sign in to comment.