summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go6
-rw-r--r--libpod/container_config.go2
-rw-r--r--libpod/container_internal_linux.go42
-rw-r--r--libpod/container_log.go7
-rw-r--r--libpod/container_log_linux.go7
-rw-r--r--libpod/define/container.go2
-rw-r--r--libpod/define/info.go9
-rw-r--r--libpod/diff.go1
-rw-r--r--libpod/info.go11
-rw-r--r--libpod/networking_linux.go28
-rw-r--r--libpod/oci_conmon_exec_linux.go2
-rw-r--r--libpod/oci_conmon_linux.go49
-rw-r--r--libpod/options.go4
-rw-r--r--libpod/pod_api.go4
-rw-r--r--libpod/runtime.go15
-rw-r--r--libpod/runtime_ctr.go14
-rw-r--r--libpod/runtime_volume_linux.go15
-rw-r--r--libpod/shutdown/handler.go2
18 files changed, 178 insertions, 42 deletions
diff --git a/libpod/container.go b/libpod/container.go
index d5d5ef1a5..c57250d72 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -126,6 +126,10 @@ type Container struct {
// This is true if a container is restored from a checkpoint.
restoreFromCheckpoint bool
+ // Used to query the NOTIFY_SOCKET once along with setting up
+ // mounts etc.
+ notifySocket string
+
slirp4netnsSubnet *net.IPNet
}
@@ -240,7 +244,7 @@ type ContainerImageVolume struct {
type ContainerSecret struct {
// Secret is the secret
*secrets.Secret
- // UID is tbe UID of the secret file
+ // UID is the UID of the secret file
UID uint32
// GID is the GID of the secret file
GID uint32
diff --git a/libpod/container_config.go b/libpod/container_config.go
index 72a969fe6..e15030c15 100644
--- a/libpod/container_config.go
+++ b/libpod/container_config.go
@@ -376,6 +376,6 @@ type ContainerMiscConfig struct {
// EnvSecrets are secrets that are set as environment variables
EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"`
// InitContainerType specifies if the container is an initcontainer
- // and if so, what type: always or oneshot are possible non-nil entries
+ // and if so, what type: always or once are possible non-nil entries
InitContainerType string `json:"init_container_type,omitempty"`
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 6d2f7bddc..8b73c82de 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -352,6 +352,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return nil, err
}
+ if err := c.mountNotifySocket(g); err != nil {
+ return nil, err
+ }
+
// Get host UID and GID based on the container process UID and GID.
hostUID, hostGID, err := butil.GetHostIDs(util.IDtoolsToRuntimeSpec(c.config.IDMappings.UIDMap), util.IDtoolsToRuntimeSpec(c.config.IDMappings.GIDMap), uint32(execUser.Uid), uint32(execUser.Gid))
if err != nil {
@@ -777,6 +781,41 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return g.Config, nil
}
+// mountNotifySocket mounts the NOTIFY_SOCKET into the container if it's set
+// and if the sdnotify mode is set to container. It also sets c.notifySocket
+// to avoid redundantly looking up the env variable.
+func (c *Container) mountNotifySocket(g generate.Generator) error {
+ notify, ok := os.LookupEnv("NOTIFY_SOCKET")
+ if !ok {
+ return nil
+ }
+ c.notifySocket = notify
+
+ if c.config.SdNotifyMode != define.SdNotifyModeContainer {
+ return nil
+ }
+
+ notifyDir := filepath.Join(c.bundlePath(), "notify")
+ logrus.Debugf("checking notify %q dir", notifyDir)
+ if err := os.MkdirAll(notifyDir, 0755); err != nil {
+ if !os.IsExist(err) {
+ return errors.Wrapf(err, "unable to create notify %q dir", notifyDir)
+ }
+ }
+ if err := label.Relabel(notifyDir, c.MountLabel(), true); err != nil {
+ return errors.Wrapf(err, "relabel failed %q", notifyDir)
+ }
+ logrus.Debugf("add bindmount notify %q dir", notifyDir)
+ if _, ok := c.state.BindMounts["/run/notify"]; !ok {
+ c.state.BindMounts["/run/notify"] = notifyDir
+ }
+
+ // Set the container's notify socket to the proxy socket created by conmon
+ g.AddProcessEnv("NOTIFY_SOCKET", "/run/notify/notify.sock")
+
+ return nil
+}
+
// systemd expects to have /run, /run/lock and /tmp on tmpfs
// It also expects to be able to write to /sys/fs/cgroup/systemd and /var/log/journal
func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) error {
@@ -1730,6 +1769,7 @@ rootless=%d
c.state.BindMounts[dest] = src
}
}
+
return nil
}
@@ -1782,7 +1822,7 @@ func (c *Container) generateResolvConf() (string, error) {
cniResponse := c.state.NetworkStatus
for _, i := range cniResponse {
for _, ip := range i.IPs {
- // Note: only using To16() does not work since it also returns a vaild ip for ipv4
+ // Note: only using To16() does not work since it also returns a valid ip for ipv4
if ip.Address.IP.To4() == nil && ip.Address.IP.To16() != nil {
ipv6 = true
}
diff --git a/libpod/container_log.go b/libpod/container_log.go
index 743c9c61b..3988bb654 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -14,6 +14,13 @@ import (
"github.com/sirupsen/logrus"
)
+// logDrivers stores the currently available log drivers, do not modify
+var logDrivers []string
+
+func init() {
+ logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging)
+}
+
// Log is a runtime function that can read one or more container logs.
func (r *Runtime) Log(ctx context.Context, containers []*Container, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
for _, ctr := range containers {
diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go
index d4afaa52a..4eb600bfe 100644
--- a/libpod/container_log_linux.go
+++ b/libpod/container_log_linux.go
@@ -9,6 +9,7 @@ import (
"strings"
"time"
+ "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/libpod/logs"
"github.com/coreos/go-systemd/v22/sdjournal"
@@ -24,6 +25,10 @@ const (
journaldLogErr = "3"
)
+func init() {
+ logDrivers = append(logDrivers, define.JournaldLogging)
+}
+
func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
journal, err := sdjournal.NewJournal()
if err != nil {
@@ -79,7 +84,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
break
}
if cursorError != nil {
- return errors.Wrap(cursorError, "inital journal cursor")
+ return errors.Wrap(cursorError, "initial journal cursor")
}
// We need the container's events in the same journal to guarantee
diff --git a/libpod/define/container.go b/libpod/define/container.go
index f0aca92aa..bb44a6a4a 100644
--- a/libpod/define/container.go
+++ b/libpod/define/container.go
@@ -34,5 +34,5 @@ const (
AlwaysInitContainer = "always"
// OneShotInitContainer is a container that only runs as init once
// and is then deleted.
- OneShotInitContainer = "oneshot"
+ OneShotInitContainer = "once"
)
diff --git a/libpod/define/info.go b/libpod/define/info.go
index de709be74..95c1196dd 100644
--- a/libpod/define/info.go
+++ b/libpod/define/info.go
@@ -8,6 +8,7 @@ type Info struct {
Host *HostInfo `json:"host"`
Store *StoreInfo `json:"store"`
Registries map[string]interface{} `json:"registries"`
+ Plugins Plugins `json:"plugins"`
Version Version `json:"version"`
}
@@ -123,3 +124,11 @@ type ContainerStore struct {
Running int `json:"running"`
Stopped int `json:"stopped"`
}
+
+type Plugins struct {
+ Volume []string `json:"volume"`
+ Network []string `json:"network"`
+ Log []string `json:"log"`
+ // FIXME what should we do with Authorization, docker seems to return nothing by default
+ // Authorization []string `json:"authorization"`
+}
diff --git a/libpod/diff.go b/libpod/diff.go
index cdd5e79cb..6a50bef32 100644
--- a/libpod/diff.go
+++ b/libpod/diff.go
@@ -14,6 +14,7 @@ var initInodes = map[string]bool{
"/etc/resolv.conf": true,
"/proc": true,
"/run": true,
+ "/run/notify": true,
"/run/.containerenv": true,
"/run/secrets": true,
"/sys": true,
diff --git a/libpod/info.go b/libpod/info.go
index 2b48ea590..8f4c7f015 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -18,6 +18,7 @@ import (
"github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/linkmode"
+ "github.com/containers/podman/v3/libpod/network"
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/storage"
@@ -65,6 +66,16 @@ func (r *Runtime) info() (*define.Info, error) {
if len(regs) > 0 {
registries["search"] = regs
}
+ volumePlugins := make([]string, 0, len(r.config.Engine.VolumePlugins)+1)
+ // the local driver always exists
+ volumePlugins = append(volumePlugins, "local")
+ for plugin := range r.config.Engine.VolumePlugins {
+ volumePlugins = append(volumePlugins, plugin)
+ }
+ info.Plugins.Volume = volumePlugins
+ // TODO move this into the new network interface
+ info.Plugins.Network = []string{network.BridgeNetworkDriver, network.MacVLANNetworkDriver}
+ info.Plugins.Log = logDrivers
info.Registries = registries
return &info, nil
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 8e9b5997c..2ed2bb01b 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -173,11 +173,27 @@ func (r *RootlessCNI) Do(toRun func() error) error {
// the link target will be available in the mount ns.
// see: https://github.com/containers/podman/issues/10855
resolvePath := "/etc/resolv.conf"
- resolvePath, err = filepath.EvalSymlinks(resolvePath)
- if err != nil {
- return err
+ for i := 0; i < 255; i++ {
+ // Do not use filepath.EvalSymlinks, we only want the first symlink under /run.
+ // If /etc/resolv.conf has more than one symlink under /run, e.g.
+ // -> /run/systemd/resolve/stub-resolv.conf -> /run/systemd/resolve/resolv.conf
+ // we would put the netns resolv.conf file to the last path. However this will
+ // break dns because the second link does not exists in the mount ns.
+ // see https://github.com/containers/podman/issues/11222
+ link, err := os.Readlink(resolvePath)
+ if err != nil {
+ // if there is no symlink exit
+ break
+ }
+ resolvePath = filepath.Join(filepath.Dir(resolvePath), link)
+ if strings.HasPrefix(resolvePath, "/run/") {
+ break
+ }
+ if i == 254 {
+ return errors.New("too many symlinks while resolving /etc/resolv.conf")
+ }
}
- logrus.Debugf("The actual path of /etc/resolv.conf on the host is %q", resolvePath)
+ logrus.Debugf("The path of /etc/resolv.conf in the mount ns is %q", resolvePath)
// When /etc/resolv.conf on the host is a symlink to /run/systemd/resolve/stub-resolv.conf,
// we have to mount an empty filesystem on /run/systemd/resolve in the child namespace,
// so as to isolate the directory from the host mount namespace.
@@ -1219,7 +1235,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
return err
}
- // OCICNI will set the loopback adpter down on teardown so we should set it up again
+ // OCICNI will set the loopback adapter down on teardown so we should set it up again
err = c.state.NetNS.Do(func(_ ns.NetNS) error {
link, err := netlink.LinkByName("lo")
if err != nil {
@@ -1229,7 +1245,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
return err
})
if err != nil {
- logrus.Warnf("failed to set loopback adpter up in the container: %v", err)
+ logrus.Warnf("failed to set loopback adapter up in the container: %v", err)
}
// Reload ports when there are still connected networks, maybe we removed the network interface with the child ip.
// Reloading without connected networks does not make sense, so we can skip this step.
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 05a4e19b0..469bc7d86 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -462,7 +462,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
Setpgid: true,
}
- err = startCommandGivenSelinux(execCmd)
+ err = startCommandGivenSelinux(execCmd, c)
// We don't need children pipes on the parent side
errorhandling.CloseQuiet(childSyncPipe)
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 846d3815a..ff25be234 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -364,11 +364,6 @@ func (r *ConmonOCIRuntime) StartContainer(ctr *Container) error {
return err
}
env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
- if ctr.config.SdNotifyMode == define.SdNotifyModeContainer {
- if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
- env = append(env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify))
- }
- }
if path, ok := os.LookupEnv("PATH"); ok {
env = append(env, fmt.Sprintf("PATH=%s", path))
}
@@ -1014,12 +1009,6 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
}
}
- if ctr.config.SdNotifyMode == define.SdNotifyModeIgnore {
- if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
- logrus.Warnf("Error unsetting NOTIFY_SOCKET %v", err)
- }
- }
-
pidfile := ctr.config.PidFile
if pidfile == "" {
pidfile = filepath.Join(ctr.state.RunDir, "pidfile")
@@ -1027,6 +1016,10 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
args := r.sharedConmonArgs(ctr, ctr.ID(), ctr.bundlePath(), pidfile, ctr.LogPath(), r.exitsDir, ociLog, ctr.LogDriver(), logTag)
+ if ctr.config.SdNotifyMode == define.SdNotifyModeContainer && ctr.notifySocket != "" {
+ args = append(args, fmt.Sprintf("--sdnotify-socket=%s", ctr.notifySocket))
+ }
+
if ctr.config.Spec.Process.Terminal {
args = append(args, "-t")
} else if ctr.config.Stdin {
@@ -1171,7 +1164,8 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
}
}
- err = startCommandGivenSelinux(cmd)
+ err = startCommandGivenSelinux(cmd, ctr)
+
// regardless of whether we errored or not, we no longer need the children pipes
childSyncPipe.Close()
childStartPipe.Close()
@@ -1203,7 +1197,13 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
// conmon not having a pid file is a valid state, so don't set it if we don't have it
logrus.Infof("Got Conmon PID as %d", conmonPID)
ctr.state.ConmonPID = conmonPID
- if ctr.config.SdNotifyMode != define.SdNotifyModeIgnore {
+
+ // Send the MAINPID via sdnotify if needed.
+ switch ctr.config.SdNotifyMode {
+ case define.SdNotifyModeContainer, define.SdNotifyModeIgnore:
+ // Nothing to do or conmon takes care of it already.
+
+ default:
if sent, err := daemon.SdNotify(false, fmt.Sprintf("MAINPID=%d", conmonPID)); err != nil {
logrus.Errorf("Error notifying systemd of Conmon PID: %v", err)
} else if sent {
@@ -1239,11 +1239,6 @@ func (r *ConmonOCIRuntime) configureConmonEnv(ctr *Container, runtimeDir string)
}
extraFiles := make([]*os.File, 0)
- if ctr.config.SdNotifyMode == define.SdNotifyModeContainer {
- if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
- env = append(env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify))
- }
- }
if !r.sdNotify {
if listenfds, ok := os.LookupEnv("LISTEN_FDS"); ok {
env = append(env, fmt.Sprintf("LISTEN_FDS=%s", listenfds), "LISTEN_PID=1")
@@ -1335,7 +1330,23 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
// startCommandGivenSelinux starts a container ensuring to set the labels of
// the process to make sure SELinux doesn't block conmon communication, if SELinux is enabled
-func startCommandGivenSelinux(cmd *exec.Cmd) error {
+func startCommandGivenSelinux(cmd *exec.Cmd, ctr *Container) error {
+ // Make sure to unset the NOTIFY_SOCKET and reset if afterwards if needed.
+ switch ctr.config.SdNotifyMode {
+ case define.SdNotifyModeContainer, define.SdNotifyModeIgnore:
+ if ctr.notifySocket != "" {
+ if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
+ logrus.Warnf("Error unsetting NOTIFY_SOCKET %v", err)
+ }
+
+ defer func() {
+ if err := os.Setenv("NOTIFY_SOCKET", ctr.notifySocket); err != nil {
+ logrus.Errorf("Error resetting NOTIFY_SOCKET=%s", ctr.notifySocket)
+ }
+ }()
+ }
+ }
+
if !selinux.GetEnabled() {
return cmd.Start()
}
diff --git a/libpod/options.go b/libpod/options.go
index b94ef88ba..59aec66c6 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -268,7 +268,7 @@ func WithRegistriesConf(path string) RuntimeOption {
logrus.Debugf("Setting custom registries.conf: %q", path)
return func(rt *Runtime) error {
if _, err := os.Stat(path); err != nil {
- return errors.Wrap(err, "error locating specified registries.conf")
+ return errors.Wrap(err, "locating specified registries.conf")
}
if rt.imageContext == nil {
rt.imageContext = &types.SystemContext{
@@ -1453,7 +1453,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption {
for _, vol := range volumes {
mountOpts, err := util.ProcessOptions(vol.Options, false, "")
if err != nil {
- return errors.Wrapf(err, "error processing options for named volume %q mounted at %q", vol.Name, vol.Dest)
+ return errors.Wrapf(err, "processing options for named volume %q mounted at %q", vol.Name, vol.Dest)
}
ctr.config.NamedVolumes = append(ctr.config.NamedVolumes, &ContainerNamedVolume{
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 6fea2dfd8..716eb2e5b 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -32,14 +32,14 @@ func (p *Pod) startInitContainers(ctx context.Context) error {
if rc != 0 {
return errors.Errorf("init container %s exited with code %d", initCon.ID(), rc)
}
- // If the container is an oneshot init container, we need to remove it
+ // If the container is a once init container, we need to remove it
// after it runs
if initCon.Config().InitContainerType == define.OneShotInitContainer {
icLock := initCon.lock
icLock.Lock()
if err := p.runtime.removeContainer(ctx, initCon, false, false, true); err != nil {
icLock.Unlock()
- return errors.Wrapf(err, "failed to remove oneshot init container %s", initCon.ID())
+ return errors.Wrapf(err, "failed to remove once init container %s", initCon.ID())
}
// Removing a container this way requires an explicit call to clean up the db
if err := p.runtime.state.RemoveContainerFromPod(p, initCon); err != nil {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 30659a3d4..c5f5db531 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -30,6 +30,7 @@ import (
"github.com/containers/podman/v3/libpod/shutdown"
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/systemd"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage"
"github.com/containers/storage/pkg/unshare"
@@ -500,6 +501,15 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// no containers running. Create immediately a namespace, as
// we will need to access the storage.
if needsUserns {
+ // warn users if mode is rootless and cgroup manager is systemd
+ // and no valid systemd session is present
+ // warn only whenever new namespace is created
+ if runtime.config.Engine.CgroupManager == config.SystemdCgroupsManager {
+ unified, _ := cgroups.IsCgroup2UnifiedMode()
+ if unified && rootless.IsRootless() && !systemd.IsSystemdSessionValid(rootless.GetRootlessUID()) {
+ logrus.Debug("Invalid systemd user session for current user")
+ }
+ }
aliveLock.Unlock() // Unlock to avoid deadlock as BecomeRootInUserNS will reexec.
pausePid, err := util.GetRootlessPauseProcessPidPathGivenDir(runtime.config.Engine.TmpDir)
if err != nil {
@@ -941,6 +951,11 @@ func (r *Runtime) GetOCIRuntimePath() string {
return r.defaultOCIRuntime.Path()
}
+// DefaultOCIRuntime return copy of Default OCI Runtime
+func (r *Runtime) DefaultOCIRuntime() OCIRuntime {
+ return r.defaultOCIRuntime
+}
+
// StorageConfig retrieves the storage options for the container runtime
func (r *Runtime) StorageConfig() storage.StoreOptions {
return r.storageConfig
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 059f56798..02bbb6981 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -246,6 +246,20 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
ctr.config.Networks = netNames
}
+ // https://github.com/containers/podman/issues/11285
+ // normalize the networks aliases to use network names and never ids
+ if len(ctr.config.NetworkAliases) > 0 {
+ netAliases := make(map[string][]string, len(ctr.config.NetworkAliases))
+ for nameOrID, aliases := range ctr.config.NetworkAliases {
+ netName, err := network.NormalizeName(r.config, nameOrID)
+ if err != nil {
+ return nil, err
+ }
+ netAliases[netName] = aliases
+ }
+ ctr.config.NetworkAliases = netAliases
+ }
+
// Inhibit shutdown until creation succeeds
shutdown.Inhibit()
defer shutdown.Uninhibit()
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index 40df98d7c..d1ea7d4fd 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -255,11 +255,6 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
// Set volume as invalid so it can no longer be used
v.valid = false
- // Remove the volume from the state
- if err := r.state.RemoveVolume(v); err != nil {
- return errors.Wrapf(err, "error removing volume %s", v.Name())
- }
-
var removalErr error
// If we use a volume plugin, we need to remove from the plugin.
@@ -287,11 +282,19 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
req := new(pluginapi.RemoveRequest)
req.Name = v.Name()
if err := v.plugin.RemoveVolume(req); err != nil {
- removalErr = errors.Wrapf(err, "volume %s could not be removed from plugin %s, but it has been removed from Podman", v.Name(), v.Driver())
+ return errors.Wrapf(err, "volume %s could not be removed from plugin %s", v.Name(), v.Driver())
}
}
}
+ // Remove the volume from the state
+ if err := r.state.RemoveVolume(v); err != nil {
+ if removalErr != nil {
+ logrus.Errorf("Error removing volume %s from plugin %s: %v", v.Name(), v.Driver(), removalErr)
+ }
+ return errors.Wrapf(err, "error removing volume %s", v.Name())
+ }
+
// Free the volume's lock
if err := v.lock.Free(); err != nil {
if removalErr == nil {
diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go
index 848b6729a..1e8a9ec3b 100644
--- a/libpod/shutdown/handler.go
+++ b/libpod/shutdown/handler.go
@@ -35,7 +35,7 @@ func Start() error {
return nil
}
- sigChan = make(chan os.Signal, 1)
+ sigChan = make(chan os.Signal, 2)
cancelChan = make(chan bool, 1)
stopped = false