diff options
Diffstat (limited to 'libpod/runtime.go')
-rw-r--r-- | libpod/runtime.go | 191 |
1 files changed, 117 insertions, 74 deletions
diff --git a/libpod/runtime.go b/libpod/runtime.go index f53cdd8b8..b3b75d791 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -217,10 +217,15 @@ type RuntimeConfig struct { EnablePortReservation bool `toml:"enable_port_reservation"` // EnableLabeling indicates wether libpod will support container labeling EnableLabeling bool `toml:"label"` + // NetworkCmdPath is the path to the slirp4netns binary + NetworkCmdPath string `toml:"network_cmd_path"` // NumLocks is the number of locks to make available for containers and // pods. NumLocks uint32 `toml:"num_locks,omitempty"` + + // EventsLogFilePath is where the events log is stored. + EventsLogFilePath string `toml:-"events_logfile_path"` } // runtimeConfiguredFrom is a struct used during early runtime init to help @@ -236,6 +241,12 @@ type runtimeConfiguredFrom struct { libpodStaticDirSet bool libpodTmpDirSet bool volPathSet bool + conmonPath bool + conmonEnvVars bool + ociRuntimes bool + runtimePath bool + cniPluginDir bool + noPivotRoot bool } var ( @@ -319,6 +330,22 @@ func SetXdgRuntimeDir(val string) error { // NewRuntime creates a new container runtime // Options can be passed to override the default configuration for the runtime func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { + return newRuntimeFromConfig("", options...) +} + +// 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(userConfigPath string, options ...RuntimeOption) (runtime *Runtime, err error) { + if userConfigPath == "" { + return nil, errors.New("invalid configuration file specified") + } + return newRuntimeFromConfig(userConfigPath, options...) +} + +func newRuntimeFromConfig(userConfigPath string, options ...RuntimeOption) (runtime *Runtime, err error) { runtime = new(Runtime) runtime.config = new(RuntimeConfig) runtime.configuredFrom = new(runtimeConfiguredFrom) @@ -333,7 +360,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { storageConf, err := util.GetDefaultStoreOptions() if err != nil { - return nil, errors.Wrapf(err, "error retrieving rootless storage config") + return nil, errors.Wrapf(err, "error retrieving storage config") } runtime.config.StorageConfig = storageConf runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod") @@ -353,11 +380,6 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { rootlessConfigPath = filepath.Join(home, ".config/containers/libpod.conf") - configPath = rootlessConfigPath - if _, err := os.Stat(configPath); err != nil { - foundConfig = false - } - runtimeDir, err := util.GetRootlessRuntimeDir() if err != nil { return nil, err @@ -365,11 +387,24 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { // containers/image uses XDG_RUNTIME_DIR to locate the auth file. // So make sure the env variable is set. - err = SetXdgRuntimeDir(runtimeDir) - if err != nil { + if err := SetXdgRuntimeDir(runtimeDir); err != nil { return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") } + } + + if userConfigPath != "" { + configPath = userConfigPath + if _, err := os.Stat(configPath); err != nil { + // If the user specified a config file, we must fail immediately + // when it doesn't exist + return nil, errors.Wrapf(err, "cannot stat %s", configPath) + } + } else if rootless.IsRootless() { + configPath = rootlessConfigPath + if _, err := os.Stat(configPath); err != nil { + foundConfig = false + } } else if _, err := os.Stat(OverrideConfigPath); err == nil { // Use the override configuration path configPath = OverrideConfigPath @@ -405,6 +440,24 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { if tmpConfig.VolumePath != "" { runtime.configuredFrom.volPathSet = true } + if tmpConfig.ConmonPath != nil { + runtime.configuredFrom.conmonPath = true + } + if tmpConfig.ConmonEnvVars != nil { + runtime.configuredFrom.conmonEnvVars = true + } + if tmpConfig.OCIRuntimes != nil { + runtime.configuredFrom.ociRuntimes = true + } + if tmpConfig.RuntimePath != nil { + runtime.configuredFrom.runtimePath = true + } + if tmpConfig.CNIPluginDir != nil { + runtime.configuredFrom.cniPluginDir = true + } + if tmpConfig.NoPivotRoot { + runtime.configuredFrom.noPivotRoot = true + } if _, err := toml.Decode(string(contents), runtime.config); err != nil { return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath) @@ -424,12 +477,24 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { } // Cherry pick the settings we want from the global configuration - 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 + if !runtime.configuredFrom.conmonPath { + runtime.config.ConmonPath = tmpConfig.ConmonPath + } + if !runtime.configuredFrom.conmonEnvVars { + runtime.config.ConmonEnvVars = tmpConfig.ConmonEnvVars + } + if !runtime.configuredFrom.ociRuntimes { + runtime.config.OCIRuntimes = tmpConfig.OCIRuntimes + } + if !runtime.configuredFrom.runtimePath { + runtime.config.RuntimePath = tmpConfig.RuntimePath + } + if !runtime.configuredFrom.cniPluginDir { + runtime.config.CNIPluginDir = tmpConfig.CNIPluginDir + } + if !runtime.configuredFrom.noPivotRoot { + runtime.config.NoPivotRoot = tmpConfig.NoPivotRoot + } break } } @@ -440,77 +505,39 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { return nil, errors.Wrapf(err, "error configuring runtime") } } - if err := makeRuntime(runtime); err != nil { - return nil, err - } - - if !foundConfig && rootlessConfigPath != "" { - os.MkdirAll(filepath.Dir(rootlessConfigPath), 0755) - file, err := os.OpenFile(rootlessConfigPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) - if err != nil && !os.IsExist(err) { - return nil, errors.Wrapf(err, "cannot open file %s", rootlessConfigPath) - } - if err == nil { - defer file.Close() - enc := toml.NewEncoder(file) - if err := enc.Encode(runtime.config); err != nil { - os.Remove(rootlessConfigPath) + if rootlessConfigPath != "" { + // storage.conf + storageConfFile := util.StorageConfigFile() + if _, err := os.Stat(storageConfFile); os.IsNotExist(err) { + if err := util.WriteStorageConfigFile(&runtime.config.StorageConfig, storageConfFile); err != nil { + return nil, errors.Wrapf(err, "cannot write config file %s", storageConfFile) } } - } - - 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) - runtime.configuredFrom = new(runtimeConfiguredFrom) - - // 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 - if _, err := os.Stat(configPath); err != nil { - return nil, errors.Wrapf(err, "error checking existence of 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 !foundConfig { + os.MkdirAll(filepath.Dir(rootlessConfigPath), 0755) + file, err := os.OpenFile(rootlessConfigPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if err != nil && !os.IsExist(err) { + return nil, errors.Wrapf(err, "cannot open file %s", rootlessConfigPath) + } + if err == nil { + defer file.Close() + enc := toml.NewEncoder(file) + if err := enc.Encode(runtime.config); err != nil { + os.Remove(rootlessConfigPath) + } + } } } - 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) (err error) { - // Backward compatibility for `runtime_path` if runtime.config.RuntimePath != nil { // Don't print twice in rootless mode. @@ -669,6 +696,8 @@ func makeRuntime(runtime *Runtime) (err error) { runtime.config.VolumePath = dbConfig.VolumePath } + runtime.config.EventsLogFilePath = filepath.Join(runtime.config.TmpDir, "events", "events.log") + logrus.Debugf("Using graph driver %s", runtime.config.StorageConfig.GraphDriverName) logrus.Debugf("Using graph root %s", runtime.config.StorageConfig.GraphRoot) logrus.Debugf("Using run root %s", runtime.config.StorageConfig.RunRoot) @@ -711,6 +740,9 @@ func makeRuntime(runtime *Runtime) (err error) { // Setting signaturepolicypath ir.SignaturePolicyPath = runtime.config.SignaturePolicyPath + // Set logfile path for events + ir.EventsLogFilePath = runtime.config.EventsLogFilePath + defer func() { if err != nil && store != nil { // Don't forcibly shut down @@ -743,6 +775,14 @@ func makeRuntime(runtime *Runtime) (err error) { } } + // Create events log dir + if err := os.MkdirAll(filepath.Dir(runtime.config.EventsLogFilePath), 0700); err != nil { + // The directory is allowed to exist + if !os.IsExist(err) { + return errors.Wrapf(err, "error creating events dirs %s", filepath.Dir(runtime.config.EventsLogFilePath)) + } + } + // Make an OCI runtime to perform container operations ociRuntime, err := newOCIRuntime(runtime.ociRuntimePath, runtime.conmonPath, runtime.config.ConmonEnvVars, @@ -948,9 +988,12 @@ func (r *Runtime) refreshRootless() error { // Take advantage of a command that requires a new userns // so that we are running as the root user and able to use refresh() cmd := exec.Command(os.Args[0], "info") - err := cmd.Run() - if err != nil { - return errors.Wrapf(err, "Error running %s info while refreshing state", os.Args[0]) + + if output, err := cmd.CombinedOutput(); err != nil { + if _, ok := err.(*exec.ExitError); !ok { + return errors.Wrapf(err, "Error waiting for info while refreshing state: %s", os.Args[0]) + } + return errors.Wrapf(err, "Error running %s info while refreshing state: %s", os.Args[0], output) } return nil } |