diff options
Diffstat (limited to 'libpod/runtime.go')
-rw-r--r-- | libpod/runtime.go | 79 |
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 { |