mirror of
https://github.com/containers/podman.git
synced 2025-06-06 15:00:40 +08:00
Add support to load runtime configuration from config file
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #430 Approved by: rhatdan
This commit is contained in:
2
Makefile
2
Makefile
@ -12,6 +12,7 @@ LIBEXECDIR ?= ${PREFIX}/libexec
|
|||||||
MANDIR ?= ${PREFIX}/share/man
|
MANDIR ?= ${PREFIX}/share/man
|
||||||
ETCDIR ?= ${DESTDIR}/etc
|
ETCDIR ?= ${DESTDIR}/etc
|
||||||
ETCDIR_LIBPOD ?= ${ETCDIR}/crio
|
ETCDIR_LIBPOD ?= ${ETCDIR}/crio
|
||||||
|
ETCDIR_CONTAINERS ?= ${ETCDIR}/containers
|
||||||
BUILDTAGS ?= seccomp $(shell hack/btrfs_tag.sh) $(shell hack/libdm_tag.sh) $(shell hack/btrfs_installed_tag.sh) $(shell hack/ostree_tag.sh) $(shell hack/selinux_tag.sh)
|
BUILDTAGS ?= seccomp $(shell hack/btrfs_tag.sh) $(shell hack/libdm_tag.sh) $(shell hack/btrfs_installed_tag.sh) $(shell hack/ostree_tag.sh) $(shell hack/selinux_tag.sh)
|
||||||
|
|
||||||
BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
|
BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
|
||||||
@ -151,6 +152,7 @@ install.man: docs
|
|||||||
install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES)) -t $(MANDIR)/man1
|
install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES)) -t $(MANDIR)/man1
|
||||||
|
|
||||||
install.config:
|
install.config:
|
||||||
|
install ${SELINUXOPT} -D -m 644 libpod.conf ${ETCDIR_CONTAINERS}/libpod.conf
|
||||||
install ${SELINUXOPT} -D -m 644 seccomp.json $(ETCDIR_LIBPOD)/seccomp.json
|
install ${SELINUXOPT} -D -m 644 seccomp.json $(ETCDIR_LIBPOD)/seccomp.json
|
||||||
install ${SELINUXOPT} -D -m 644 crio-umount.conf $(OCIUMOUNTINSTALLDIR)/crio-umount.conf
|
install ${SELINUXOPT} -D -m 644 crio-umount.conf $(OCIUMOUNTINSTALLDIR)/crio-umount.conf
|
||||||
|
|
||||||
|
@ -37,6 +37,14 @@ const (
|
|||||||
SeccompDefaultPath = "/usr/share/containers/seccomp.json"
|
SeccompDefaultPath = "/usr/share/containers/seccomp.json"
|
||||||
// SeccompOverridePath if this exists it overrides the default seccomp path
|
// SeccompOverridePath if this exists it overrides the default seccomp path
|
||||||
SeccompOverridePath = "/etc/crio/seccomp.json"
|
SeccompOverridePath = "/etc/crio/seccomp.json"
|
||||||
|
|
||||||
|
// ConfigPath is the path to the libpod configuration file
|
||||||
|
// This file is loaded to replace the builtin default config before
|
||||||
|
// runtime options (e.g. WithStorageConfig) are applied.
|
||||||
|
// If it is not present, the builtin default config is used instead
|
||||||
|
// This path can be overridden when the runtime is created by using
|
||||||
|
// NewRuntimeFromConfig() instead of NewRuntime()
|
||||||
|
ConfigPath = "/etc/containers/libpod.conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A RuntimeOption is a functional option which alters the Runtime created by
|
// A RuntimeOption is a functional option which alters the Runtime created by
|
||||||
@ -155,13 +163,83 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
// Copy the default configuration
|
// Copy the default configuration
|
||||||
deepcopier.Copy(defaultRuntimeConfig).To(runtime.config)
|
deepcopier.Copy(defaultRuntimeConfig).To(runtime.config)
|
||||||
|
|
||||||
// Overwrite it with user-given configuration options
|
// Now overwrite it with the given configuration file, if it exists
|
||||||
|
// Do not fail on error, instead just use the builtin defaults
|
||||||
|
if _, err := os.Stat(ConfigPath); err == nil {
|
||||||
|
// Read the contents of the config file
|
||||||
|
contents, err := ioutil.ReadFile(ConfigPath)
|
||||||
|
if err == nil {
|
||||||
|
// Only proceed if we successfully read the file
|
||||||
|
_, err := toml.Decode(string(contents), runtime.config)
|
||||||
|
if err != nil {
|
||||||
|
// We may have just ruined our RuntimeConfig
|
||||||
|
// Make a new one to be safe
|
||||||
|
runtime.config = new(RuntimeConfig)
|
||||||
|
deepcopier.Copy(defaultRuntimeConfig).To(runtime.config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite config with user-given configuration options
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
if err := opt(runtime); err != nil {
|
if err := opt(runtime); err != nil {
|
||||||
return nil, errors.Wrapf(err, "error configuring runtime")
|
return nil, errors.Wrapf(err, "error configuring runtime")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := makeRuntime(runtime); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtime, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRuntimeFromConfig creates a new container runtime using the given
|
||||||
|
// configuration file for its default configuration. Passed RuntimeOption
|
||||||
|
// functions can be used to mutate this configuration further.
|
||||||
|
// An error will be returned if the configuration file at the given path does
|
||||||
|
// not exist or cannot be loaded
|
||||||
|
func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime *Runtime, err error) {
|
||||||
|
runtime = new(Runtime)
|
||||||
|
runtime.config = new(RuntimeConfig)
|
||||||
|
|
||||||
|
// Set two fields not in the TOML config
|
||||||
|
runtime.config.StateType = defaultRuntimeConfig.StateType
|
||||||
|
runtime.config.StorageConfig = storage.StoreOptions{}
|
||||||
|
|
||||||
|
// Check to see if the given configuration file exists
|
||||||
|
if _, err := os.Stat(configPath); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error stating configuration file %s", configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read contents of the config file
|
||||||
|
contents, err := ioutil.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error reading configuration file %s", configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode configuration file
|
||||||
|
if _, err := toml.Decode(string(contents), runtime.config); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error decoding configuration from file %s", configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the config with user-given configuration options
|
||||||
|
for _, opt := range options {
|
||||||
|
if err := opt(runtime); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error configuring runtime")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := makeRuntime(runtime); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtime, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a new runtime based on the given configuration
|
||||||
|
// Sets up containers/storage, state store, OCI runtime
|
||||||
|
func makeRuntime(runtime *Runtime) error {
|
||||||
// Find a working OCI runtime binary
|
// Find a working OCI runtime binary
|
||||||
foundRuntime := false
|
foundRuntime := false
|
||||||
for _, path := range runtime.config.RuntimePath {
|
for _, path := range runtime.config.RuntimePath {
|
||||||
@ -177,7 +255,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !foundRuntime {
|
if !foundRuntime {
|
||||||
return nil, errors.Wrapf(ErrInvalidArg,
|
return errors.Wrapf(ErrInvalidArg,
|
||||||
"could not find a working runc binary (configured options: %v)",
|
"could not find a working runc binary (configured options: %v)",
|
||||||
runtime.config.RuntimePath)
|
runtime.config.RuntimePath)
|
||||||
}
|
}
|
||||||
@ -197,7 +275,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !foundConmon {
|
if !foundConmon {
|
||||||
return nil, errors.Wrapf(ErrInvalidArg,
|
return errors.Wrapf(ErrInvalidArg,
|
||||||
"could not find a working conmon binary (configured options: %v)",
|
"could not find a working conmon binary (configured options: %v)",
|
||||||
runtime.config.RuntimePath)
|
runtime.config.RuntimePath)
|
||||||
}
|
}
|
||||||
@ -205,7 +283,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
// Set up containers/storage
|
// Set up containers/storage
|
||||||
store, err := storage.GetStore(runtime.config.StorageConfig)
|
store, err := storage.GetStore(runtime.config.StorageConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
runtime.store = store
|
runtime.store = store
|
||||||
is.Transport.SetStore(store)
|
is.Transport.SetStore(store)
|
||||||
@ -224,7 +302,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
// images
|
// images
|
||||||
storageService, err := getStorageService(runtime.store)
|
storageService, err := getStorageService(runtime.store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
runtime.storageService = storageService
|
runtime.storageService = storageService
|
||||||
|
|
||||||
@ -239,7 +317,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
runtime.config.CgroupManager, runtime.config.TmpDir,
|
runtime.config.CgroupManager, runtime.config.TmpDir,
|
||||||
runtime.config.MaxLogSize, runtime.config.NoPivotRoot)
|
runtime.config.MaxLogSize, runtime.config.NoPivotRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
runtime.ociRuntime = ociRuntime
|
runtime.ociRuntime = ociRuntime
|
||||||
|
|
||||||
@ -247,7 +325,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
if err := os.MkdirAll(runtime.config.StaticDir, 0755); err != nil {
|
if err := os.MkdirAll(runtime.config.StaticDir, 0755); err != nil {
|
||||||
// The directory is allowed to exist
|
// The directory is allowed to exist
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return nil, errors.Wrapf(err, "error creating runtime static files directory %s",
|
return errors.Wrapf(err, "error creating runtime static files directory %s",
|
||||||
runtime.config.StaticDir)
|
runtime.config.StaticDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +335,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
if err := os.MkdirAll(lockDir, 0755); err != nil {
|
if err := os.MkdirAll(lockDir, 0755); err != nil {
|
||||||
// The directory is allowed to exist
|
// The directory is allowed to exist
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return nil, errors.Wrapf(err, "error creating runtime lockfiles directory %s",
|
return errors.Wrapf(err, "error creating runtime lockfiles directory %s",
|
||||||
lockDir)
|
lockDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,7 +345,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
if err := os.MkdirAll(runtime.config.TmpDir, 0755); err != nil {
|
if err := os.MkdirAll(runtime.config.TmpDir, 0755); err != nil {
|
||||||
// The directory is allowed to exist
|
// The directory is allowed to exist
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return nil, errors.Wrapf(err, "error creating runtime temporary files directory %s",
|
return errors.Wrapf(err, "error creating runtime temporary files directory %s",
|
||||||
runtime.config.TmpDir)
|
runtime.config.TmpDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +353,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
// Set up the CNI net plugin
|
// Set up the CNI net plugin
|
||||||
netPlugin, err := ocicni.InitCNI(runtime.config.CNIConfigDir, runtime.config.CNIPluginDir...)
|
netPlugin, err := ocicni.InitCNI(runtime.config.CNIConfigDir, runtime.config.CNIPluginDir...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error configuring CNI network plugin")
|
return errors.Wrapf(err, "error configuring CNI network plugin")
|
||||||
}
|
}
|
||||||
runtime.netPlugin = netPlugin
|
runtime.netPlugin = netPlugin
|
||||||
|
|
||||||
@ -284,7 +362,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
case InMemoryStateStore:
|
case InMemoryStateStore:
|
||||||
state, err := NewInMemoryState()
|
state, err := NewInMemoryState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
runtime.state = state
|
runtime.state = state
|
||||||
case SQLiteStateStore:
|
case SQLiteStateStore:
|
||||||
@ -295,14 +373,14 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
if err := os.MkdirAll(specsDir, 0755); err != nil {
|
if err := os.MkdirAll(specsDir, 0755); err != nil {
|
||||||
// The directory is allowed to exist
|
// The directory is allowed to exist
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return nil, errors.Wrapf(err, "error creating runtime OCI specs directory %s",
|
return errors.Wrapf(err, "error creating runtime OCI specs directory %s",
|
||||||
specsDir)
|
specsDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := NewSQLState(dbPath, specsDir, runtime.lockDir, runtime)
|
state, err := NewSQLState(dbPath, specsDir, runtime.lockDir, runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
runtime.state = state
|
runtime.state = state
|
||||||
case BoltDBStateStore:
|
case BoltDBStateStore:
|
||||||
@ -310,11 +388,11 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
|
|
||||||
state, err := NewBoltState(dbPath, runtime.lockDir, runtime)
|
state, err := NewBoltState(dbPath, runtime.lockDir, runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
runtime.state = state
|
runtime.state = state
|
||||||
default:
|
default:
|
||||||
return nil, errors.Wrapf(ErrInvalidArg, "unrecognized state type passed")
|
return errors.Wrapf(ErrInvalidArg, "unrecognized state type passed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now need to see if the system has restarted
|
// We now need to see if the system has restarted
|
||||||
@ -324,7 +402,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
runtimeAliveFile := filepath.Join(runtime.config.TmpDir, "alive")
|
runtimeAliveFile := filepath.Join(runtime.config.TmpDir, "alive")
|
||||||
aliveLock, err := storage.GetLockfile(runtimeAliveLock)
|
aliveLock, err := storage.GetLockfile(runtimeAliveLock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error acquiring runtime init lock")
|
return errors.Wrapf(err, "error acquiring runtime init lock")
|
||||||
}
|
}
|
||||||
// Acquire the lock and hold it until we return
|
// Acquire the lock and hold it until we return
|
||||||
// This ensures that no two processes will be in runtime.refresh at once
|
// This ensures that no two processes will be in runtime.refresh at once
|
||||||
@ -340,10 +418,10 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
// As such, it's not really a performance concern
|
// As such, it's not really a performance concern
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
if err2 := runtime.refresh(runtimeAliveFile); err2 != nil {
|
if err2 := runtime.refresh(runtimeAliveFile); err2 != nil {
|
||||||
return nil, err2
|
return err2
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile)
|
return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +429,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
// further
|
// further
|
||||||
runtime.valid = true
|
runtime.valid = true
|
||||||
|
|
||||||
return runtime, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig returns a copy of the configuration used by the runtime
|
// GetConfig returns a copy of the configuration used by the runtime
|
||||||
|
Reference in New Issue
Block a user