oci: allow to define multiple OCI runtimes

we can define multiple OCI runtimes that can be chosen with
--runtime.

in libpod.conf is possible to specify them with:

[runtimes]
foo = [
             "/usr/bin/foo",
	     "/usr/sbin/foo",
]
bar = [
             "/usr/bin/foo",
	     "/usr/sbin/foo",
]

If the argument to --runtime is an absolute path then it is used
directly without any lookup in the configuration.

Closes: https://github.com/containers/libpod/issues/1750

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2019-01-04 11:16:40 +01:00
parent 650cf122e1
commit 50c86ae389
No known key found for this signature in database
GPG key ID: E4730F97F60286ED
4 changed files with 55 additions and 47 deletions

View file

@ -68,7 +68,7 @@ Default state dir is configured in /etc/containers/storage.conf.
**--runtime**=**value**
Path to the OCI compatible binary used to run containers
Name of the OCI runtime as specified in libpod.conf or absolute path to the OCI compatible binary used to run containers.
**--storage-driver, -s**=**value**

View file

@ -4,17 +4,6 @@
# Default transport method for pulling and pushing for images
image_default_transport = "docker://"
# Paths to look for a valid OCI runtime (runc, runv, etc)
runtime_path = [
"/usr/bin/runc",
"/usr/sbin/runc",
"/usr/local/bin/runc",
"/usr/local/sbin/runc",
"/sbin/runc",
"/bin/runc",
"/usr/lib/cri-o-runc/sbin/runc"
]
# Paths to look for the Conmon container manager binary
conmon_path = [
"/usr/libexec/podman/conmon",
@ -98,3 +87,15 @@ pause_command = "/pause"
# Default libpod support for container labeling
# label=true
# Paths to look for a valid OCI runtime (runc, runv, etc)
[runtimes]
runc = [
"/usr/bin/runc",
"/usr/sbin/runc",
"/usr/local/bin/runc",
"/usr/local/sbin/runc",
"/sbin/runc",
"/bin/runc",
"/usr/lib/cri-o-runc/sbin/runc"
]

View file

@ -137,21 +137,17 @@ func WithStateType(storeType RuntimeStateStore) RuntimeOption {
}
// WithOCIRuntime specifies an OCI runtime to use for running containers.
func WithOCIRuntime(runtimePath string) RuntimeOption {
func WithOCIRuntime(runtime string) RuntimeOption {
return func(rt *Runtime) error {
if rt.valid {
return ErrRuntimeFinalized
}
if runtimePath == "" {
if runtime == "" {
return errors.Wrapf(ErrInvalidArg, "must provide a valid path")
}
rt.config.OCIRuntimes = []OCIRuntimePath{
{
Paths: []string{runtimePath},
},
}
rt.config.OCIRuntime = runtime
return nil
}

View file

@ -99,9 +99,9 @@ type Runtime struct {
// OCIRuntimePath contains information about an OCI runtime.
type OCIRuntimePath struct {
// Name of the runtime to refer to by the --runtime flag
Name string
Name string `toml:"name"`
// Paths to check for this executable
Paths []string
Paths []string `toml:"paths"`
}
// RuntimeConfig contains configuration options used to set up the runtime
@ -126,8 +126,10 @@ type RuntimeConfig struct {
// cause conflicts in containers/storage
// As such this is not exposed via the config file
StateType RuntimeStateStore `toml:"-"`
// OCIRuntime is the OCI runtime to use.
OCIRuntime string `toml:"runtime"`
// OCIRuntimes are the set of configured OCI runtimes (default is runc)
OCIRuntimes []OCIRuntimePath `toml:"runtimes"`
OCIRuntimes map[string][]string `toml:"runtimes"`
// ConmonPath is the path to the Conmon binary used for managing
// containers
// The first path pointing to a valid file will be used
@ -219,18 +221,16 @@ var (
StorageConfig: storage.StoreOptions{},
ImageDefaultTransport: DefaultTransport,
StateType: BoltDBStateStore,
OCIRuntimes: []OCIRuntimePath{
{
Name: "runc",
Paths: []string{
"/usr/bin/runc",
"/usr/sbin/runc",
"/usr/local/bin/runc",
"/usr/local/sbin/runc",
"/sbin/runc",
"/bin/runc",
"/usr/lib/cri-o-runc/sbin/runc",
},
OCIRuntime: "runc",
OCIRuntimes: map[string][]string{
"runc": {
"/usr/bin/runc",
"/usr/sbin/runc",
"/usr/local/bin/runc",
"/usr/local/sbin/runc",
"/sbin/runc",
"/bin/runc",
"/usr/lib/cri-o-runc/sbin/runc",
},
},
ConmonPath: []string{
@ -425,8 +425,9 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime
runtime.config = new(RuntimeConfig)
runtime.configuredFrom = new(runtimeConfiguredFrom)
// Set two fields not in the TOML config
// Set three fields not in the TOML config
runtime.config.StateType = defaultRuntimeConfig.StateType
runtime.config.OCIRuntime = defaultRuntimeConfig.OCIRuntime
runtime.config.StorageConfig = storage.StoreOptions{}
// Check to see if the given configuration file exists
@ -464,19 +465,29 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime
func makeRuntime(runtime *Runtime) (err error) {
// Find a working OCI runtime binary
foundRuntime := false
outer:
for _, oruntime := range runtime.config.OCIRuntimes {
for _, path := range oruntime.Paths {
stat, err := os.Stat(path)
if err != nil {
continue
// If runtime is an absolute path, then use it as it is.
if runtime.config.OCIRuntime[0] == '/' {
foundRuntime = true
runtime.ociRuntimePath = OCIRuntimePath{Name: filepath.Base(runtime.config.OCIRuntime), Paths: []string{runtime.config.OCIRuntime}}
} else {
// If not, look it up in the configuration.
paths := runtime.config.OCIRuntimes[runtime.config.OCIRuntime]
if paths != nil {
for _, path := range paths {
stat, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
continue
}
return errors.Wrapf(err, "cannot stat %s", path)
}
if !stat.Mode().IsRegular() {
continue
}
foundRuntime = true
runtime.ociRuntimePath = OCIRuntimePath{Name: runtime.config.OCIRuntime, Paths: []string{path}}
break
}
if stat.IsDir() {
continue
}
foundRuntime = true
runtime.ociRuntimePath = OCIRuntimePath{Name: oruntime.Name, Paths: []string{path}}
break outer
}
}
if !foundRuntime {