summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/define/errors.go4
-rw-r--r--libpod/runtime.go54
-rw-r--r--libpod/runtime_img.go7
3 files changed, 61 insertions, 4 deletions
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index a4368a9aa..9d532263c 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -107,4 +107,8 @@ var (
// ErrOCIRuntimeNotFound indicates the OCI runtime attempted to invoke a command
// that was not found
ErrOCIRuntimeNotFound = errors.New("OCI runtime command not found error")
+
+ // ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH)
+ // is out of date for the current podman version
+ ErrConmonOutdated = errors.New("outdated conmon version")
)
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 38bfac8ba..83799a52b 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "bytes"
"context"
"fmt"
"io/ioutil"
@@ -8,6 +9,8 @@ import (
"os/exec"
"os/user"
"path/filepath"
+ "regexp"
+ "strconv"
"strings"
"sync"
"syscall"
@@ -739,11 +742,43 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) {
return manager, nil
}
+// probeConmon calls conmon --version and verifies it is a new enough version for
+// the runtime expectations podman currently has
+func probeConmon(conmonBinary string) error {
+ cmd := exec.Command(conmonBinary, "--version")
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ err := cmd.Run()
+ if err != nil {
+ return err
+ }
+ r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`)
+
+ matches := r.FindStringSubmatch(out.String())
+ if len(matches) != 4 {
+ return errors.Wrapf(err, "conmon version changed format")
+ }
+ major, err := strconv.Atoi(matches[1])
+ if err != nil || major < 1 {
+ return define.ErrConmonOutdated
+ }
+ // conmon used to be shipped with CRI-O, and was versioned along with it.
+ // even though the conmon that came with crio-1.9 to crio-1.15 has a higher
+ // version number than conmon 1.0.0, 1.0.0 is newer, so we need this check
+ minor, err := strconv.Atoi(matches[2])
+ if err != nil || minor > 9 {
+ return define.ErrConmonOutdated
+ }
+
+ return nil
+}
+
// Make a new runtime based on the given configuration
// Sets up containers/storage, state store, OCI runtime
func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
// Find a working conmon binary
foundConmon := false
+ foundOutdatedConmon := false
for _, path := range runtime.config.ConmonPath {
stat, err := os.Stat(path)
if err != nil {
@@ -752,6 +787,11 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
if stat.IsDir() {
continue
}
+ if err := probeConmon(path); err != nil {
+ logrus.Warnf("conmon at %s invalid: %v", path, err)
+ foundOutdatedConmon = true
+ continue
+ }
foundConmon = true
runtime.conmonPath = path
logrus.Debugf("using conmon: %q", path)
@@ -761,13 +801,21 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
// Search the $PATH as last fallback
if !foundConmon {
if conmon, err := exec.LookPath("conmon"); err == nil {
- foundConmon = true
- runtime.conmonPath = conmon
- logrus.Debugf("using conmon from $PATH: %q", conmon)
+ if err := probeConmon(conmon); err != nil {
+ logrus.Warnf("conmon at %s is invalid: %v", conmon, err)
+ foundOutdatedConmon = true
+ } else {
+ foundConmon = true
+ runtime.conmonPath = conmon
+ logrus.Debugf("using conmon from $PATH: %q", conmon)
+ }
}
}
if !foundConmon {
+ if foundOutdatedConmon {
+ return errors.Wrapf(define.ErrConmonOutdated, "please update to v1.0.0 or later")
+ }
return errors.Wrapf(define.ErrInvalidArg,
"could not find a working conmon binary (configured options: %v)",
runtime.config.ConmonPath)
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 4055734eb..20dee4080 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -28,6 +28,7 @@ import (
// RemoveImage deletes an image from local storage
// Images being used by running containers can only be removed if force=true
func (r *Runtime) RemoveImage(ctx context.Context, img *image.Image, force bool) (string, error) {
+ var returnMessage string
r.lock.Lock()
defer r.lock.Unlock()
@@ -93,7 +94,11 @@ func (r *Runtime) RemoveImage(ctx context.Context, img *image.Image, force bool)
err = errStorage
}
}
- return img.ID(), err
+ for _, name := range img.Names() {
+ returnMessage = returnMessage + fmt.Sprintf("Untagged: %s\n", name)
+ }
+ returnMessage = returnMessage + fmt.Sprintf("Deleted: %s", img.ID())
+ return returnMessage, err
}
// Remove containers that are in storage rather than Podman.