mirror of
https://github.com/containers/podman.git
synced 2025-09-04 18:35:35 +00:00
Merge pull request #26895 from intirix/tcp-close
Add support for criu's tcp-close functionality.
This commit is contained in:
@@ -52,6 +52,7 @@ func init() {
|
||||
flags.BoolVarP(&restoreOptions.All, "all", "a", false, "Restore all checkpointed containers")
|
||||
flags.BoolVarP(&restoreOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
||||
flags.BoolVar(&restoreOptions.TCPEstablished, "tcp-established", false, "Restore a container with established TCP connections")
|
||||
flags.BoolVar(&restoreOptions.TCPClose, "tcp-close", false, "Restore a container and close all TCP connections")
|
||||
flags.BoolVar(&restoreOptions.FileLocks, "file-locks", false, "Restore a container with file locks")
|
||||
|
||||
importFlagName := "import"
|
||||
|
@@ -150,6 +150,14 @@ initial *container* start, with a new set of port forwarding rules.
|
||||
|
||||
For more details, see **[podman run --publish](podman-run.1.md#--publish)**.
|
||||
|
||||
#### **--tcp-close**
|
||||
|
||||
Restore a *container* and close all TCP connections. This option is useful
|
||||
when TCP connections are not needed after restore or when connections
|
||||
will be reestablished by the application. If the checkpoint image was created with
|
||||
**--tcp-close**, this option should be used during restore.\
|
||||
The default is **false**.
|
||||
|
||||
#### **--tcp-established**
|
||||
|
||||
Restore a *container* with established TCP connections. If the checkpoint image
|
||||
|
@@ -965,6 +965,8 @@ type ContainerCheckpointOptions struct {
|
||||
// TCPEstablished tells the API to checkpoint a container
|
||||
// even if it contains established TCP connections
|
||||
TCPEstablished bool
|
||||
// TCPClose tells the API to close all TCP connections during restore
|
||||
TCPClose bool
|
||||
// TargetFile tells the API to read (or write) the checkpoint image
|
||||
// from (or to) the filename set in TargetFile
|
||||
TargetFile string
|
||||
|
@@ -1082,6 +1082,9 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
|
||||
if restoreOptions.TCPEstablished {
|
||||
args = append(args, "--runtime-opt", "--tcp-established")
|
||||
}
|
||||
if restoreOptions.TCPClose {
|
||||
args = append(args, "--runtime-opt", "--tcp-close")
|
||||
}
|
||||
if restoreOptions.FileLocks {
|
||||
args = append(args, "--runtime-opt", "--file-locks")
|
||||
}
|
||||
|
@@ -307,6 +307,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
|
||||
query := struct {
|
||||
Keep bool `schema:"keep"`
|
||||
TCPEstablished bool `schema:"tcpEstablished"`
|
||||
TCPClose bool `schema:"tcpClose"`
|
||||
Import bool `schema:"import"`
|
||||
Name string `schema:"name"`
|
||||
IgnoreRootFS bool `schema:"ignoreRootFS"`
|
||||
@@ -329,6 +330,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
|
||||
Name: query.Name,
|
||||
Keep: query.Keep,
|
||||
TCPEstablished: query.TCPEstablished,
|
||||
TCPClose: query.TCPClose,
|
||||
IgnoreRootFS: query.IgnoreRootFS,
|
||||
IgnoreVolumes: query.IgnoreVolumes,
|
||||
IgnoreStaticIP: query.IgnoreStaticIP,
|
||||
|
@@ -1636,7 +1636,11 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
|
||||
// - in: query
|
||||
// name: tcpEstablished
|
||||
// type: boolean
|
||||
// description: checkpoint a container with established TCP connections
|
||||
// description: restore a container with established TCP connections
|
||||
// - in: query
|
||||
// name: tcpClose
|
||||
// type: boolean
|
||||
// description: restore a container but close the TCP connections
|
||||
// - in: query
|
||||
// name: import
|
||||
// type: boolean
|
||||
|
@@ -83,6 +83,7 @@ type RestoreOptions struct {
|
||||
Keep *bool
|
||||
Name *string
|
||||
TCPEstablished *bool
|
||||
TCPClose *bool
|
||||
Pod *string
|
||||
PrintStats *bool
|
||||
PublishPorts []string
|
||||
|
@@ -152,6 +152,21 @@ func (o *RestoreOptions) GetTCPEstablished() bool {
|
||||
return *o.TCPEstablished
|
||||
}
|
||||
|
||||
// WithTCPClose set field TCPClose to given value
|
||||
func (o *RestoreOptions) WithTCPClose(value bool) *RestoreOptions {
|
||||
o.TCPClose = &value
|
||||
return o
|
||||
}
|
||||
|
||||
// GetTCPClose returns value of field TCPClose
|
||||
func (o *RestoreOptions) GetTCPClose() bool {
|
||||
if o.TCPClose == nil {
|
||||
var z bool
|
||||
return z
|
||||
}
|
||||
return *o.TCPClose
|
||||
}
|
||||
|
||||
// WithPod set field Pod to given value
|
||||
func (o *RestoreOptions) WithPod(value string) *RestoreOptions {
|
||||
o.Pod = &value
|
||||
|
@@ -227,6 +227,7 @@ type RestoreOptions struct {
|
||||
Latest bool
|
||||
Name string
|
||||
TCPEstablished bool
|
||||
TCPClose bool
|
||||
ImportPrevious string
|
||||
PublishPorts []string
|
||||
Pod string
|
||||
|
@@ -738,6 +738,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
|
||||
restoreOptions := libpod.ContainerCheckpointOptions{
|
||||
Keep: options.Keep,
|
||||
TCPEstablished: options.TCPEstablished,
|
||||
TCPClose: options.TCPClose,
|
||||
TargetFile: options.Import,
|
||||
Name: options.Name,
|
||||
IgnoreRootfs: options.IgnoreRootFS,
|
||||
|
@@ -472,6 +472,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
|
||||
options.WithKeep(opts.Keep)
|
||||
options.WithName(opts.Name)
|
||||
options.WithTCPEstablished(opts.TCPEstablished)
|
||||
options.WithTCPClose(opts.TCPClose)
|
||||
options.WithPod(opts.Pod)
|
||||
options.WithPrintStats(opts.PrintStats)
|
||||
options.WithPublishPorts(opts.PublishPorts)
|
||||
|
@@ -402,6 +402,55 @@ var _ = Describe("Podman checkpoint", func() {
|
||||
conn.Close()
|
||||
})
|
||||
|
||||
It("podman restore container with tcp-close", func() {
|
||||
Skip("FIXME: #26289 - Rawhide only issue, skip for now")
|
||||
|
||||
// Start a container with redis (which listens on tcp port)
|
||||
localRunString := getRunString([]string{REDIS_IMAGE})
|
||||
session := podmanTest.Podman(localRunString)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
cid := session.OutputToString()
|
||||
if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
|
||||
Fail("Container failed to get ready")
|
||||
}
|
||||
|
||||
// Get container IP
|
||||
IP := podmanTest.PodmanExitCleanly("inspect", cid, fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname))
|
||||
|
||||
// Open a network connection to the redis server
|
||||
conn, err := net.DialTimeout("tcp4", IP.OutputToString()+":6379", time.Duration(3)*time.Second)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer conn.Close()
|
||||
|
||||
// Checkpoint with --tcp-established since we have an open connection
|
||||
podmanTest.PodmanExitCleanly("container", "checkpoint", cid, "--tcp-established")
|
||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
||||
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
|
||||
|
||||
// Restore should fail as the checkpoint image contains established TCP connections
|
||||
result := podmanTest.Podman([]string{"container", "restore", cid})
|
||||
result.WaitWithDefaultTimeout()
|
||||
|
||||
// default message when using crun
|
||||
expectStderr := "crun: CRIU restoring failed -52. Please check CRIU logfile"
|
||||
if podmanTest.OCIRuntime == "runc" {
|
||||
expectStderr = "runc: criu failed: type NOTIFY errno 0"
|
||||
}
|
||||
if !IsRemote() {
|
||||
// This part is only seen with podman local, never remote
|
||||
expectStderr = "OCI runtime error: " + expectStderr
|
||||
}
|
||||
Expect(result).Should(ExitWithError(125, expectStderr))
|
||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
||||
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
|
||||
|
||||
// Now it should work thanks to "--tcp-close"
|
||||
podmanTest.PodmanExitCleanly("container", "restore", cid, "--tcp-close")
|
||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
|
||||
})
|
||||
|
||||
It("podman checkpoint with --leave-running", func() {
|
||||
localRunString := getRunString([]string{ALPINE, "top"})
|
||||
session := podmanTest.Podman(localRunString)
|
||||
|
Reference in New Issue
Block a user