summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go3
-rw-r--r--libpod/container_api.go5
-rw-r--r--libpod/container_internal.go18
-rw-r--r--libpod/container_internal_linux.go44
-rw-r--r--libpod/events/config.go10
-rw-r--r--libpod/events/journal_linux.go24
-rw-r--r--libpod/events/logfile.go5
-rw-r--r--libpod/events/nullout.go8
-rw-r--r--libpod/info.go2
-rw-r--r--libpod/oci_internal_linux.go4
-rw-r--r--libpod/runtime.go23
-rw-r--r--libpod/runtime_ctr.go2
12 files changed, 104 insertions, 44 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 2d96b1120..9c01d2adf 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -377,6 +377,9 @@ type ContainerConfig struct {
RestartRetries uint `json:"restart_retries,omitempty"`
// TODO log options for log drivers
+ // PostConfigureNetNS needed when a user namespace is created by an OCI runtime
+ // if the network namespace is created before the user namespace it will be
+ // owned by the wrong user namespace.
PostConfigureNetNS bool `json:"postConfigureNetNS"`
// OCIRuntime used to create the container
diff --git a/libpod/container_api.go b/libpod/container_api.go
index ef9c3f006..abcfcb271 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -773,6 +773,11 @@ type ContainerCheckpointOptions struct {
// IgnoreRootfs tells the API to not export changes to
// the container's root file-system (or to not import)
IgnoreRootfs bool
+ // IgnoreStaticIP tells the API to ignore the IP set
+ // during 'podman run' with '--ip'. This is especially
+ // important to be able to restore a container multiple
+ // times with '--import --name'.
+ IgnoreStaticIP bool
}
// Checkpoint checkpoints a container
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index aba9c5b93..313f67963 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1152,9 +1152,27 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
c.newContainerEvent(events.Restart)
if c.state.State == define.ContainerStateRunning {
+ conmonPID := c.state.ConmonPID
if err := c.stop(timeout); err != nil {
return err
}
+ // Old versions of conmon have a bug where they create the exit file before
+ // closing open file descriptors causing a race condition when restarting
+ // containers with open ports since we cannot bind the ports as they're not
+ // yet closed by conmon.
+ //
+ // Killing the old conmon PID is ~okay since it forces the FDs of old conmons
+ // to be closed, while it's a NOP for newer versions which should have
+ // exited already.
+ if conmonPID != 0 {
+ // Ignore errors from FindProcess() as conmon could already have exited.
+ p, err := os.FindProcess(conmonPID)
+ if p != nil && err == nil {
+ if err = p.Kill(); err != nil {
+ logrus.Debugf("error killing conmon process: %v", err)
+ }
+ }
+ }
}
defer func() {
if err != nil {
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 6dbd53fbf..5aa4ee9a9 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -471,9 +471,9 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
return err
}
- g.RemoveMount("/sys/fs/cgroup")
-
if unified {
+ g.RemoveMount("/sys/fs/cgroup")
+
sourcePath := filepath.Join("/sys/fs/cgroup")
systemdMnt := spec.Mount{
Destination: "/sys/fs/cgroup",
@@ -483,31 +483,13 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
}
g.AddMount(systemdMnt)
} else {
- // rootless containers have no write access to /sys/fs/cgroup, so don't
- // add any mount into the container.
- if !rootless.IsRootless() {
- cgroupPath, err := c.CGroupPath()
- if err != nil {
- return err
- }
- sourcePath := filepath.Join("/sys/fs/cgroup", cgroupPath)
-
- systemdMnt := spec.Mount{
- Destination: "/sys/fs/cgroup",
- Type: "bind",
- Source: sourcePath,
- Options: []string{"bind", "private"},
- }
- g.AddMount(systemdMnt)
- } else {
- systemdMnt := spec.Mount{
- Destination: "/sys/fs/cgroup",
- Type: "bind",
- Source: "/sys/fs/cgroup",
- Options: []string{"bind", "nodev", "noexec", "nosuid"},
- }
- g.AddMount(systemdMnt)
+ systemdMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup/systemd",
+ Type: "bind",
+ Source: "/sys/fs/cgroup/systemd",
+ Options: []string{"bind", "nodev", "noexec", "nosuid"},
}
+ g.AddMount(systemdMnt)
}
return nil
@@ -743,6 +725,14 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return err
}
+ // If a container is restored multiple times from an exported checkpoint with
+ // the help of '--import --name', the restore will fail if during 'podman run'
+ // a static container IP was set with '--ip'. The user can tell the restore
+ // process to ignore the static IP with '--ignore-static-ip'
+ if options.IgnoreStaticIP {
+ c.config.StaticIP = nil
+ }
+
// Read network configuration from checkpoint
// Currently only one interface with one IP is supported.
networkStatusFile, err := os.Open(filepath.Join(c.bundlePath(), "network.status"))
@@ -752,7 +742,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
// TODO: This implicit restoring with or without IP depending on an
// unrelated restore parameter (--name) does not seem like the
// best solution.
- if err == nil && options.Name == "" {
+ if err == nil && options.Name == "" && !options.IgnoreStaticIP {
// The file with the network.status does exist. Let's restore the
// container with the same IP address as during checkpointing.
defer networkStatusFile.Close()
diff --git a/libpod/events/config.go b/libpod/events/config.go
index 96172d47b..453c64f8c 100644
--- a/libpod/events/config.go
+++ b/libpod/events/config.go
@@ -22,13 +22,13 @@ const (
type Event struct {
// ContainerExitCode is for storing the exit code of a container which can
// be used for "internal" event notification
- ContainerExitCode int
+ ContainerExitCode int `json:",omitempty"`
// ID can be for the container, image, volume, etc
- ID string
+ ID string `json:",omitempty"`
// Image used where applicable
- Image string
+ Image string `json:",omitempty"`
// Name where applicable
- Name string
+ Name string `json:",omitempty"`
// Status describes the event that occurred
Status Status
// Time the event occurred
@@ -53,6 +53,8 @@ type Eventer interface {
Write(event Event) error
// Read an event from the backend
Read(options ReadOptions) error
+ // String returns the type of event logger
+ String() string
}
// ReadOptions describe the attributes needed to read event logs
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index d5bce4334..7d195dc79 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -54,14 +54,17 @@ func (e EventJournalD) Read(options ReadOptions) error {
if err != nil {
return errors.Wrapf(err, "failed to generate event options")
}
- podmanJournal := sdjournal.Match{Field: "SYSLOG_IDENTIFIER", Value: "podman"} //nolint
- j, err := sdjournal.NewJournal() //nolint
+ j, err := sdjournal.NewJournal() //nolint
if err != nil {
return err
}
- if err := j.AddMatch(podmanJournal.String()); err != nil {
- return errors.Wrap(err, "failed to add filter for event log")
- }
+ // TODO AddMatch and Seek seem to conflict
+ // Issue filed upstream -> https://github.com/coreos/go-systemd/issues/315
+ // Leaving commented code in case upstream fixes things
+ //podmanJournal := sdjournal.Match{Field: "SYSLOG_IDENTIFIER", Value: "podman"} //nolint
+ //if err := j.AddMatch(podmanJournal.String()); err != nil {
+ // return errors.Wrap(err, "failed to add filter for event log")
+ //}
if len(options.Since) == 0 && len(options.Until) == 0 && options.Stream {
if err := j.SeekTail(); err != nil {
return errors.Wrap(err, "failed to seek end of journal")
@@ -96,6 +99,12 @@ func (e EventJournalD) Read(options ReadOptions) error {
if err != nil {
return err
}
+ // TODO this keeps us from feeding the podman event parser with
+ // with regular journal content; it can be removed if the above
+ // problem with AddMatch is resolved.
+ if entry.Fields["PODMAN_EVENT"] == "" {
+ continue
+ }
newEvent, err := newEventFromJournalEntry(entry)
if err != nil {
// We can't decode this event.
@@ -146,3 +155,8 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) { /
}
return &newEvent, nil
}
+
+// String returns a string representation of the logger
+func (e EventJournalD) String() string {
+ return Journald.String()
+}
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 30d72b9fc..4b65b0ad0 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -71,3 +71,8 @@ func (e EventLogFile) Read(options ReadOptions) error {
close(options.EventChannel)
return nil
}
+
+// String returns a string representation of the logger
+func (e EventLogFile) String() string {
+ return LogFile.String()
+}
diff --git a/libpod/events/nullout.go b/libpod/events/nullout.go
index b11afcf80..f3b36e609 100644
--- a/libpod/events/nullout.go
+++ b/libpod/events/nullout.go
@@ -17,6 +17,10 @@ func (e EventToNull) Read(options ReadOptions) error {
// NewNullEventer returns a new null eventer. You should only do this for
// the purposes on internal libpod testing.
func NewNullEventer() Eventer {
- e := EventToNull{}
- return e
+ return EventToNull{}
+}
+
+// String returns a string representation of the logger
+func (e EventToNull) String() string {
+ return "none"
}
diff --git a/libpod/info.go b/libpod/info.go
index 4a89fa648..9ab6f7e52 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -102,7 +102,7 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) {
return nil, errors.Wrapf(err, "error getting hostname")
}
info["hostname"] = host
-
+ info["eventlogger"] = r.eventer.String()
return info, nil
}
diff --git a/libpod/oci_internal_linux.go b/libpod/oci_internal_linux.go
index 0bcd021db..52cebefab 100644
--- a/libpod/oci_internal_linux.go
+++ b/libpod/oci_internal_linux.go
@@ -278,6 +278,10 @@ func (r *OCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, pidPath
// No case here should happen except JSONLogging, but keep this here in case the options are extended
logrus.Errorf("%s logging specified but not supported. Choosing k8s-file logging instead", ctr.LogDriver())
fallthrough
+ case "":
+ // to get here, either a user would specify `--log-driver ""`, or this came from another place in libpod
+ // since the former case is obscure, and the latter case isn't an error, let's silently fallthrough
+ fallthrough
case KubernetesLogging:
logDriver = fmt.Sprintf("%s:%s", KubernetesLogging, logPath)
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index ffdbc32f1..38bfac8ba 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -52,7 +52,7 @@ const (
var (
// InstallPrefix is the prefix where podman will be installed.
// It can be overridden at build time.
- installPrefix = "/usr/local"
+ installPrefix = "/usr"
// EtcDir is the sysconfdir where podman should look for system config files.
// It can be overridden at build time.
etcDir = "/etc"
@@ -328,16 +328,19 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
}, nil
}
-// SetXdgRuntimeDir ensures the XDG_RUNTIME_DIR env variable is set
-// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
-// It internally calls EnableLinger() so that the user's processes are not
+// SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set.
+// containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is
+// use for the libpod.conf configuration file.
+// SetXdgDirs internally calls EnableLinger() so that the user's processes are not
// killed once the session is terminated. EnableLinger() also attempts to
// get the runtime directory when XDG_RUNTIME_DIR is not specified.
-func SetXdgRuntimeDir() error {
+// This function should only be called when running rootless.
+func SetXdgDirs() error {
if !rootless.IsRootless() {
return nil
}
+ // Setup XDG_RUNTIME_DIR
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
runtimeDirLinger, err := rootless.EnableLinger()
@@ -365,6 +368,16 @@ func SetXdgRuntimeDir() error {
if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil {
return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
}
+
+ // Setup XDG_CONFIG_HOME
+ if cfgHomeDir := os.Getenv("XDG_CONFIG_HOME"); cfgHomeDir == "" {
+ if cfgHomeDir, err = util.GetRootlessConfigHomeDir(); err != nil {
+ return err
+ }
+ if err = os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil {
+ return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME")
+ }
+ }
return nil
}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 47d49f6aa..61a871b28 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -52,6 +52,8 @@ func (r *Runtime) RestoreContainer(ctx context.Context, rSpec *spec.Spec, config
if err != nil {
return nil, errors.Wrapf(err, "error initializing container variables")
}
+ // For an imported checkpoint no one has ever set the StartedTime. Set it now.
+ ctr.state.StartedTime = time.Now()
return r.setupContainer(ctx, ctr)
}