aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go3
-rw-r--r--libpod/container_inspect.go25
-rw-r--r--libpod/container_internal.go10
-rw-r--r--libpod/container_internal_linux.go34
-rw-r--r--libpod/container_internal_linux_test.go29
-rw-r--r--libpod/container_log.go16
-rw-r--r--libpod/define/container_inspect.go29
-rw-r--r--libpod/events/filters.go4
-rw-r--r--libpod/events/journal_linux.go4
-rw-r--r--libpod/events/logfile.go2
-rw-r--r--libpod/kube.go4
-rw-r--r--libpod/network/cni/cni_exec.go2
-rw-r--r--libpod/network/devices.go10
-rw-r--r--libpod/network/network.go5
-rw-r--r--libpod/networking_linux.go9
-rw-r--r--libpod/networking_slirp4netns.go11
-rw-r--r--libpod/oci_conmon_exec_linux.go16
-rw-r--r--libpod/oci_conmon_linux.go44
-rw-r--r--libpod/options.go480
-rw-r--r--libpod/pod.go169
-rw-r--r--libpod/pod_api.go53
-rw-r--r--libpod/pod_internal.go2
-rw-r--r--libpod/runtime_ctr.go26
-rw-r--r--libpod/runtime_pod_infra_linux.go284
-rw-r--r--libpod/runtime_pod_linux.go57
25 files changed, 386 insertions, 942 deletions
diff --git a/libpod/container.go b/libpod/container.go
index c57250d72..0986a0d80 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -159,6 +159,9 @@ type ContainerState struct {
// OOMKilled indicates that the container was killed as it ran out of
// memory
OOMKilled bool `json:"oomKilled,omitempty"`
+ // Checkpointed indicates that the container was stopped by a checkpoint
+ // operation.
+ Checkpointed bool `json:"checkpointed,omitempty"`
// PID is the PID of a running container
PID int `json:"pid,omitempty"`
// ConmonPID is the PID of the container's conmon
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 97318a2e8..2ef4532cd 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -103,18 +103,19 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
Path: path,
Args: args,
State: &define.InspectContainerState{
- OciVersion: ctrSpec.Version,
- Status: runtimeInfo.State.String(),
- Running: runtimeInfo.State == define.ContainerStateRunning,
- Paused: runtimeInfo.State == define.ContainerStatePaused,
- OOMKilled: runtimeInfo.OOMKilled,
- Dead: runtimeInfo.State.String() == "bad state",
- Pid: runtimeInfo.PID,
- ConmonPid: runtimeInfo.ConmonPID,
- ExitCode: runtimeInfo.ExitCode,
- Error: "", // can't get yet
- StartedAt: runtimeInfo.StartedTime,
- FinishedAt: runtimeInfo.FinishedTime,
+ OciVersion: ctrSpec.Version,
+ Status: runtimeInfo.State.String(),
+ Running: runtimeInfo.State == define.ContainerStateRunning,
+ Paused: runtimeInfo.State == define.ContainerStatePaused,
+ OOMKilled: runtimeInfo.OOMKilled,
+ Dead: runtimeInfo.State.String() == "bad state",
+ Pid: runtimeInfo.PID,
+ ConmonPid: runtimeInfo.ConmonPID,
+ ExitCode: runtimeInfo.ExitCode,
+ Error: "", // can't get yet
+ StartedAt: runtimeInfo.StartedTime,
+ FinishedAt: runtimeInfo.FinishedTime,
+ Checkpointed: runtimeInfo.Checkpointed,
},
Image: config.RootfsImageID,
ImageName: config.RootfsImageName,
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 3f7a4807d..4d1a25541 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -584,6 +584,7 @@ func resetState(state *ContainerState) {
state.StoppedByUser = false
state.RestartPolicyMatch = false
state.RestartCount = 0
+ state.Checkpointed = false
}
// Refresh refreshes the container's state after a restart.
@@ -972,11 +973,12 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
}
// Check the status
+ conf := depCtr.Config()
state, err := depCtr.State()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID())
}
- if state != define.ContainerStateRunning {
+ if state != define.ContainerStateRunning && !conf.IsInfra {
notRunning = append(notRunning, dep)
}
depCtrs[dep] = depCtr
@@ -1071,6 +1073,11 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
return err
}
+ // Make sure the workdir exists while initializing container
+ if err := c.resolveWorkDir(); err != nil {
+ return err
+ }
+
// Save the OCI newSpec to disk
if err := c.saveSpec(newSpec); err != nil {
return err
@@ -1104,6 +1111,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
c.state.ExecSessions = make(map[string]*ExecSession)
}
+ c.state.Checkpointed = false
c.state.ExitCode = 0
c.state.Exited = false
c.state.State = define.ContainerStateCreated
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 8b73c82de..eabe8efd2 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package libpod
@@ -176,11 +177,6 @@ func (c *Container) prepare() error {
return err
}
- // Make sure the workdir exists
- if err := c.resolveWorkDir(); err != nil {
- return err
- }
-
return nil
}
@@ -778,6 +774,18 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
+ // Pass down the LISTEN_* environment (see #10443).
+ for _, key := range []string{"LISTEN_PID", "LISTEN_FDS", "LISTEN_FDNAMES"} {
+ if val, ok := os.LookupEnv(key); ok {
+ // Force the PID to `1` since we cannot rely on (all
+ // versions of) all runtimes to do it for us.
+ if key == "LISTEN_PID" {
+ val = "1"
+ }
+ g.AddProcessEnv(key, val)
+ }
+ }
+
return g.Config, nil
}
@@ -1138,6 +1146,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
if !options.KeepRunning && !options.PreCheckPoint {
c.state.State = define.ContainerStateStopped
+ c.state.Checkpointed = true
// Cleanup Storage and Network
if err := c.cleanup(ctx); err != nil {
@@ -1935,9 +1944,24 @@ func (c *Container) generateHosts(path string) (string, error) {
}
hosts := string(orig)
hosts += c.getHosts()
+
+ hosts = c.appendLocalhost(hosts)
+
return c.writeStringToRundir("hosts", hosts)
}
+// based on networking mode we may want to append the localhost
+// if there isn't any record for it and also this shoud happen
+// in slirp4netns and similar network modes.
+func (c *Container) appendLocalhost(hosts string) string {
+ if !strings.Contains(hosts, "localhost") &&
+ !c.config.NetMode.IsHost() {
+ hosts += "127.0.0.1\tlocalhost\n::1\tlocalhost\n"
+ }
+
+ return hosts
+}
+
// appendHosts appends a container's config and state pertaining to hosts to a container's
// local hosts file. netCtr is the container from which the netNS information is
// taken.
diff --git a/libpod/container_internal_linux_test.go b/libpod/container_internal_linux_test.go
index 1465ffbea..899f9bffd 100644
--- a/libpod/container_internal_linux_test.go
+++ b/libpod/container_internal_linux_test.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package libpod
@@ -7,6 +8,7 @@ import (
"os"
"testing"
+ "github.com/containers/podman/v3/pkg/namespaces"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert"
)
@@ -68,3 +70,30 @@ func TestGenerateUserGroupEntry(t *testing.T) {
}
assert.Equal(t, group, "567:x:567:567\n")
}
+
+func TestAppendLocalhost(t *testing.T) {
+ {
+ c := Container{
+ config: &ContainerConfig{
+ ContainerNetworkConfig: ContainerNetworkConfig{
+ NetMode: namespaces.NetworkMode("slirp4netns"),
+ },
+ },
+ }
+
+ assert.Equal(t, "127.0.0.1\tlocalhost\n::1\tlocalhost\n", c.appendLocalhost(""))
+ assert.Equal(t, "127.0.0.1\tlocalhost", c.appendLocalhost("127.0.0.1\tlocalhost"))
+ }
+ {
+ c := Container{
+ config: &ContainerConfig{
+ ContainerNetworkConfig: ContainerNetworkConfig{
+ NetMode: namespaces.NetworkMode("host"),
+ },
+ },
+ }
+
+ assert.Equal(t, "", c.appendLocalhost(""))
+ assert.Equal(t, "127.0.0.1\tlocalhost", c.appendLocalhost("127.0.0.1\tlocalhost"))
+ }
+}
diff --git a/libpod/container_log.go b/libpod/container_log.go
index 3988bb654..89dd5e8b0 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -107,16 +107,18 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
// until EOF.
state, err := c.State()
if err != nil || state != define.ContainerStateRunning {
- // Make sure to wait at least for the poll duration
- // before stopping the file logger (see #10675).
- time.Sleep(watch.POLL_DURATION)
- tailError := t.StopAtEOF()
- if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" {
- logrus.Errorf("Error stopping logger: %v", tailError)
- }
if err != nil && errors.Cause(err) != define.ErrNoSuchCtr {
logrus.Errorf("Error getting container state: %v", err)
}
+ go func() {
+ // Make sure to wait at least for the poll duration
+ // before stopping the file logger (see #10675).
+ time.Sleep(watch.POLL_DURATION)
+ tailError := t.StopAtEOF()
+ if tailError != nil && tailError.Error() != "tail: stop at eof" {
+ logrus.Errorf("Error stopping logger: %v", tailError)
+ }
+ }()
return nil
}
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index af8ba6ecf..90703a807 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -189,20 +189,21 @@ type InspectMount struct {
// Docker, but here we see more fields that are unused (nonsensical in the
// context of Libpod).
type InspectContainerState struct {
- OciVersion string `json:"OciVersion"`
- Status string `json:"Status"`
- Running bool `json:"Running"`
- Paused bool `json:"Paused"`
- Restarting bool `json:"Restarting"` // TODO
- OOMKilled bool `json:"OOMKilled"`
- Dead bool `json:"Dead"`
- Pid int `json:"Pid"`
- ConmonPid int `json:"ConmonPid,omitempty"`
- ExitCode int32 `json:"ExitCode"`
- Error string `json:"Error"` // TODO
- StartedAt time.Time `json:"StartedAt"`
- FinishedAt time.Time `json:"FinishedAt"`
- Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"`
+ OciVersion string `json:"OciVersion"`
+ Status string `json:"Status"`
+ Running bool `json:"Running"`
+ Paused bool `json:"Paused"`
+ Restarting bool `json:"Restarting"` // TODO
+ OOMKilled bool `json:"OOMKilled"`
+ Dead bool `json:"Dead"`
+ Pid int `json:"Pid"`
+ ConmonPid int `json:"ConmonPid,omitempty"`
+ ExitCode int32 `json:"ExitCode"`
+ Error string `json:"Error"` // TODO
+ StartedAt time.Time `json:"StartedAt"`
+ FinishedAt time.Time `json:"FinishedAt"`
+ Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"`
+ Checkpointed bool `json:"Checkpointed,omitempty"`
}
// HealthCheckResults describes the results/logs from a healthcheck
diff --git a/libpod/events/filters.go b/libpod/events/filters.go
index 4d27e8fc4..d5e2b81f3 100644
--- a/libpod/events/filters.go
+++ b/libpod/events/filters.go
@@ -135,7 +135,7 @@ func generateEventFilters(filters []string, since, until string) (map[string][]E
}
if len(since) > 0 {
- timeSince, err := util.ParseInputTime(since)
+ timeSince, err := util.ParseInputTime(since, true)
if err != nil {
return nil, errors.Wrapf(err, "unable to convert since time of %s", since)
}
@@ -144,7 +144,7 @@ func generateEventFilters(filters []string, since, until string) (map[string][]E
}
if len(until) > 0 {
- timeUntil, err := util.ParseInputTime(until)
+ timeUntil, err := util.ParseInputTime(until, false)
if err != nil {
return nil, errors.Wrapf(err, "unable to convert until time of %s", until)
}
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 7006290e9..a3e0d9754 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -73,13 +73,15 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
if err != nil {
return errors.Wrapf(err, "failed to parse event filters")
}
+
var untilTime time.Time
if len(options.Until) > 0 {
- untilTime, err = util.ParseInputTime(options.Until)
+ untilTime, err = util.ParseInputTime(options.Until, false)
if err != nil {
return err
}
}
+
j, err := sdjournal.NewJournal()
if err != nil {
return err
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 952444f2b..e3f0ab8f0 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -53,7 +53,7 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
return err
}
if len(options.Until) > 0 {
- untilTime, err := util.ParseInputTime(options.Until)
+ untilTime, err := util.ParseInputTime(options.Until, false)
if err != nil {
return err
}
diff --git a/libpod/kube.go b/libpod/kube.go
index a3f49bfe8..fff040adb 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -10,6 +10,8 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/lookup"
+ "github.com/containers/podman/v3/pkg/namespaces"
+ "github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/util"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/opencontainers/runtime-spec/specs-go"
@@ -72,7 +74,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
return nil, servicePorts, err
}
servicePorts = containerPortsToServicePorts(ports)
- hostNetwork = p.config.InfraContainer.HostNetwork
+ hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host))
}
pod, err := p.podWithContainers(allContainers, ports, hostNetwork)
if err != nil {
diff --git a/libpod/network/cni/cni_exec.go b/libpod/network/cni/cni_exec.go
index 0aec3d4f1..c4d7f49f7 100644
--- a/libpod/network/cni/cni_exec.go
+++ b/libpod/network/cni/cni_exec.go
@@ -8,7 +8,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/libpod/network/devices.go b/libpod/network/devices.go
index de6bb4efc..fc9aff337 100644
--- a/libpod/network/devices.go
+++ b/libpod/network/devices.go
@@ -2,12 +2,11 @@ package network
import (
"fmt"
- "os/exec"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/pkg/util"
- "github.com/containers/podman/v3/utils"
"github.com/sirupsen/logrus"
+ "github.com/vishvananda/netlink"
)
// GetFreeDeviceName returns a device name that is unused; used when no network
@@ -52,12 +51,9 @@ func GetFreeDeviceName(config *config.Config) (string, error) {
// RemoveInterface removes an interface by the given name
func RemoveInterface(interfaceName string) error {
- // Make sure we have the ip command on the system
- ipPath, err := exec.LookPath("ip")
+ link, err := netlink.LinkByName(interfaceName)
if err != nil {
return err
}
- // Delete the network interface
- _, err = utils.ExecCmd(ipPath, []string{"link", "del", interfaceName}...)
- return err
+ return netlink.LinkDel(link)
}
diff --git a/libpod/network/network.go b/libpod/network/network.go
index 805988432..3b81ce776 100644
--- a/libpod/network/network.go
+++ b/libpod/network/network.go
@@ -194,8 +194,9 @@ func removeNetwork(config *config.Config, name string) error {
return errors.Wrapf(err, "failed to get live network names")
}
if util.StringInSlice(interfaceName, liveNetworkNames) {
- if err := RemoveInterface(interfaceName); err != nil {
- return errors.Wrapf(err, "failed to delete the network interface %q", interfaceName)
+ if err = RemoveInterface(interfaceName); err != nil {
+ // only log the error, it is not fatal
+ logrus.Infof("failed to remove network interface %s: %v", interfaceName, err)
}
}
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index dbe2274d3..9aa6cab15 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -185,7 +185,13 @@ func (r *RootlessCNI) Do(toRun func() error) error {
// if there is no symlink exit
break
}
- resolvePath = filepath.Join(filepath.Dir(resolvePath), link)
+ if filepath.IsAbs(link) {
+ // link is as an absolute path
+ resolvePath = link
+ } else {
+ // link is as a relative, join it with the previous path
+ resolvePath = filepath.Join(filepath.Dir(resolvePath), link)
+ }
if strings.HasPrefix(resolvePath, "/run/") {
break
}
@@ -632,7 +638,6 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
}
podName := getCNIPodName(ctr)
-
networks, _, err := ctr.networks()
if err != nil {
return nil, err
diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go
index 5858364ff..a09027b72 100644
--- a/libpod/networking_slirp4netns.go
+++ b/libpod/networking_slirp4netns.go
@@ -632,16 +632,7 @@ func (c *Container) reloadRootlessRLKPortMapping() error {
childIP := getRootlessPortChildIP(c)
logrus.Debugf("reloading rootless ports for container %s, childIP is %s", c.config.ID, childIP)
- var conn net.Conn
- var err error
- // try three times to connect to the socket, maybe it is not ready yet
- for i := 0; i < 3; i++ {
- conn, err = net.Dial("unix", filepath.Join(c.runtime.config.Engine.TmpDir, "rp", c.config.ID))
- if err == nil {
- break
- }
- time.Sleep(250 * time.Millisecond)
- }
+ conn, err := openUnixSocket(filepath.Join(c.runtime.config.Engine.TmpDir, "rp", c.config.ID))
if err != nil {
// This is not a hard error for backwards compatibility. A container started
// with an old version did not created the rootlessport socket.
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 469bc7d86..5a7677b04 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -438,7 +438,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
// }
// }
- conmonEnv, extraFiles := r.configureConmonEnv(c, runtimeDir)
+ conmonEnv := r.configureConmonEnv(c, runtimeDir)
var filesToClose []*os.File
if options.PreserveFDs > 0 {
@@ -456,7 +456,6 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
execCmd.Env = append(execCmd.Env, conmonEnv...)
execCmd.ExtraFiles = append(execCmd.ExtraFiles, childSyncPipe, childStartPipe, childAttachPipe)
- execCmd.ExtraFiles = append(execCmd.ExtraFiles, extraFiles...)
execCmd.Dir = c.execBundlePath(sessionID)
execCmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
@@ -685,6 +684,19 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
pspec.Env = append(pspec.Env, env...)
}
+ // Add secret envs if they exist
+ manager, err := c.runtime.SecretsManager()
+ if err != nil {
+ return nil, err
+ }
+ for name, secr := range c.config.EnvSecrets {
+ _, data, err := manager.LookupSecretData(secr.Name)
+ if err != nil {
+ return nil, err
+ }
+ pspec.Env = append(pspec.Env, fmt.Sprintf("%s=%s", name, string(data)))
+ }
+
if options.Cwd != "" {
pspec.Cwd = options.Cwd
}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index c14911980..353e6af71 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -34,7 +34,6 @@ import (
"github.com/containers/podman/v3/utils"
"github.com/containers/storage/pkg/homedir"
pmount "github.com/containers/storage/pkg/mount"
- "github.com/coreos/go-systemd/v22/activation"
"github.com/coreos/go-systemd/v22/daemon"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
@@ -66,7 +65,6 @@ type ConmonOCIRuntime struct {
supportsJSON bool
supportsKVM bool
supportsNoCgroups bool
- sdNotify bool
enableKeyring bool
}
@@ -105,7 +103,6 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
runtime.logSizeMax = runtimeCfg.Containers.LogSizeMax
runtime.noPivot = runtimeCfg.Engine.NoPivotRoot
runtime.reservePorts = runtimeCfg.Engine.EnablePortReservation
- runtime.sdNotify = runtimeCfg.Engine.SDNotify
runtime.enableKeyring = runtimeCfg.Containers.EnableKeyring
// TODO: probe OCI runtime for feature and enable automatically if
@@ -1050,8 +1047,22 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
}
}
- if ctr.config.PreserveFDs > 0 {
- args = append(args, formatRuntimeOpts("--preserve-fds", fmt.Sprintf("%d", ctr.config.PreserveFDs))...)
+ // Pass down the LISTEN_* environment (see #10443).
+ preserveFDs := ctr.config.PreserveFDs
+ if val := os.Getenv("LISTEN_FDS"); val != "" {
+ if ctr.config.PreserveFDs > 0 {
+ logrus.Warnf("Ignoring LISTEN_FDS to preserve custom user-specified FDs")
+ } else {
+ fds, err := strconv.Atoi(val)
+ if err != nil {
+ return fmt.Errorf("converting LISTEN_FDS=%s: %w", val, err)
+ }
+ preserveFDs = uint(fds)
+ }
+ }
+
+ if preserveFDs > 0 {
+ args = append(args, formatRuntimeOpts("--preserve-fds", fmt.Sprintf("%d", preserveFDs))...)
}
if restoreOptions != nil {
@@ -1104,11 +1115,11 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
}
// 0, 1 and 2 are stdin, stdout and stderr
- conmonEnv, envFiles := r.configureConmonEnv(ctr, runtimeDir)
+ conmonEnv := r.configureConmonEnv(ctr, runtimeDir)
var filesToClose []*os.File
- if ctr.config.PreserveFDs > 0 {
- for fd := 3; fd < int(3+ctr.config.PreserveFDs); fd++ {
+ if preserveFDs > 0 {
+ for fd := 3; fd < int(3+preserveFDs); fd++ {
f := os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd))
filesToClose = append(filesToClose, f)
cmd.ExtraFiles = append(cmd.ExtraFiles, f)
@@ -1118,10 +1129,9 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
cmd.Env = r.conmonEnv
// we don't want to step on users fds they asked to preserve
// Since 0-2 are used for stdio, start the fds we pass in at preserveFDs+3
- cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", ctr.config.PreserveFDs+3), fmt.Sprintf("_OCI_STARTPIPE=%d", ctr.config.PreserveFDs+4))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", preserveFDs+3), fmt.Sprintf("_OCI_STARTPIPE=%d", preserveFDs+4))
cmd.Env = append(cmd.Env, conmonEnv...)
cmd.ExtraFiles = append(cmd.ExtraFiles, childSyncPipe, childStartPipe)
- cmd.ExtraFiles = append(cmd.ExtraFiles, envFiles...)
if r.reservePorts && !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() {
ports, err := bindPorts(ctr.config.PortMappings)
@@ -1225,7 +1235,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
// 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) {
+func (r *ConmonOCIRuntime) configureConmonEnv(ctr *Container, runtimeDir string) []string {
var env []string
for _, e := range os.Environ() {
if strings.HasPrefix(e, "LC_") {
@@ -1240,17 +1250,7 @@ func (r *ConmonOCIRuntime) configureConmonEnv(ctr *Container, runtimeDir string)
env = append(env, fmt.Sprintf("HOME=%s", home))
}
- extraFiles := make([]*os.File, 0)
- if !r.sdNotify {
- if listenfds, ok := os.LookupEnv("LISTEN_FDS"); ok {
- env = append(env, fmt.Sprintf("LISTEN_FDS=%s", listenfds), "LISTEN_PID=1")
- fds := activation.Files(false)
- extraFiles = append(extraFiles, fds...)
- }
- } else {
- logrus.Debug("disabling SD notify")
- }
- return env, extraFiles
+ return env
}
// sharedConmonArgs takes common arguments for exec and create/restore and formats them for the conmon CLI
diff --git a/libpod/options.go b/libpod/options.go
index 0bcd1e3a6..4cbd2b5e2 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/events"
+ netTypes "github.com/containers/podman/v3/libpod/network/types"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/specgen"
@@ -21,7 +22,6 @@ import (
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
"github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -713,7 +713,6 @@ func (r *Runtime) WithPod(pod *Pod) CtrCreateOption {
if pod == nil {
return define.ErrInvalidArg
}
-
ctr.config.Pod = pod.ID()
return nil
@@ -1430,20 +1429,6 @@ func WithRestartRetries(tries uint) CtrCreateOption {
}
}
-// withIsInfra sets the container to be an infra container. This means the container will be sometimes hidden
-// and expected to be the first container in the pod.
-func withIsInfra() CtrCreateOption {
- return func(ctr *Container) error {
- if ctr.valid {
- return define.ErrCtrFinalized
- }
-
- ctr.config.IsInfra = true
-
- return nil
- }
-}
-
// WithNamedVolumes adds the given named volumes to the container.
func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption {
return func(ctr *Container) error {
@@ -1541,6 +1526,20 @@ func WithCreateCommand(cmd []string) CtrCreateOption {
}
}
+// withIsInfra allows us to dfferentiate between infra containers and regular containers
+// within the container config
+func withIsInfra() CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+
+ ctr.config.IsInfra = true
+
+ return nil
+ }
+}
+
// WithCreateWorkingDir tells Podman to create the container's working directory
// if it does not exist.
func WithCreateWorkingDir() CtrCreateOption {
@@ -1812,45 +1811,14 @@ func WithInitCtrType(containerType string) CtrCreateOption {
// Pod Creation Options
-// WithInfraImage sets the infra image for libpod.
-// An infra image is used for inter-container kernel
-// namespace sharing within a pod. Typically, an infra
-// container is lightweight and is there to reap
-// zombie processes within its pid namespace.
-func WithInfraImage(img string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- pod.config.InfraContainer.InfraImage = img
-
- return nil
- }
-}
-
-// WithInfraCommand sets the command to
-// run on pause container start up.
-func WithInfraCommand(cmd []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- pod.config.InfraContainer.InfraCommand = cmd
- return nil
- }
-}
-
-// WithInfraName sets the infra container name for a single pod.
-func WithInfraName(name string) PodCreateOption {
+// WithPodCreateCommand adds the full command plus arguments of the current
+// process to the pod config.
+func WithPodCreateCommand(createCmd []string) PodCreateOption {
return func(pod *Pod) error {
if pod.valid {
return define.ErrPodFinalized
}
-
- pod.config.InfraContainer.InfraName = name
-
+ pod.config.CreateCommand = createCmd
return nil
}
}
@@ -1891,26 +1859,14 @@ func WithPodHostname(hostname string) PodCreateOption {
}
}
-// WithPodCreateCommand adds the full command plus arguments of the current
-// process to the pod config.
-func WithPodCreateCommand(createCmd []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
- pod.config.CreateCommand = createCmd
- return nil
- }
-}
-
// WithInfraConmonPidFile sets the path to a custom conmon PID file for the
// infra container.
-func WithInfraConmonPidFile(path string) PodCreateOption {
+func WithInfraConmonPidFile(path string, infraSpec *specgen.SpecGenerator) PodCreateOption {
return func(pod *Pod) error {
if pod.valid {
return define.ErrPodFinalized
}
- pod.config.InfraContainer.ConmonPidFile = path
+ infraSpec.ConmonPidFile = path
return nil
}
}
@@ -2099,320 +2055,25 @@ func WithInfraContainer() PodCreateOption {
if pod.valid {
return define.ErrPodFinalized
}
-
- pod.config.InfraContainer.HasInfraContainer = true
+ pod.config.HasInfra = true
return nil
}
}
// WithInfraContainerPorts tells the pod to add port bindings to the pause container
-func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set pod ports as no infra container is being created")
- }
- pod.config.InfraContainer.PortBindings = bindings
- return nil
- }
-}
-
-// WithPodStaticIP sets a static IP for the pod.
-func WithPodStaticIP(ip net.IP) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static IP as no infra container is being created")
- }
-
- if pod.config.InfraContainer.HostNetwork {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP if host network is specified")
- }
-
- if len(pod.config.InfraContainer.Networks) > 1 {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if joining more than 1 CNI network")
- }
-
- pod.config.InfraContainer.StaticIP = ip
-
- return nil
- }
-}
-
-// WithPodStaticMAC sets a static MAC address for the pod.
-func WithPodStaticMAC(mac net.HardwareAddr) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static MAC as no infra container is being created")
- }
-
- if pod.config.InfraContainer.HostNetwork {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set static MAC if host network is specified")
- }
-
- if len(pod.config.InfraContainer.Networks) > 1 {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if joining more than 1 CNI network")
- }
-
- pod.config.InfraContainer.StaticMAC = mac
-
- return nil
- }
-}
-
-// WithPodUseImageResolvConf sets a pod to use an image's resolv.conf and not
-// create its own.
-func WithPodUseImageResolvConf() PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
- }
-
- if len(pod.config.InfraContainer.DNSServer) != 0 ||
- len(pod.config.InfraContainer.DNSSearch) != 0 ||
- len(pod.config.InfraContainer.DNSOption) != 0 {
- return errors.Wrapf(define.ErrInvalidArg, "requested use of image resolv.conf conflicts with already-configured DNS settings")
- }
-
- pod.config.InfraContainer.UseImageResolvConf = true
-
- return nil
- }
-}
-
-// WithPodDNS sets the DNS Servers for a pod.
-func WithPodDNS(dnsServer []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
- }
-
- if pod.config.InfraContainer.UseImageResolvConf {
- return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS servers if pod will not create /etc/resolv.conf")
- }
-
- pod.config.InfraContainer.DNSServer = dnsServer
-
- return nil
- }
-}
-
-// WithPodDNSSearch sets the DNS Search domains for a pod.
-func WithPodDNSSearch(dnsSearch []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
- }
-
- if pod.config.InfraContainer.UseImageResolvConf {
- return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS search domains if pod will not create /etc/resolv.conf")
- }
-
- pod.config.InfraContainer.DNSSearch = dnsSearch
-
- return nil
- }
-}
-
-// WithPodDNSOption sets DNS Options for a pod.
-func WithPodDNSOption(dnsOption []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
- }
-
- if pod.config.InfraContainer.UseImageResolvConf {
- return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if pod will not create /etc/resolv.conf")
- }
-
- pod.config.InfraContainer.DNSOption = dnsOption
-
- return nil
- }
-}
-
-// WithPodUseImageHosts tells the pod not to create /etc/hosts and instead to
-// use the one provided by the image.
-func WithPodUseImageHosts() PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created")
- }
-
- if len(pod.config.InfraContainer.HostAdd) != 0 {
- return errors.Wrapf(define.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file")
- }
-
- pod.config.InfraContainer.UseImageHosts = true
-
- return nil
- }
-}
-
-// WithPodHosts adds additional entries to the pod's /etc/hosts
-func WithPodHosts(hosts []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created")
- }
-
- if pod.config.InfraContainer.UseImageHosts {
- return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if container is using image hosts")
- }
-
- pod.config.InfraContainer.HostAdd = hosts
-
- return nil
- }
-}
-
-// WithPodNetworks sets additional CNI networks for the pod to join.
-func WithPodNetworks(networks []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod CNI networks as no infra container is being created")
- }
-
- if (pod.config.InfraContainer.StaticIP != nil || pod.config.InfraContainer.StaticMAC != nil) &&
- len(networks) > 1 {
- return errors.Wrapf(define.ErrInvalidArg, "cannot join more than one CNI network if setting a static IP or MAC address")
- }
-
- if pod.config.InfraContainer.HostNetwork {
- return errors.Wrapf(define.ErrInvalidArg, "cannot join pod to CNI networks if host network is specified")
- }
-
- pod.config.InfraContainer.Networks = networks
-
- return nil
- }
-}
-
-// WithPodNoNetwork tells the pod to disable external networking.
-func WithPodNoNetwork() PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod networking as no infra container is being created")
- }
-
- if len(pod.config.InfraContainer.PortBindings) > 0 ||
- pod.config.InfraContainer.StaticIP != nil ||
- pod.config.InfraContainer.StaticMAC != nil ||
- len(pod.config.InfraContainer.Networks) > 0 ||
- pod.config.InfraContainer.HostNetwork {
- return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified")
- }
-
- pod.config.InfraContainer.NoNetwork = true
-
- return nil
- }
-}
-
-// WithPodHostNetwork tells the pod to use the host's network namespace.
-func WithPodHostNetwork() PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod host networking as no infra container is being created")
- }
-
- if len(pod.config.InfraContainer.PortBindings) > 0 ||
- pod.config.InfraContainer.StaticIP != nil ||
- pod.config.InfraContainer.StaticMAC != nil ||
- len(pod.config.InfraContainer.Networks) > 0 ||
- pod.config.InfraContainer.NoNetwork {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
- }
-
- pod.config.InfraContainer.HostNetwork = true
-
- return nil
- }
-}
-
-// WithPodInfraExitCommand sets an exit command for the pod's infra container.
-// Semantics are identical to WithExitCommand() above - the ID of the container
-// will be appended to the end of the provided command (note that this will
-// specifically be the ID of the infra container *and not the pod's id*.
-func WithPodInfraExitCommand(exitCmd []string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod infra container exit command as no infra container is being created")
- }
-
- pod.config.InfraContainer.ExitCommand = exitCmd
-
- return nil
- }
-}
-
-// WithPodSlirp4netns tells the pod to use slirp4netns.
-func WithPodSlirp4netns(networkOptions map[string][]string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod networking as no infra container is being created")
- }
- if pod.config.InfraContainer.HostNetwork {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set both HostNetwork and Slirp4netns")
- }
- pod.config.InfraContainer.Slirp4netns = true
- pod.config.InfraContainer.NetworkOptions = networkOptions
-
- return nil
+func WithInfraContainerPorts(bindings []ocicni.PortMapping, infraSpec *specgen.SpecGenerator) []netTypes.PortMapping {
+ bindingSpec := []netTypes.PortMapping{}
+ for _, bind := range bindings {
+ currBind := netTypes.PortMapping{}
+ currBind.ContainerPort = uint16(bind.ContainerPort)
+ currBind.HostIP = bind.HostIP
+ currBind.HostPort = uint16(bind.HostPort)
+ currBind.Protocol = bind.Protocol
+ bindingSpec = append(bindingSpec, currBind)
}
+ infraSpec.PortMappings = bindingSpec
+ return infraSpec.PortMappings
}
// WithVolatile sets the volatile flag for the container storage.
@@ -2428,78 +2089,3 @@ func WithVolatile() CtrCreateOption {
return nil
}
}
-
-// WithPodUserns sets the userns for the infra container in a pod.
-func WithPodUserns(userns specgen.Namespace) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
-
- if !pod.config.InfraContainer.HasInfraContainer {
- return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod userns as no infra container is being created")
- }
-
- pod.config.InfraContainer.Userns = userns
-
- return nil
- }
-}
-
-// WithPodCPUPAQ takes the given cpu period and quota and inserts them in the proper place.
-func WithPodCPUPAQ(period uint64, quota int64) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
- if pod.CPUPeriod() != 0 && pod.CPUQuota() != 0 {
- pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{
- Period: &period,
- Quota: &quota,
- }
- } else {
- pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{}
- pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{
- Period: &period,
- Quota: &quota,
- }
- }
- return nil
- }
-}
-
-// WithPodCPUSetCPUS computes and sets the Cpus linux resource string which determines the amount of cores, from those available, we are allowed to execute on
-func WithPodCPUSetCPUs(inp string) PodCreateOption {
- return func(pod *Pod) error {
- if pod.valid {
- return define.ErrPodFinalized
- }
- if pod.ResourceLim().CPU.Period != nil {
- pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp
- } else {
- pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{}
- pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{}
- pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp
- }
- return nil
- }
-}
-
-func WithPodPidNS(inp specgen.Namespace) PodCreateOption {
- return func(p *Pod) error {
- if p.valid {
- return define.ErrPodFinalized
- }
- if p.config.UsePodPID {
- switch inp.NSMode {
- case "container":
- return errors.Wrap(define.ErrInvalidArg, "Cannot take container in a different NS as an argument")
- case "host":
- p.config.UsePodPID = false
- }
- p.config.InfraContainer.PidNS = inp
- }
-
- return nil
- }
-}
diff --git a/libpod/pod.go b/libpod/pod.go
index 7df15df7b..e4516b354 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -2,14 +2,12 @@ package libpod
import (
"context"
- "net"
+ "fmt"
"sort"
"time"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/lock"
- "github.com/containers/podman/v3/pkg/specgen"
- "github.com/cri-o/ocicni/pkg/ocicni"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@@ -63,7 +61,7 @@ type PodConfig struct {
UsePodUTS bool `json:"sharesUts,omitempty"`
UsePodCgroupNS bool `json:"sharesCgroupNS,omitempty"`
- InfraContainer *InfraContainerConfig `json:"infraConfig"`
+ HasInfra bool `json:"hasInfra,omitempty"`
// Time pod was created
CreatedTime time.Time `json:"created"`
@@ -85,41 +83,6 @@ type podState struct {
InfraContainerID string
}
-// InfraContainerConfig is the configuration for the pod's infra container.
-// Generally speaking, these are equivalent to container configuration options
-// you will find in container_config.go (and even named identically), save for
-// HasInfraContainer (which determines if an infra container is even created -
-// if it is false, no other options in this struct will be used) and HostNetwork
-// (this involves the created OCI spec, and as such is not represented directly
-// in container_config.go).
-// Generally speaking, aside from those two exceptions, these options will set
-// the equivalent field in the container's configuration.
-type InfraContainerConfig struct {
- ConmonPidFile string `json:"conmonPidFile"`
- HasInfraContainer bool `json:"makeInfraContainer"`
- NoNetwork bool `json:"noNetwork,omitempty"`
- HostNetwork bool `json:"infraHostNetwork,omitempty"`
- PidNS specgen.Namespace `json:"infraPid,omitempty"`
- PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
- StaticIP net.IP `json:"staticIP,omitempty"`
- StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
- UseImageResolvConf bool `json:"useImageResolvConf,omitempty"`
- DNSServer []string `json:"dnsServer,omitempty"`
- DNSSearch []string `json:"dnsSearch,omitempty"`
- DNSOption []string `json:"dnsOption,omitempty"`
- UseImageHosts bool `json:"useImageHosts,omitempty"`
- HostAdd []string `json:"hostsAdd,omitempty"`
- Networks []string `json:"networks,omitempty"`
- ExitCommand []string `json:"exitCommand,omitempty"`
- InfraImage string `json:"infraImage,omitempty"`
- InfraCommand []string `json:"infraCommand,omitempty"`
- InfraName string `json:"infraName,omitempty"`
- Slirp4netns bool `json:"slirp4netns,omitempty"`
- NetworkOptions map[string][]string `json:"network_options,omitempty"`
- ResourceLimits *specs.LinuxResources `json:"resource_limits,omitempty"`
- Userns specgen.Namespace `json:"userns,omitempty"`
-}
-
// ID retrieves the pod's ID
func (p *Pod) ID() string {
return p.config.ID
@@ -139,45 +102,104 @@ func (p *Pod) Namespace() string {
// ResourceLim returns the cpuset resource limits for the pod
func (p *Pod) ResourceLim() *specs.LinuxResources {
resCopy := &specs.LinuxResources{}
- if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
+ empty := &specs.LinuxResources{
+ CPU: &specs.LinuxCPU{},
+ }
+ infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
+ if err != nil {
+ return empty
+ }
+ conf := infra.config.Spec
+ if err != nil {
+ return empty
+ }
+ if conf.Linux == nil || conf.Linux.Resources == nil {
+ return empty
+ }
+ if err = JSONDeepCopy(conf.Linux.Resources, resCopy); err != nil {
return nil
}
- if resCopy != nil && resCopy.CPU != nil {
+ if resCopy.CPU != nil {
return resCopy
}
- empty := &specs.LinuxResources{
- CPU: &specs.LinuxCPU{},
- }
+
return empty
}
// CPUPeriod returns the pod CPU period
func (p *Pod) CPUPeriod() uint64 {
- resCopy := &specs.LinuxResources{}
- if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
+ if p.state.InfraContainerID == "" {
return 0
}
- if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Period != nil {
- return *resCopy.CPU.Period
+ infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
+ if err != nil {
+ return 0
+ }
+ conf := infra.config.Spec
+ if conf != nil && conf.Linux != nil && conf.Linux.Resources != nil && conf.Linux.Resources.CPU != nil && conf.Linux.Resources.CPU.Period != nil {
+ return *conf.Linux.Resources.CPU.Period
}
return 0
}
// CPUQuota returns the pod CPU quota
func (p *Pod) CPUQuota() int64 {
- resCopy := &specs.LinuxResources{}
- if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
+ if p.state.InfraContainerID == "" {
+ return 0
+ }
+ infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
+ if err != nil {
return 0
}
- if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Quota != nil {
- return *resCopy.CPU.Quota
+ conf := infra.config.Spec
+ if conf != nil && conf.Linux != nil && conf.Linux.Resources != nil && conf.Linux.Resources.CPU != nil && conf.Linux.Resources.CPU.Quota != nil {
+ return *conf.Linux.Resources.CPU.Quota
}
return 0
}
// PidMode returns the PID mode given by the user ex: pod, private...
func (p *Pod) PidMode() string {
- return string(p.config.InfraContainer.PidNS.NSMode)
+ infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
+ if err != nil {
+ return ""
+ }
+ conf := infra.Config()
+ ctrSpec := conf.Spec
+ if ctrSpec != nil && ctrSpec.Linux != nil {
+ for _, ns := range ctrSpec.Linux.Namespaces {
+ if ns.Type == specs.PIDNamespace {
+ if ns.Path != "" {
+ return fmt.Sprintf("ns:%s", ns.Path)
+ }
+ return "private"
+ }
+ }
+ return "host"
+ }
+ return ""
+}
+
+// PidMode returns the PID mode given by the user ex: pod, private...
+func (p *Pod) UserNSMode() string {
+ infra, err := p.infraContainer()
+ if err != nil {
+ return ""
+ }
+ conf := infra.Config()
+ ctrSpec := conf.Spec
+ if ctrSpec != nil && ctrSpec.Linux != nil {
+ for _, ns := range ctrSpec.Linux.Namespaces {
+ if ns.Type == specs.UserNamespace {
+ if ns.Path != "" {
+ return fmt.Sprintf("ns:%s", ns.Path)
+ }
+ return "private"
+ }
+ }
+ return "host"
+ }
+ return ""
}
// Labels returns the pod's labels
@@ -263,20 +285,24 @@ func (p *Pod) CgroupPath() (string, error) {
if p.state.CgroupPath != "" {
return p.state.CgroupPath, nil
}
- if !p.HasInfraContainer() {
+ if p.state.InfraContainerID == "" {
return "", errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
}
- id := p.state.InfraContainerID
+ id, err := p.infraContainerID()
+ if err != nil {
+ return "", err
+ }
if id != "" {
- ctr, err := p.runtime.state.Container(id)
+ ctr, err := p.infraContainer()
if err != nil {
return "", errors.Wrapf(err, "could not get infra")
}
if ctr != nil {
- ctr.Start(context.Background(), false)
+ ctr.Start(context.Background(), true)
cgroupPath, err := ctr.CGroupPath()
+ fmt.Println(cgroupPath)
if err != nil {
return "", errors.Wrapf(err, "could not get container cgroup")
}
@@ -325,7 +351,7 @@ func (p *Pod) allContainers() ([]*Container, error) {
// HasInfraContainer returns whether the pod will create an infra container
func (p *Pod) HasInfraContainer() bool {
- return p.config.InfraContainer.HasInfraContainer
+ return p.config.HasInfra
}
// SharesNamespaces checks if the pod has any kernel namespaces set as shared. An infra container will not be
@@ -350,19 +376,26 @@ func (p *Pod) InfraContainerID() (string, error) {
return p.infraContainerID()
}
-// InfraContainer returns the infra container.
-func (p *Pod) InfraContainer() (*Container, error) {
- if !p.HasInfraContainer() {
- return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
- }
- id, err := p.InfraContainerID()
+// infraContainer is the unlocked versio of InfraContainer which returns the infra container
+func (p *Pod) infraContainer() (*Container, error) {
+ id, err := p.infraContainerID()
if err != nil {
return nil, err
}
+ if id == "" {
+ return nil, errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
+ }
return p.runtime.state.Container(id)
}
+// InfraContainer returns the infra container.
+func (p *Pod) InfraContainer() (*Container, error) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+ return p.infraContainer()
+}
+
// TODO add pod batching
// Lock pod to avoid lock contention
// Store and lock all containers (no RemoveContainer in batch guarantees cache will not become stale)
@@ -412,13 +445,7 @@ func (p *Pod) ProcessLabel() (string, error) {
if !p.HasInfraContainer() {
return "", nil
}
-
- id, err := p.InfraContainerID()
- if err != nil {
- return "", err
- }
-
- ctr, err := p.runtime.state.Container(id)
+ ctr, err := p.infraContainer()
if err != nil {
return "", err
}
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 53fb9538f..5f4d983b9 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -582,41 +582,46 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
// Infra config contains detailed information on the pod's infra
// container.
var infraConfig *define.InspectPodInfraConfig
- if p.config.InfraContainer != nil && p.config.InfraContainer.HasInfraContainer {
+ if p.state.InfraContainerID != "" {
+ infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
+ if err != nil {
+ return nil, err
+ }
infraConfig = new(define.InspectPodInfraConfig)
- infraConfig.HostNetwork = p.config.InfraContainer.HostNetwork
- infraConfig.StaticIP = p.config.InfraContainer.StaticIP
- infraConfig.StaticMAC = p.config.InfraContainer.StaticMAC.String()
- infraConfig.NoManageResolvConf = p.config.InfraContainer.UseImageResolvConf
- infraConfig.NoManageHosts = p.config.InfraContainer.UseImageHosts
+ infraConfig.HostNetwork = !infra.Config().ContainerNetworkConfig.UseImageHosts
+ infraConfig.StaticIP = infra.Config().ContainerNetworkConfig.StaticIP
+ infraConfig.NoManageResolvConf = infra.Config().UseImageResolvConf
+ infraConfig.NoManageHosts = infra.Config().UseImageHosts
infraConfig.CPUPeriod = p.CPUPeriod()
infraConfig.CPUQuota = p.CPUQuota()
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
infraConfig.PidNS = p.PidMode()
- infraConfig.UserNS = p.config.InfraContainer.Userns.String()
+ infraConfig.UserNS = p.UserNSMode()
- if len(p.config.InfraContainer.DNSServer) > 0 {
- infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
- infraConfig.DNSServer = append(infraConfig.DNSServer, p.config.InfraContainer.DNSServer...)
+ if len(infra.Config().ContainerNetworkConfig.DNSServer) > 0 {
+ infraConfig.DNSServer = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSServer))
+ for _, entry := range infra.Config().ContainerNetworkConfig.DNSServer {
+ infraConfig.DNSServer = append(infraConfig.DNSServer, entry.String())
+ }
}
- if len(p.config.InfraContainer.DNSSearch) > 0 {
- infraConfig.DNSSearch = make([]string, 0, len(p.config.InfraContainer.DNSSearch))
- infraConfig.DNSSearch = append(infraConfig.DNSSearch, p.config.InfraContainer.DNSSearch...)
+ if len(infra.Config().ContainerNetworkConfig.DNSSearch) > 0 {
+ infraConfig.DNSSearch = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSSearch))
+ infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.Config().ContainerNetworkConfig.DNSSearch...)
}
- if len(p.config.InfraContainer.DNSOption) > 0 {
- infraConfig.DNSOption = make([]string, 0, len(p.config.InfraContainer.DNSOption))
- infraConfig.DNSOption = append(infraConfig.DNSOption, p.config.InfraContainer.DNSOption...)
+ if len(infra.Config().ContainerNetworkConfig.DNSOption) > 0 {
+ infraConfig.DNSOption = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSOption))
+ infraConfig.DNSOption = append(infraConfig.DNSOption, infra.Config().ContainerNetworkConfig.DNSOption...)
}
- if len(p.config.InfraContainer.HostAdd) > 0 {
- infraConfig.HostAdd = make([]string, 0, len(p.config.InfraContainer.HostAdd))
- infraConfig.HostAdd = append(infraConfig.HostAdd, p.config.InfraContainer.HostAdd...)
+ if len(infra.Config().HostAdd) > 0 {
+ infraConfig.HostAdd = make([]string, 0, len(infra.Config().HostAdd))
+ infraConfig.HostAdd = append(infraConfig.HostAdd, infra.Config().HostAdd...)
}
- if len(p.config.InfraContainer.Networks) > 0 {
- infraConfig.Networks = make([]string, 0, len(p.config.InfraContainer.Networks))
- infraConfig.Networks = append(infraConfig.Networks, p.config.InfraContainer.Networks...)
+ if len(infra.Config().ContainerNetworkConfig.Networks) > 0 {
+ infraConfig.Networks = make([]string, 0, len(infra.Config().ContainerNetworkConfig.Networks))
+ infraConfig.Networks = append(infraConfig.Networks, infra.Config().ContainerNetworkConfig.Networks...)
}
- infraConfig.NetworkOptions = p.config.InfraContainer.NetworkOptions
- infraConfig.PortBindings = makeInspectPortBindings(p.config.InfraContainer.PortBindings, nil)
+ infraConfig.NetworkOptions = infra.Config().ContainerNetworkConfig.NetworkOptions
+ infraConfig.PortBindings = makeInspectPortBindings(infra.Config().ContainerNetworkConfig.PortMappings, nil)
}
inspectData := define.InspectPodData{
diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go
index e81bd7b16..079b631a0 100644
--- a/libpod/pod_internal.go
+++ b/libpod/pod_internal.go
@@ -20,7 +20,7 @@ func newPod(runtime *Runtime) *Pod {
pod.config.ID = stringid.GenerateNonCryptoID()
pod.config.Labels = make(map[string]string)
pod.config.CreatedTime = time.Now()
- pod.config.InfraContainer = new(InfraContainerConfig)
+ // pod.config.InfraContainer = new(ContainerConfig)
pod.state = new(podState)
pod.runtime = runtime
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 52072b0f3..7d3891f6e 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/domain/entities/reports"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
"github.com/docker/go-units"
@@ -38,12 +39,15 @@ type CtrCreateOption func(*Container) error
type ContainerFilter func(*Container) bool
// NewContainer creates a new container from a given OCI config.
-func (r *Runtime) NewContainer(ctx context.Context, rSpec *spec.Spec, options ...CtrCreateOption) (*Container, error) {
+func (r *Runtime) NewContainer(ctx context.Context, rSpec *spec.Spec, spec *specgen.SpecGenerator, infra bool, options ...CtrCreateOption) (*Container, error) {
r.lock.Lock()
defer r.lock.Unlock()
if !r.valid {
return nil, define.ErrRuntimeStopped
}
+ if infra {
+ options = append(options, withIsInfra())
+ }
return r.newContainer(ctx, rSpec, options...)
}
@@ -172,6 +176,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
}
ctr.config.ShmSize = size
ctr.config.StopSignal = 15
+
ctr.config.StopTimeout = r.config.Engine.StopTimeout
} else {
// This is a restore from an imported checkpoint
@@ -211,7 +216,11 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
}
func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ...CtrCreateOption) (*Container, error) {
- ctr, err := r.initContainerVariables(rSpec, nil)
+ var ctr *Container
+ var err error
+
+ ctr, err = r.initContainerVariables(rSpec, nil)
+
if err != nil {
return nil, errors.Wrapf(err, "error initializing container variables")
}
@@ -230,7 +239,9 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
if err := ctr.validate(); err != nil {
return nil, err
}
-
+ if ctr.config.IsInfra {
+ ctr.config.StopTimeout = 10
+ }
// normalize the networks to names
// ocicni only knows about cni names so we have to make
// sure we do not use ids internally
@@ -327,7 +338,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
switch r.config.Engine.CgroupManager {
case config.CgroupfsCgroupsManager:
if ctr.config.CgroupParent == "" {
- if pod != nil && pod.config.UsePodCgroup {
+ if pod != nil && pod.config.UsePodCgroup && !ctr.IsInfra() {
podCgroup, err := pod.CgroupPath()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID())
@@ -348,7 +359,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
case config.SystemdCgroupsManager:
if ctr.config.CgroupParent == "" {
switch {
- case pod != nil && pod.config.UsePodCgroup:
+ case pod != nil && pod.config.UsePodCgroup && !ctr.IsInfra():
podCgroup, err := pod.CgroupPath()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID())
@@ -833,7 +844,10 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol
return id, err
}
- infraID := pod.state.InfraContainerID
+ infraID, err := pod.infraContainerID()
+ if err != nil {
+ return "", err
+ }
if c.ID() == infraID {
return id, errors.Errorf("container %s is the infra container of pod %s and cannot be removed without removing the pod", c.ID(), pod.ID())
}
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
deleted file mode 100644
index 9236fb1f5..000000000
--- a/libpod/runtime_pod_infra_linux.go
+++ /dev/null
@@ -1,284 +0,0 @@
-// +build linux
-
-package libpod
-
-import (
- "context"
- "strings"
-
- "github.com/containers/common/pkg/config"
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/pkg/namespaces"
- "github.com/containers/podman/v3/pkg/rootless"
- "github.com/containers/podman/v3/pkg/specgen"
- "github.com/containers/podman/v3/pkg/util"
- v1 "github.com/opencontainers/image-spec/specs-go/v1"
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/opencontainers/runtime-tools/generate"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-const (
- // IDTruncLength is the length of the pod's id that will be used to make the
- // infra container name
- IDTruncLength = 12
-)
-
-func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawImageName, imgID string, config *v1.ImageConfig) (*Container, error) {
- // Set up generator for infra container defaults
- g, err := generate.New("linux")
- if err != nil {
- return nil, err
- }
-
- // Set Pod hostname
- g.Config.Hostname = p.config.Hostname
-
- var options []CtrCreateOption
-
- // Command: If user-specified, use that preferentially.
- // If not set and the config file is set, fall back to that.
- var infraCtrCommand []string
- if p.config.InfraContainer.InfraCommand != nil {
- logrus.Debugf("User-specified infra container entrypoint %v", p.config.InfraContainer.InfraCommand)
- infraCtrCommand = p.config.InfraContainer.InfraCommand
- } else if r.config.Engine.InfraCommand != "" {
- logrus.Debugf("Config-specified infra container entrypoint %s", r.config.Engine.InfraCommand)
- infraCtrCommand = []string{r.config.Engine.InfraCommand}
- }
- // Only if set by the user or containers.conf, we set entrypoint for the
- // infra container.
- // This is only used by commit, so it shouldn't matter... But someone
- // may eventually want to commit an infra container?
- // TODO: Should we actually do this if set by containers.conf?
- if infraCtrCommand != nil {
- // Need to duplicate the array - we are going to add Cmd later
- // so the current array will be changed.
- newArr := make([]string, 0, len(infraCtrCommand))
- newArr = append(newArr, infraCtrCommand...)
- options = append(options, WithEntrypoint(newArr))
- }
-
- isRootless := rootless.IsRootless()
-
- // I've seen circumstances where config is being passed as nil.
- // Let's err on the side of safety and make sure it's safe to use.
- if config != nil {
- if infraCtrCommand == nil {
- // If we have no entrypoint and command from the image,
- // we can't go on - the infra container has no command.
- if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 {
- return nil, errors.Errorf("infra container has no command")
- }
- if len(config.Entrypoint) > 0 {
- infraCtrCommand = config.Entrypoint
- } else {
- // Use the Docker default "/bin/sh -c"
- // entrypoint, as we're overriding command.
- // If an image doesn't want this, it can
- // override entrypoint too.
- infraCtrCommand = []string{"/bin/sh", "-c"}
- }
- }
- if len(config.Cmd) > 0 {
- infraCtrCommand = append(infraCtrCommand, config.Cmd...)
- }
-
- if len(config.Env) > 0 {
- for _, nameValPair := range config.Env {
- nameValSlice := strings.Split(nameValPair, "=")
- if len(nameValSlice) < 2 {
- return nil, errors.Errorf("Invalid environment variable structure in pause image")
- }
- g.AddProcessEnv(nameValSlice[0], nameValSlice[1])
- }
- }
-
- switch {
- case p.config.InfraContainer.HostNetwork:
- if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
- return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID())
- }
- case p.config.InfraContainer.NoNetwork:
- // Do nothing - we have a network namespace by default,
- // but should not configure slirp.
- default:
- // Since user namespace sharing is not implemented, we only need to check if it's rootless
- netmode := "bridge"
- if p.config.InfraContainer.Slirp4netns {
- netmode = "slirp4netns"
- if len(p.config.InfraContainer.NetworkOptions) != 0 {
- options = append(options, WithNetworkOptions(p.config.InfraContainer.NetworkOptions))
- }
- }
- // FIXME allow pods to have exposed ports
- options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, nil, !p.config.InfraContainer.Userns.IsHost(), netmode, p.config.InfraContainer.Networks))
- }
-
- // For each option in InfraContainerConfig - if set, pass into
- // the infra container we're creating with the appropriate
- // With... option.
- if p.config.InfraContainer.StaticIP != nil {
- options = append(options, WithStaticIP(p.config.InfraContainer.StaticIP))
- }
- if p.config.InfraContainer.StaticMAC != nil {
- options = append(options, WithStaticMAC(p.config.InfraContainer.StaticMAC))
- }
- if p.config.InfraContainer.UseImageResolvConf {
- options = append(options, WithUseImageResolvConf())
- }
- if len(p.config.InfraContainer.DNSServer) > 0 {
- options = append(options, WithDNS(p.config.InfraContainer.DNSServer))
- }
- if len(p.config.InfraContainer.DNSSearch) > 0 {
- options = append(options, WithDNSSearch(p.config.InfraContainer.DNSSearch))
- }
- if len(p.config.InfraContainer.DNSOption) > 0 {
- options = append(options, WithDNSOption(p.config.InfraContainer.DNSOption))
- }
- if p.config.InfraContainer.UseImageHosts {
- options = append(options, WithUseImageHosts())
- }
- if len(p.config.InfraContainer.HostAdd) > 0 {
- options = append(options, WithHosts(p.config.InfraContainer.HostAdd))
- }
- if len(p.config.InfraContainer.ExitCommand) > 0 {
- options = append(options, WithExitCommand(p.config.InfraContainer.ExitCommand))
- }
-
- if p.config.UsePodPID && p.config.InfraContainer.PidNS.NSMode != "host" {
- g.AddOrReplaceLinuxNamespace(string(spec.LinuxNamespaceType("pid")), p.config.InfraContainer.PidNS.Value)
- } else if p.config.InfraContainer.PidNS.NSMode == "host" {
- newNS := []spec.LinuxNamespace{}
- for _, entry := range g.Config.Linux.Namespaces {
- if entry.Type != spec.LinuxNamespaceType("pid") {
- newNS = append(newNS, entry)
- }
- }
- g.Config.Linux.Namespaces = newNS
- }
- }
-
- for _, ctl := range r.config.Containers.DefaultSysctls {
- sysctl := strings.SplitN(ctl, "=", 2)
- if len(sysctl) < 2 {
- return nil, errors.Errorf("invalid default sysctl %s", ctl)
- }
-
- // Ignore net sysctls if --net=host
- if p.config.InfraContainer.HostNetwork && strings.HasPrefix(sysctl[0], "net.") {
- logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace set to host", sysctl[0], sysctl[1])
- continue
- }
-
- g.AddLinuxSysctl(sysctl[0], sysctl[1])
- }
-
- g.SetRootReadonly(true)
- g.SetProcessArgs(infraCtrCommand)
-
- logrus.Debugf("Using %q as infra container command", infraCtrCommand)
-
- mapopt, err := util.ParseIDMapping(namespaces.UsernsMode(p.config.InfraContainer.Userns.String()), []string{}, []string{}, "", "")
- if err != nil {
- return nil, err
- }
- user, err := specgen.SetupUserNS(mapopt, p.config.InfraContainer.Userns, &g)
- if err != nil {
- return nil, err
- }
- if user != "" {
- options = append(options, WithUser(user))
- }
-
- g.RemoveMount("/dev/shm")
- if isRootless {
- g.RemoveMount("/dev/pts")
- devPts := spec.Mount{
- Destination: "/dev/pts",
- Type: "devpts",
- Source: "devpts",
- Options: []string{"private", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
- }
- g.AddMount(devPts)
- }
-
- // Add default sysctls from containers.conf
- defaultSysctls, err := util.ValidateSysctls(r.config.Sysctls())
- if err != nil {
- return nil, err
- }
- for sysctlKey, sysctlVal := range defaultSysctls {
- // Ignore mqueue sysctls if not sharing IPC
- if !p.config.UsePodIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
- logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace for pod is unused", sysctlKey, sysctlVal)
- continue
- }
-
- // Ignore net sysctls if host network or not sharing network
- if (p.config.InfraContainer.HostNetwork || !p.config.UsePodNet) && strings.HasPrefix(sysctlKey, "net.") {
- logrus.Infof("Sysctl %s=%s ignored in containers.conf, since Network Namespace for pod is unused", sysctlKey, sysctlVal)
- continue
- }
-
- // Ignore uts sysctls if not sharing UTS
- if !p.config.UsePodUTS && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) {
- logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace for pod is unused", sysctlKey, sysctlVal)
- continue
- }
- g.AddLinuxSysctl(sysctlKey, sysctlVal)
- }
-
- containerName := p.config.InfraContainer.InfraName
- if containerName == "" {
- containerName = p.ID()[:IDTruncLength] + "-infra"
- }
- logrus.Infof("Infra container name %s", containerName)
- options = append(options, r.WithPod(p))
- options = append(options, WithRootFSFromImage(imgID, imgName, rawImageName))
- options = append(options, WithName(containerName))
- options = append(options, withIsInfra())
- options = append(options, WithIDMappings(*mapopt))
- if len(p.config.InfraContainer.ConmonPidFile) > 0 {
- options = append(options, WithConmonPidFile(p.config.InfraContainer.ConmonPidFile))
- }
- newRes := new(spec.LinuxResources)
- newRes.CPU = new(spec.LinuxCPU)
- newRes.CPU = p.ResourceLim().CPU
- g.Config.Linux.Resources.CPU = newRes.CPU
-
- return r.newContainer(ctx, g.Config, options...)
-}
-
-// createInfraContainer wrap creates an infra container for a pod.
-// An infra container becomes the basis for kernel namespace sharing between
-// containers in the pod.
-func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container, error) {
- if !r.valid {
- return nil, define.ErrRuntimeStopped
- }
- imageName := p.config.InfraContainer.InfraImage
- if imageName == "" {
- imageName = r.config.Engine.InfraImage
- }
-
- pulledImages, err := r.LibimageRuntime().Pull(ctx, imageName, config.PullPolicyMissing, nil)
- if err != nil {
- return nil, errors.Wrap(err, "error pulling infra-container image")
- }
-
- newImage := pulledImages[0]
- data, err := newImage.Inspect(ctx, false)
- if err != nil {
- return nil, err
- }
-
- imageName = "none"
- if len(newImage.Names()) > 0 {
- imageName = newImage.Names()[0]
- }
- imageID := data.ID
-
- return r.makeInfraContainer(ctx, p, imageName, r.config.Engine.InfraImage, imageID, data.Config)
-}
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index fce3f38a7..7571fdfff 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -14,13 +14,14 @@ import (
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/specgen"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// NewPod makes a new, empty pod
-func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Pod, deferredErr error) {
+func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, options ...PodCreateOption) (_ *Pod, deferredErr error) {
r.lock.Lock()
defer r.lock.Unlock()
@@ -50,8 +51,8 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
pod.config.Name = name
}
- if pod.config.Hostname == "" {
- pod.config.Hostname = pod.config.Name
+ if p.InfraContainerSpec != nil && p.InfraContainerSpec.Hostname == "" {
+ p.InfraContainerSpec.Hostname = pod.config.Name
}
// Allocate a lock for the pod
@@ -88,6 +89,9 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
// launch should do it for us
if pod.config.UsePodCgroup {
pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
+ if p.InfraContainerSpec != nil {
+ p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
+ }
}
}
case config.SystemdCgroupsManager:
@@ -108,6 +112,9 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
return nil, errors.Wrapf(err, "unable to create pod cgroup for pod %s", pod.ID())
}
pod.state.CgroupPath = cgroupPath
+ if p.InfraContainerSpec != nil {
+ p.InfraContainerSpec.CgroupParent = pod.state.CgroupPath
+ }
}
default:
return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager)
@@ -127,28 +134,40 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
if err := r.state.AddPod(pod); err != nil {
return nil, errors.Wrapf(err, "error adding pod to state")
}
- defer func() {
- if deferredErr != nil {
- if err := r.removePod(ctx, pod, true, true); err != nil {
- logrus.Errorf("Error removing pod after pause container creation failure: %v", err)
- }
- }
- }()
+ return pod, nil
+}
- if pod.HasInfraContainer() {
- ctr, err := r.createInfraContainer(ctx, pod)
- if err != nil {
- return nil, errors.Wrapf(err, "error adding Infra Container")
- }
- pod.state.InfraContainerID = ctr.ID()
- if err := pod.save(); err != nil {
- return nil, err
- }
+// AddInfra adds the created infra container to the pod state
+func (r *Runtime) AddInfra(ctx context.Context, pod *Pod, infraCtr *Container) (*Pod, error) {
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ if !r.valid {
+ return nil, define.ErrRuntimeStopped
+ }
+ pod.state.InfraContainerID = infraCtr.ID()
+ if err := pod.save(); err != nil {
+ return nil, err
}
pod.newPodEvent(events.Create)
return pod, nil
}
+// SavePod is a helper function to save the pod state from outside of libpod
+func (r *Runtime) SavePod(pod *Pod) error {
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ if !r.valid {
+ return define.ErrRuntimeStopped
+ }
+ if err := pod.save(); err != nil {
+ return err
+ }
+ pod.newPodEvent(events.Create)
+ return nil
+}
+
func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) error {
if err := p.updatePod(); err != nil {
return err