summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_api.go16
-rw-r--r--libpod/container_exec.go10
-rw-r--r--libpod/container_internal.go11
-rw-r--r--libpod/container_internal_linux.go136
-rw-r--r--libpod/container_log.go2
-rw-r--r--libpod/networking_linux.go2
-rw-r--r--libpod/oci.go4
-rw-r--r--libpod/oci_attach_linux.go29
-rw-r--r--libpod/oci_attach_linux_cgo.go11
-rw-r--r--libpod/oci_attach_linux_nocgo.go7
-rw-r--r--libpod/oci_conmon_exec_linux.go10
-rw-r--r--libpod/oci_conmon_linux.go62
-rw-r--r--libpod/options.go2
13 files changed, 223 insertions, 79 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go
index c3e1a23d2..87ff764e3 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -703,6 +703,16 @@ type ContainerCheckpointOptions struct {
// important to be able to restore a container multiple
// times with '--import --name'.
IgnoreStaticMAC bool
+ // IgnoreVolumes tells the API to not export or not to import
+ // the content of volumes associated with the container
+ IgnoreVolumes bool
+ // Pre Checkpoint container and leave container running
+ PreCheckPoint bool
+ // Dump container with Pre Checkpoint images
+ WithPrevious bool
+ // ImportPrevious tells the API to restore container with two
+ // images. One is TargetFile, the other is ImportPrevious.
+ ImportPrevious string
}
// Checkpoint checkpoints a container
@@ -715,6 +725,12 @@ func (c *Container) Checkpoint(ctx context.Context, options ContainerCheckpointO
}
}
+ if options.WithPrevious {
+ if err := c.canWithPrevious(); err != nil {
+ return err
+ }
+ }
+
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index fce26acb0..5aee847e1 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -8,7 +8,6 @@ import (
"strconv"
"time"
- "github.com/containers/common/pkg/capabilities"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/storage/pkg/stringid"
@@ -973,20 +972,12 @@ func (c *Container) removeAllExecSessions() error {
// Make an ExecOptions struct to start the OCI runtime and prepare its exec
// bundle.
func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) {
- // TODO: check logic here - should we set Privileged if the container is
- // privileged?
- var capList []string
- if session.Config.Privileged || c.config.Privileged {
- capList = capabilities.AllCapabilities()
- }
-
if err := c.createExecBundle(session.ID()); err != nil {
return nil, err
}
opts := new(ExecOptions)
opts.Cmd = session.Config.Command
- opts.CapAdd = capList
opts.Env = session.Config.Environment
opts.Terminal = session.Config.Terminal
opts.Cwd = session.Config.WorkDir
@@ -995,6 +986,7 @@ func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) {
opts.DetachKeys = session.Config.DetachKeys
opts.ExitCommand = session.Config.ExitCommand
opts.ExitCommandDelay = session.Config.ExitCommandDelay
+ opts.Privileged = session.Config.Privileged
return opts, nil
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 540230c26..c7548e0e5 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -134,6 +134,11 @@ func (c *Container) CheckpointPath() string {
return filepath.Join(c.bundlePath(), "checkpoint")
}
+// PreCheckpointPath returns the path to the directory containing the pre-checkpoint-images
+func (c *Container) PreCheckPointPath() string {
+ return filepath.Join(c.bundlePath(), "pre-checkpoint")
+}
+
// AttachSocketPath retrieves the path of the container's attach socket
func (c *Container) AttachSocketPath() (string, error) {
return c.ociRuntime.AttachSocketPath(c)
@@ -2023,6 +2028,12 @@ func (c *Container) checkReadyForRemoval() error {
return nil
}
+// canWithPrevious return the stat of the preCheckPoint dir
+func (c *Container) canWithPrevious() error {
+ _, err := os.Stat(c.PreCheckPointPath())
+ return err
+}
+
// writeJSONFile marshalls and writes the given data to a JSON file
// in the bundle path
func (c *Container) writeJSONFile(v interface{}, file string) error {
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index cefe12209..705086bda 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -529,6 +529,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
+ availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps()
+ if err != nil {
+ return nil, err
+ }
+ g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs)
+ g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs)
+
// Hostname handling:
// If we have a UTS namespace, set Hostname in the OCI spec.
// Set the HOSTNAME environment variable unless explicitly overridden by
@@ -536,6 +543,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// set it to the host's hostname instead.
hostname := c.Hostname()
foundUTS := false
+
for _, i := range c.config.Spec.Linux.Namespaces {
if i.Type == spec.UTSNamespace && i.Path == "" {
foundUTS = true
@@ -790,11 +798,11 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr
return nil
}
-func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
- if (len(c.config.NamedVolumes) > 0) || (len(c.Dependencies()) > 0) {
- return errors.Errorf("Cannot export checkpoints of containers with named volumes or dependencies")
+func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
+ if len(c.Dependencies()) > 0 {
+ return errors.Errorf("Cannot export checkpoints of containers with dependencies")
}
- logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), dest)
+ logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), options.TargetFile)
includeFiles := []string{
"checkpoint",
@@ -804,10 +812,13 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
"spec.dump",
"network.status"}
+ if options.PreCheckPoint {
+ includeFiles[0] = "pre-checkpoint"
+ }
// Get root file-system changes included in the checkpoint archive
rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
deleteFilesList := filepath.Join(c.bundlePath(), "deleted.files")
- if !ignoreRootfs {
+ if !options.IgnoreRootfs {
// To correctly track deleted files, let's go through the output of 'podman diff'
tarFiles, err := c.runtime.GetDiff("", c.ID())
if err != nil {
@@ -870,6 +881,47 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
}
}
+ // Folder containing archived volumes that will be included in the export
+ expVolDir := filepath.Join(c.bundlePath(), "volumes")
+
+ // Create an archive for each volume associated with the container
+ if !options.IgnoreVolumes {
+ if err := os.MkdirAll(expVolDir, 0700); err != nil {
+ return errors.Wrapf(err, "error creating volumes export directory %q", expVolDir)
+ }
+
+ for _, v := range c.config.NamedVolumes {
+ volumeTarFilePath := filepath.Join("volumes", v.Name+".tar")
+ volumeTarFileFullPath := filepath.Join(c.bundlePath(), volumeTarFilePath)
+
+ volumeTarFile, err := os.Create(volumeTarFileFullPath)
+ if err != nil {
+ return errors.Wrapf(err, "error creating %q", volumeTarFileFullPath)
+ }
+
+ volume, err := c.runtime.GetVolume(v.Name)
+ if err != nil {
+ return err
+ }
+
+ input, err := archive.TarWithOptions(volume.MountPoint(), &archive.TarOptions{
+ Compression: archive.Uncompressed,
+ IncludeSourceDir: true,
+ })
+ if err != nil {
+ return errors.Wrapf(err, "error reading volume directory %q", v.Dest)
+ }
+
+ _, err = io.Copy(volumeTarFile, input)
+ if err != nil {
+ return err
+ }
+ volumeTarFile.Close()
+
+ includeFiles = append(includeFiles, volumeTarFilePath)
+ }
+ }
+
input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{
Compression: archive.Gzip,
IncludeSourceDir: true,
@@ -880,13 +932,13 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
return errors.Wrapf(err, "error reading checkpoint directory %q", c.ID())
}
- outFile, err := os.Create(dest)
+ outFile, err := os.Create(options.TargetFile)
if err != nil {
- return errors.Wrapf(err, "error creating checkpoint export file %q", dest)
+ return errors.Wrapf(err, "error creating checkpoint export file %q", options.TargetFile)
}
defer outFile.Close()
- if err := os.Chmod(dest, 0600); err != nil {
+ if err := os.Chmod(options.TargetFile, 0600); err != nil {
return err
}
@@ -898,6 +950,10 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error {
os.Remove(rootfsDiffPath)
os.Remove(deleteFilesList)
+ if !options.IgnoreVolumes {
+ os.RemoveAll(expVolDir)
+ }
+
return nil
}
@@ -962,15 +1018,24 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
defer c.newContainerEvent(events.Checkpoint)
+ // There is a bug from criu: https://github.com/checkpoint-restore/criu/issues/116
+ // We have to change the symbolic link from absolute path to relative path
+ if options.WithPrevious {
+ os.Remove(path.Join(c.CheckpointPath(), "parent"))
+ if err := os.Symlink("../pre-checkpoint", path.Join(c.CheckpointPath(), "parent")); err != nil {
+ return err
+ }
+ }
+
if options.TargetFile != "" {
- if err = c.exportCheckpoint(options.TargetFile, options.IgnoreRootfs); err != nil {
+ if err = c.exportCheckpoint(options); err != nil {
return err
}
}
logrus.Debugf("Checkpointed container %s", c.ID())
- if !options.KeepRunning {
+ if !options.KeepRunning && !options.PreCheckPoint {
c.state.State = define.ContainerStateStopped
// Cleanup Storage and Network
@@ -979,7 +1044,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
}
}
- if !options.Keep {
+ if !options.Keep && !options.PreCheckPoint {
cleanup := []string{
"dump.log",
"stats-dump",
@@ -1027,6 +1092,21 @@ func (c *Container) importCheckpoint(input string) error {
return nil
}
+func (c *Container) importPreCheckpoint(input string) error {
+ archiveFile, err := os.Open(input)
+ if err != nil {
+ return errors.Wrap(err, "failed to open pre-checkpoint archive for import")
+ }
+
+ defer archiveFile.Close()
+
+ err = archive.Untar(archiveFile, c.bundlePath(), nil)
+ if err != nil {
+ return errors.Wrapf(err, "Unpacking of pre-checkpoint archive %s failed", input)
+ }
+ return nil
+}
+
func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (retErr error) {
if err := c.checkpointRestoreSupported(); err != nil {
return err
@@ -1036,6 +1116,12 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID())
}
+ if options.ImportPrevious != "" {
+ if err := c.importPreCheckpoint(options.ImportPrevious); err != nil {
+ return err
+ }
+ }
+
if options.TargetFile != "" {
if err := c.importCheckpoint(options.TargetFile); err != nil {
return err
@@ -1193,6 +1279,30 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return err
}
+ // When restoring from an imported archive, allow restoring the content of volumes.
+ // Volumes are created in setupContainer()
+ if options.TargetFile != "" && !options.IgnoreVolumes {
+ for _, v := range c.config.NamedVolumes {
+ volumeFilePath := filepath.Join(c.bundlePath(), "volumes", v.Name+".tar")
+
+ volumeFile, err := os.Open(volumeFilePath)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to open volume file %s", volumeFilePath)
+ }
+ defer volumeFile.Close()
+
+ volume, err := c.runtime.GetVolume(v.Name)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to retrieve volume %s", v.Name)
+ }
+
+ mountPoint := volume.MountPoint()
+ if err := archive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil {
+ return errors.Wrapf(err, "Failed to extract volume %s to %s", volumeFilePath, mountPoint)
+ }
+ }
+ }
+
// Before actually restarting the container, apply the root file-system changes
if !options.IgnoreRootfs {
rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
@@ -1245,6 +1355,10 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err != nil {
logrus.Debugf("Non-fatal: removal of checkpoint directory (%s) failed: %v", c.CheckpointPath(), err)
}
+ err = os.RemoveAll(c.PreCheckPointPath())
+ if err != nil {
+ logrus.Debugf("Non-fatal: removal of pre-checkpoint directory (%s) failed: %v", c.PreCheckPointPath(), err)
+ }
cleanup := [...]string{"restore.log", "dump.log", "stats-dump", "stats-restore", "network.status", "rootfs-diff.tar", "deleted.files"}
for _, del := range cleanup {
file := filepath.Join(c.bundlePath(), del)
diff --git a/libpod/container_log.go b/libpod/container_log.go
index e58503bd3..f16e08353 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -82,7 +82,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
if nll.Partial() {
partial += nll.Msg
continue
- } else if !nll.Partial() && len(partial) > 1 {
+ } else if !nll.Partial() && len(partial) > 0 {
nll.Msg = partial + nll.Msg
partial = ""
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index be6867399..addf1814c 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -685,7 +685,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error {
return errors.Wrapf(err, "failed to generate random netns name")
}
- nsPath := fmt.Sprintf("/var/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
+ nsPath := fmt.Sprintf("/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil {
return err
diff --git a/libpod/oci.go b/libpod/oci.go
index 157c42c38..6948e6425 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -151,8 +151,6 @@ type OCIRuntime interface {
type ExecOptions struct {
// Cmd is the command to execute.
Cmd []string
- // CapAdd is a set of capabilities to add to the executed command.
- CapAdd []string
// Env is a set of environment variables to add to the container.
Env map[string]string
// Terminal is whether to create a new TTY for the exec session.
@@ -181,6 +179,8 @@ type ExecOptions struct {
// ExitCommandDelay is a delay (in seconds) between the exec session
// exiting, and the exit command being invoked.
ExitCommandDelay uint
+ // Privileged indicates the execed process will be launched in Privileged mode
+ Privileged bool
}
// HTTPAttachStreams informs the HTTPAttach endpoint which of the container's
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index fbc95510e..4556eba94 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -28,6 +28,15 @@ const (
AttachPipeStderr = 3
)
+func openUnixSocket(path string) (*net.UnixConn, error) {
+ fd, err := unix.Open(path, unix.O_PATH, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer unix.Close(fd)
+ return net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: fmt.Sprintf("/proc/self/fd/%d", fd), Net: "unixpacket"})
+}
+
// Attach to the given container
// Does not check if state is appropriate
// started is only required if startContainer is true
@@ -52,11 +61,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
if err != nil {
return err
}
- socketPath := buildSocketPath(attachSock)
- conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ conn, err := openUnixSocket(attachSock)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
}
defer func() {
if err := conn.Close(); err != nil {
@@ -124,7 +132,6 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se
if err != nil {
return err
}
- socketPath := buildSocketPath(sockPath)
// 2: read from attachFd that the parent process has set up the console socket
if _, err := readConmonPipeData(attachFd, ""); err != nil {
@@ -132,9 +139,9 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se
}
// 2: then attach
- conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ conn, err := openUnixSocket(sockPath)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath)
}
defer func() {
if err := conn.Close(); err != nil {
@@ -182,16 +189,6 @@ func registerResizeFunc(resize <-chan remotecommand.TerminalSize, bundlePath str
})
}
-func buildSocketPath(socketPath string) string {
- maxUnixLength := unixPathLength()
- if maxUnixLength < len(socketPath) {
- socketPath = socketPath[0:maxUnixLength]
- }
-
- logrus.Debug("connecting to socket ", socketPath)
- return socketPath
-}
-
func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detachKeys []byte) (chan error, chan error) {
receiveStdoutError := make(chan error)
go func() {
diff --git a/libpod/oci_attach_linux_cgo.go b/libpod/oci_attach_linux_cgo.go
deleted file mode 100644
index d81243360..000000000
--- a/libpod/oci_attach_linux_cgo.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//+build linux,cgo
-
-package libpod
-
-//#include <sys/un.h>
-// extern int unix_path_length(){struct sockaddr_un addr; return sizeof(addr.sun_path) - 1;}
-import "C"
-
-func unixPathLength() int {
- return int(C.unix_path_length())
-}
diff --git a/libpod/oci_attach_linux_nocgo.go b/libpod/oci_attach_linux_nocgo.go
deleted file mode 100644
index a514a555d..000000000
--- a/libpod/oci_attach_linux_nocgo.go
+++ /dev/null
@@ -1,7 +0,0 @@
-//+build linux,!cgo
-
-package libpod
-
-func unixPathLength() int {
- return 107
-}
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 4546acefb..dc5dd03df 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -2,7 +2,6 @@ package libpod
import (
"fmt"
- "net"
"net/http"
"os"
"os/exec"
@@ -398,10 +397,6 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
args = append(args, formatRuntimeOpts("--preserve-fds", fmt.Sprintf("%d", options.PreserveFDs))...)
}
- for _, capability := range options.CapAdd {
- args = append(args, formatRuntimeOpts("--cap", capability)...)
- }
-
if options.Terminal {
args = append(args, "-t")
}
@@ -516,7 +511,6 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
if err != nil {
return err
}
- socketPath := buildSocketPath(sockPath)
// 2: read from attachFd that the parent process has set up the console socket
if _, err := readConmonPipeData(pipes.attachPipe, ""); err != nil {
@@ -524,9 +518,9 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
}
// 2: then attach
- conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ conn, err := openUnixSocket(sockPath)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath)
}
defer func() {
if err := conn.Close(); err != nil {
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index e7cb5a802..70896cda4 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -22,6 +22,7 @@ import (
"text/template"
"time"
+ "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
conmonConfig "github.com/containers/conmon/runner/config"
"github.com/containers/podman/v2/libpod/define"
@@ -528,13 +529,12 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
if err != nil {
return err
}
- socketPath := buildSocketPath(attachSock)
var conn *net.UnixConn
if streamAttach {
- newConn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"})
+ newConn, err := openUnixSocket(attachSock)
if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath)
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
}
conn = newConn
defer func() {
@@ -543,7 +543,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
}
}()
- logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), socketPath)
+ logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), attachSock)
}
detachString := ctr.runtime.config.Engine.DetachKeys
@@ -768,10 +768,14 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
}
// imagePath is used by CRIU to store the actual checkpoint files
imagePath := ctr.CheckpointPath()
+ if options.PreCheckPoint {
+ imagePath = ctr.PreCheckPointPath()
+ }
// workPath will be used to store dump.log and stats-dump
workPath := ctr.bundlePath()
logrus.Debugf("Writing checkpoint to %s", imagePath)
logrus.Debugf("Writing checkpoint logs to %s", workPath)
+ logrus.Debugf("Pre-dump the container %t", options.PreCheckPoint)
args := []string{}
args = append(args, r.runtimeFlags...)
args = append(args, "checkpoint")
@@ -785,6 +789,15 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
if options.TCPEstablished {
args = append(args, "--tcp-established")
}
+ if !options.PreCheckPoint && options.KeepRunning {
+ args = append(args, "--leave-running")
+ }
+ if options.PreCheckPoint {
+ args = append(args, "--pre-dump")
+ }
+ if !options.PreCheckPoint && options.WithPrevious {
+ args = append(args, "--parent-path", ctr.PreCheckPointPath())
+ }
runtimeDir, err := util.GetRuntimeDir()
if err != nil {
return err
@@ -793,6 +806,7 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
}
args = append(args, ctr.ID())
+ logrus.Debugf("the args to checkpoint: %s %s", r.path, strings.Join(args, " "))
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...)
}
@@ -1201,13 +1215,7 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
}
pspec.SelinuxLabel = c.config.ProcessLabel
pspec.Args = options.Cmd
- for _, cap := range options.CapAdd {
- pspec.Capabilities.Bounding = append(pspec.Capabilities.Bounding, cap)
- pspec.Capabilities.Effective = append(pspec.Capabilities.Effective, cap)
- pspec.Capabilities.Inheritable = append(pspec.Capabilities.Inheritable, cap)
- pspec.Capabilities.Permitted = append(pspec.Capabilities.Permitted, cap)
- pspec.Capabilities.Ambient = append(pspec.Capabilities.Ambient, cap)
- }
+
// We need to default this to false else it will inherit terminal as true
// from the container.
pspec.Terminal = false
@@ -1263,6 +1271,31 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
pspec.User = processUser
}
+ ctrSpec, err := c.specFromState()
+ if err != nil {
+ return nil, err
+ }
+
+ allCaps := capabilities.AllCapabilities()
+ if options.Privileged {
+ pspec.Capabilities.Bounding = allCaps
+ } else {
+ pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding
+ }
+ if execUser.Uid == 0 {
+ pspec.Capabilities.Effective = pspec.Capabilities.Bounding
+ pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
+ pspec.Capabilities.Permitted = pspec.Capabilities.Bounding
+ pspec.Capabilities.Ambient = pspec.Capabilities.Bounding
+ } else {
+ if user == c.config.User {
+ pspec.Capabilities.Effective = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Inheritable = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Permitted = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Ambient = ctrSpec.Process.Capabilities.Effective
+ }
+ }
+
hasHomeSet := false
for _, s := range pspec.Env {
if strings.HasPrefix(s, "HOME=") {
@@ -1288,7 +1321,12 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
// configureConmonEnv gets the environment values to add to conmon's exec struct
// TODO this may want to be less hardcoded/more configurable in the future
func (r *ConmonOCIRuntime) configureConmonEnv(ctr *Container, runtimeDir string) ([]string, []*os.File) {
- env := make([]string, 0, 6)
+ var env []string
+ for _, e := range os.Environ() {
+ if strings.HasPrefix(e, "LC_") {
+ env = append(env, e)
+ }
+ }
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
env = append(env, fmt.Sprintf("_CONTAINERS_USERNS_CONFIGURED=%s", os.Getenv("_CONTAINERS_USERNS_CONFIGURED")))
env = append(env, fmt.Sprintf("_CONTAINERS_ROOTLESS_UID=%s", os.Getenv("_CONTAINERS_ROOTLESS_UID")))
diff --git a/libpod/options.go b/libpod/options.go
index 8100eee62..ef7db3235 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -306,7 +306,7 @@ func WithDefaultMountsFile(mountsFile string) RuntimeOption {
// WithTmpDir sets the directory that temporary runtime files which are not
// expected to survive across reboots will be stored.
-// This should be located on a tmpfs mount (/tmp or /var/run for example).
+// This should be located on a tmpfs mount (/tmp or /run for example).
func WithTmpDir(dir string) RuntimeOption {
return func(rt *Runtime) error {
if rt.valid {