summaryrefslogtreecommitdiff
path: root/libpod/runtime.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/runtime.go')
-rw-r--r--libpod/runtime.go79
1 files changed, 74 insertions, 5 deletions
diff --git a/libpod/runtime.go b/libpod/runtime.go
index c975f628b..52f4523ba 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -7,6 +7,7 @@ import (
"os/exec"
"path/filepath"
"sync"
+ "syscall"
"github.com/BurntSushi/toml"
is "github.com/containers/image/storage"
@@ -79,7 +80,8 @@ type RuntimeOption func(*Runtime) error
// Runtime is the core libpod runtime
type Runtime struct {
- config *RuntimeConfig
+ config *RuntimeConfig
+
state State
store storage.Store
storageService *storageService
@@ -88,12 +90,23 @@ type Runtime struct {
netPlugin ocicni.CNIPlugin
ociRuntimePath OCIRuntimePath
conmonPath string
- valid bool
- lock sync.RWMutex
imageRuntime *image.Runtime
firewallBackend firewall.FirewallBackend
lockManager lock.Manager
configuredFrom *runtimeConfiguredFrom
+
+ // doRenumber indicates that the runtime should perform a lock renumber
+ // during initialization.
+ // Once the runtime has been initialized and returned, this variable is
+ // unused.
+ doRenumber bool
+
+ // valid indicates whether the runtime is ready to use.
+ // valid is set to true when a runtime is returned from GetRuntime(),
+ // and remains true until the runtime is shut down (rendering its
+ // storage unusable). When valid is false, the runtime cannot be used.
+ valid bool
+ lock sync.RWMutex
}
// OCIRuntimePath contains information about an OCI runtime.
@@ -130,6 +143,12 @@ type RuntimeConfig struct {
OCIRuntime string `toml:"runtime"`
// OCIRuntimes are the set of configured OCI runtimes (default is runc)
OCIRuntimes map[string][]string `toml:"runtimes"`
+ // RuntimePath is the path to OCI runtime binary for launching
+ // containers.
+ // The first path pointing to a valid file will be used
+ // This is used only when there are no OCIRuntime/OCIRuntimes defined. It
+ // is used only to be backward compatible with older versions of Podman.
+ RuntimePath []string `toml:"runtime_path"`
// ConmonPath is the path to the Conmon binary used for managing
// containers
// The first path pointing to a valid file will be used
@@ -389,7 +408,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
// If the configuration file was not found but we are running in rootless, a subset of the
// global config file is used.
for _, path := range []string{OverrideConfigPath, ConfigPath} {
- contents, err := ioutil.ReadFile(OverrideConfigPath)
+ contents, err := ioutil.ReadFile(path)
if err != nil {
// Ignore any error, the file might not be readable by us.
continue
@@ -403,6 +422,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
runtime.config.ConmonPath = tmpConfig.ConmonPath
runtime.config.ConmonEnvVars = tmpConfig.ConmonEnvVars
runtime.config.OCIRuntimes = tmpConfig.OCIRuntimes
+ runtime.config.RuntimePath = tmpConfig.RuntimePath
runtime.config.CNIPluginDir = tmpConfig.CNIPluginDir
runtime.config.NoPivotRoot = tmpConfig.NoPivotRoot
break
@@ -485,12 +505,37 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime
// Make a new runtime based on the given configuration
// Sets up containers/storage, state store, OCI runtime
func makeRuntime(runtime *Runtime) (err error) {
+
+ // Backward compatibility for `runtime_path`
+ if runtime.config.RuntimePath != nil {
+ // Don't print twice in rootless mode.
+ if os.Geteuid() == 0 {
+ logrus.Warningf("The configuration is using `runtime_path`, which is deprecated and will be removed in future. Please use `runtimes` and `runtime`")
+ logrus.Warningf("If you are using both `runtime_path` and `runtime`, the configuration from `runtime_path` is used")
+ }
+
+ // Transform `runtime_path` into `runtimes` and `runtime`.
+ name := filepath.Base(runtime.config.RuntimePath[0])
+ runtime.config.OCIRuntime = name
+ runtime.config.OCIRuntimes = map[string][]string{name: runtime.config.RuntimePath}
+ }
+
// Find a working OCI runtime binary
foundRuntime := false
// If runtime is an absolute path, then use it as it is.
- if runtime.config.OCIRuntime[0] == '/' {
+ if runtime.config.OCIRuntime != "" && runtime.config.OCIRuntime[0] == '/' {
foundRuntime = true
runtime.ociRuntimePath = OCIRuntimePath{Name: filepath.Base(runtime.config.OCIRuntime), Paths: []string{runtime.config.OCIRuntime}}
+ stat, err := os.Stat(runtime.config.OCIRuntime)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return errors.Wrapf(err, "the specified OCI runtime %s does not exist", runtime.config.OCIRuntime)
+ }
+ return errors.Wrapf(err, "cannot stat the OCI runtime path %s", runtime.config.OCIRuntime)
+ }
+ if !stat.Mode().IsRegular() {
+ return fmt.Errorf("the specified OCI runtime %s is not a valid file", runtime.config.OCIRuntime)
+ }
} else {
// If not, look it up in the configuration.
paths := runtime.config.OCIRuntimes[runtime.config.OCIRuntime]
@@ -731,6 +776,7 @@ func makeRuntime(runtime *Runtime) (err error) {
aliveLock.Unlock()
}
}()
+
_, err = os.Stat(runtimeAliveFile)
if err != nil {
// If the file doesn't exist, we need to refresh the state
@@ -756,12 +802,35 @@ func makeRuntime(runtime *Runtime) (err error) {
if err != nil {
return err
}
+ } else if errors.Cause(err) == syscall.ERANGE && runtime.doRenumber {
+ logrus.Debugf("Number of locks does not match - removing old locks")
+
+ // ERANGE indicates a lock numbering mismatch.
+ // Since we're renumbering, this is not fatal.
+ // Remove the earlier set of locks and recreate.
+ if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil {
+ return errors.Wrapf(err, "error removing libpod locks file %s", lockPath)
+ }
+
+ manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
+ if err != nil {
+ return err
+ }
} else {
return err
}
}
runtime.lockManager = manager
+ // If we're renumbering locks, do it now.
+ // It breaks out of normal runtime init, and will not return a valid
+ // runtime.
+ if runtime.doRenumber {
+ if err := runtime.renumberLocks(); err != nil {
+ return err
+ }
+ }
+
// If we need to refresh the state, do it now - things are guaranteed to
// be set up by now.
if doRefresh {