mirror of https://github.com/containers/podman.git
Merge pull request #1918 from mheon/use_db_paths
Use paths written in DB instead if they differ from our defaults
This commit is contained in:
commit
50e754cd57
|
@ -67,7 +67,7 @@ func createCmd(c *cli.Context) error {
|
||||||
rootless.SetSkipStorageSetup(true)
|
rootless.SetSkipStorageSetup(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := libpodruntime.GetContainerRuntime(c)
|
runtime, err := libpodruntime.GetRuntime(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating libpod runtime")
|
return errors.Wrapf(err, "error creating libpod runtime")
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,32 +11,18 @@ import (
|
||||||
|
|
||||||
// GetRuntime generates a new libpod runtime configured by command line options
|
// GetRuntime generates a new libpod runtime configured by command line options
|
||||||
func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
||||||
storageOpts, err := util.GetDefaultStoreOptions()
|
storageOpts := new(storage.StoreOptions)
|
||||||
if err != nil {
|
options := []libpod.RuntimeOption{}
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return GetRuntimeWithStorageOpts(c, &storageOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetContainerRuntime generates a new libpod runtime configured by command line options for containers
|
if c.IsSet("uidmap") || c.IsSet("gidmap") || c.IsSet("subuidmap") || c.IsSet("subgidmap") {
|
||||||
func GetContainerRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
|
||||||
mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap"))
|
mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
storageOpts, err := util.GetDefaultStoreOptions()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
storageOpts.UIDMap = mappings.UIDMap
|
storageOpts.UIDMap = mappings.UIDMap
|
||||||
storageOpts.GIDMap = mappings.GIDMap
|
storageOpts.GIDMap = mappings.GIDMap
|
||||||
return GetRuntimeWithStorageOpts(c, &storageOpts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRuntime generates a new libpod runtime configured by command line options
|
|
||||||
func GetRuntimeWithStorageOpts(c *cli.Context, storageOpts *storage.StoreOptions) (*libpod.Runtime, error) {
|
|
||||||
options := []libpod.RuntimeOption{}
|
|
||||||
|
|
||||||
if c.GlobalIsSet("root") {
|
if c.GlobalIsSet("root") {
|
||||||
storageOpts.GraphRoot = c.GlobalString("root")
|
storageOpts.GraphRoot = c.GlobalString("root")
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ func runCmd(c *cli.Context) error {
|
||||||
rootless.SetSkipStorageSetup(true)
|
rootless.SetSkipStorageSetup(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := libpodruntime.GetContainerRuntime(c)
|
runtime, err := libpodruntime.GetRuntime(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating libpod runtime")
|
return errors.Wrapf(err, "error creating libpod runtime")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package libpod
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -19,7 +18,6 @@ type BoltState struct {
|
||||||
dbLock sync.Mutex
|
dbLock sync.Mutex
|
||||||
namespace string
|
namespace string
|
||||||
namespaceBytes []byte
|
namespaceBytes []byte
|
||||||
lockDir string
|
|
||||||
runtime *Runtime
|
runtime *Runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,25 +50,15 @@ type BoltState struct {
|
||||||
// containers/storage do not occur.
|
// containers/storage do not occur.
|
||||||
|
|
||||||
// NewBoltState creates a new bolt-backed state database
|
// NewBoltState creates a new bolt-backed state database
|
||||||
func NewBoltState(path, lockDir string, runtime *Runtime) (State, error) {
|
func NewBoltState(path string, runtime *Runtime) (State, error) {
|
||||||
state := new(BoltState)
|
state := new(BoltState)
|
||||||
state.dbPath = path
|
state.dbPath = path
|
||||||
state.lockDir = lockDir
|
|
||||||
state.runtime = runtime
|
state.runtime = runtime
|
||||||
state.namespace = ""
|
state.namespace = ""
|
||||||
state.namespaceBytes = nil
|
state.namespaceBytes = nil
|
||||||
|
|
||||||
logrus.Debugf("Initializing boltdb state at %s", path)
|
logrus.Debugf("Initializing boltdb state at %s", path)
|
||||||
|
|
||||||
// Make the directory that will hold container lockfiles
|
|
||||||
if err := os.MkdirAll(lockDir, 0750); err != nil {
|
|
||||||
// The directory is allowed to exist
|
|
||||||
if !os.IsExist(err) {
|
|
||||||
return nil, errors.Wrapf(err, "error creating lockfiles dir %s", lockDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.lockDir = lockDir
|
|
||||||
|
|
||||||
db, err := bolt.Open(path, 0600, nil)
|
db, err := bolt.Open(path, 0600, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error opening database %s", path)
|
return nil, errors.Wrapf(err, "error opening database %s", path)
|
||||||
|
@ -115,11 +103,6 @@ func NewBoltState(path, lockDir string, runtime *Runtime) (State, error) {
|
||||||
return nil, errors.Wrapf(err, "error creating initial database layout")
|
return nil, errors.Wrapf(err, "error creating initial database layout")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check runtime configuration
|
|
||||||
if err := checkRuntimeConfig(db, runtime); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
state.valid = true
|
state.valid = true
|
||||||
|
|
||||||
return state, nil
|
return state, nil
|
||||||
|
@ -240,6 +223,72 @@ func (s *BoltState) Refresh() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDBConfig retrieves runtime configuration fields that were created when
|
||||||
|
// the database was first initialized
|
||||||
|
func (s *BoltState) GetDBConfig() (*DBConfig, error) {
|
||||||
|
if !s.valid {
|
||||||
|
return nil, ErrDBClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := new(DBConfig)
|
||||||
|
|
||||||
|
db, err := s.getDBCon()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.closeDBCon(db)
|
||||||
|
|
||||||
|
err = db.View(func(tx *bolt.Tx) error {
|
||||||
|
configBucket, err := getRuntimeConfigBucket(tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some of these may be nil
|
||||||
|
// When we convert to string, Go will coerce them to ""
|
||||||
|
// That's probably fine - we could raise an error if the key is
|
||||||
|
// missing, but just not including it is also OK.
|
||||||
|
libpodRoot := configBucket.Get(staticDirKey)
|
||||||
|
libpodTmp := configBucket.Get(tmpDirKey)
|
||||||
|
storageRoot := configBucket.Get(graphRootKey)
|
||||||
|
storageTmp := configBucket.Get(runRootKey)
|
||||||
|
graphDriver := configBucket.Get(graphDriverKey)
|
||||||
|
|
||||||
|
cfg.LibpodRoot = string(libpodRoot)
|
||||||
|
cfg.LibpodTmp = string(libpodTmp)
|
||||||
|
cfg.StorageRoot = string(storageRoot)
|
||||||
|
cfg.StorageTmp = string(storageTmp)
|
||||||
|
cfg.GraphDriver = string(graphDriver)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateDBConfig validates paths in the given runtime against the database
|
||||||
|
func (s *BoltState) ValidateDBConfig(runtime *Runtime) error {
|
||||||
|
if !s.valid {
|
||||||
|
return ErrDBClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := s.getDBCon()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer s.closeDBCon(db)
|
||||||
|
|
||||||
|
// Check runtime configuration
|
||||||
|
if err := checkRuntimeConfig(db, runtime); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetNamespace sets the namespace that will be used for container and pod
|
// SetNamespace sets the namespace that will be used for container and pod
|
||||||
// retrieval
|
// retrieval
|
||||||
func (s *BoltState) SetNamespace(ns string) error {
|
func (s *BoltState) SetNamespace(ns string) error {
|
||||||
|
|
|
@ -30,6 +30,13 @@ const (
|
||||||
containersName = "containers"
|
containersName = "containers"
|
||||||
podIDName = "pod-id"
|
podIDName = "pod-id"
|
||||||
namespaceName = "namespace"
|
namespaceName = "namespace"
|
||||||
|
|
||||||
|
staticDirName = "static-dir"
|
||||||
|
tmpDirName = "tmp-dir"
|
||||||
|
runRootName = "run-root"
|
||||||
|
graphRootName = "graph-root"
|
||||||
|
graphDriverName = "graph-driver-name"
|
||||||
|
osName = "os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -49,21 +56,19 @@ var (
|
||||||
containersBkt = []byte(containersName)
|
containersBkt = []byte(containersName)
|
||||||
podIDKey = []byte(podIDName)
|
podIDKey = []byte(podIDName)
|
||||||
namespaceKey = []byte(namespaceName)
|
namespaceKey = []byte(namespaceName)
|
||||||
|
|
||||||
|
staticDirKey = []byte(staticDirName)
|
||||||
|
tmpDirKey = []byte(tmpDirName)
|
||||||
|
runRootKey = []byte(runRootName)
|
||||||
|
graphRootKey = []byte(graphRootName)
|
||||||
|
graphDriverKey = []byte(graphDriverName)
|
||||||
|
osKey = []byte(osName)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check if the configuration of the database is compatible with the
|
// Check if the configuration of the database is compatible with the
|
||||||
// configuration of the runtime opening it
|
// configuration of the runtime opening it
|
||||||
// If there is no runtime configuration loaded, load our own
|
// If there is no runtime configuration loaded, load our own
|
||||||
func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error {
|
func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error {
|
||||||
var (
|
|
||||||
staticDir = []byte("static-dir")
|
|
||||||
tmpDir = []byte("tmp-dir")
|
|
||||||
runRoot = []byte("run-root")
|
|
||||||
graphRoot = []byte("graph-root")
|
|
||||||
graphDriverName = []byte("graph-driver-name")
|
|
||||||
osKey = []byte("os")
|
|
||||||
)
|
|
||||||
|
|
||||||
err := db.Update(func(tx *bolt.Tx) error {
|
err := db.Update(func(tx *bolt.Tx) error {
|
||||||
configBkt, err := getRuntimeConfigBucket(tx)
|
configBkt, err := getRuntimeConfigBucket(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -74,31 +79,31 @@ func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateDBAgainstConfig(configBkt, "static dir",
|
if err := validateDBAgainstConfig(configBkt, "libpod root directory (staticdir)",
|
||||||
rt.config.StaticDir, staticDir, ""); err != nil {
|
rt.config.StaticDir, staticDirKey, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateDBAgainstConfig(configBkt, "tmp dir",
|
if err := validateDBAgainstConfig(configBkt, "libpod temporary files directory (tmpdir)",
|
||||||
rt.config.TmpDir, tmpDir, ""); err != nil {
|
rt.config.TmpDir, tmpDirKey, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateDBAgainstConfig(configBkt, "run root",
|
if err := validateDBAgainstConfig(configBkt, "storage temporary directory (runroot)",
|
||||||
rt.config.StorageConfig.RunRoot, runRoot,
|
rt.config.StorageConfig.RunRoot, runRootKey,
|
||||||
storage.DefaultStoreOptions.RunRoot); err != nil {
|
storage.DefaultStoreOptions.RunRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateDBAgainstConfig(configBkt, "graph root",
|
if err := validateDBAgainstConfig(configBkt, "storage graph root directory (graphroot)",
|
||||||
rt.config.StorageConfig.GraphRoot, graphRoot,
|
rt.config.StorageConfig.GraphRoot, graphRootKey,
|
||||||
storage.DefaultStoreOptions.GraphRoot); err != nil {
|
storage.DefaultStoreOptions.GraphRoot); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return validateDBAgainstConfig(configBkt, "graph driver name",
|
return validateDBAgainstConfig(configBkt, "storage graph driver",
|
||||||
rt.config.StorageConfig.GraphDriverName,
|
rt.config.StorageConfig.GraphDriverName,
|
||||||
graphDriverName,
|
graphDriverKey,
|
||||||
storage.DefaultStoreOptions.GraphDriverName)
|
storage.DefaultStoreOptions.GraphDriverName)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -261,7 +266,7 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the lock
|
// Get the lock
|
||||||
lockPath := filepath.Join(s.lockDir, string(id))
|
lockPath := filepath.Join(s.runtime.lockDir, string(id))
|
||||||
lock, err := storage.GetLockfile(lockPath)
|
lock, err := storage.GetLockfile(lockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error retrieving lockfile for container %s", string(id))
|
return errors.Wrapf(err, "error retrieving lockfile for container %s", string(id))
|
||||||
|
@ -297,7 +302,7 @@ func (s *BoltState) getPodFromDB(id []byte, pod *Pod, podBkt *bolt.Bucket) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the lock
|
// Get the lock
|
||||||
lockPath := filepath.Join(s.lockDir, string(id))
|
lockPath := filepath.Join(s.runtime.lockDir, string(id))
|
||||||
lock, err := storage.GetLockfile(lockPath)
|
lock, err := storage.GetLockfile(lockPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error retrieving lockfile for pod %s", string(id))
|
return errors.Wrapf(err, "error retrieving lockfile for pod %s", string(id))
|
||||||
|
|
|
@ -73,6 +73,18 @@ func (s *InMemoryState) Refresh() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDBConfig is not implemented for in-memory state.
|
||||||
|
// As we do not store a config, return an empty one.
|
||||||
|
func (s *InMemoryState) GetDBConfig() (*DBConfig, error) {
|
||||||
|
return &DBConfig{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateDBConfig is not implemented for the in-memory state.
|
||||||
|
// Since we do nothing just return no error.
|
||||||
|
func (s *InMemoryState) ValidateDBConfig(runtime *Runtime) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetNamespace sets the namespace for container and pod retrieval.
|
// SetNamespace sets the namespace for container and pod retrieval.
|
||||||
func (s *InMemoryState) SetNamespace(ns string) error {
|
func (s *InMemoryState) SetNamespace(ns string) error {
|
||||||
s.namespace = ns
|
s.namespace = ns
|
||||||
|
|
|
@ -29,19 +29,40 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption {
|
||||||
return ErrRuntimeFinalized
|
return ErrRuntimeFinalized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.RunRoot != "" {
|
||||||
rt.config.StorageConfig.RunRoot = config.RunRoot
|
rt.config.StorageConfig.RunRoot = config.RunRoot
|
||||||
rt.config.StorageConfig.GraphRoot = config.GraphRoot
|
rt.configuredFrom.storageRunRootSet = true
|
||||||
rt.config.StorageConfig.GraphDriverName = config.GraphDriverName
|
}
|
||||||
rt.config.StaticDir = filepath.Join(config.GraphRoot, "libpod")
|
|
||||||
|
|
||||||
|
if config.GraphRoot != "" {
|
||||||
|
rt.config.StorageConfig.GraphRoot = config.GraphRoot
|
||||||
|
rt.configuredFrom.storageGraphRootSet = true
|
||||||
|
|
||||||
|
// Also set libpod static dir, so we are a subdirectory
|
||||||
|
// of the c/storage store by default
|
||||||
|
rt.config.StaticDir = filepath.Join(config.GraphRoot, "libpod")
|
||||||
|
rt.configuredFrom.libpodStaticDirSet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.GraphDriverName != "" {
|
||||||
|
rt.config.StorageConfig.GraphDriverName = config.GraphDriverName
|
||||||
|
rt.configuredFrom.storageGraphDriverSet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.GraphDriverOptions != nil {
|
||||||
rt.config.StorageConfig.GraphDriverOptions = make([]string, len(config.GraphDriverOptions))
|
rt.config.StorageConfig.GraphDriverOptions = make([]string, len(config.GraphDriverOptions))
|
||||||
copy(rt.config.StorageConfig.GraphDriverOptions, config.GraphDriverOptions)
|
copy(rt.config.StorageConfig.GraphDriverOptions, config.GraphDriverOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.UIDMap != nil {
|
||||||
rt.config.StorageConfig.UIDMap = make([]idtools.IDMap, len(config.UIDMap))
|
rt.config.StorageConfig.UIDMap = make([]idtools.IDMap, len(config.UIDMap))
|
||||||
copy(rt.config.StorageConfig.UIDMap, config.UIDMap)
|
copy(rt.config.StorageConfig.UIDMap, config.UIDMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.GIDMap != nil {
|
||||||
rt.config.StorageConfig.GIDMap = make([]idtools.IDMap, len(config.GIDMap))
|
rt.config.StorageConfig.GIDMap = make([]idtools.IDMap, len(config.GIDMap))
|
||||||
copy(rt.config.StorageConfig.GIDMap, config.GIDMap)
|
copy(rt.config.StorageConfig.GIDMap, config.GIDMap)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -174,6 +195,7 @@ func WithStaticDir(dir string) RuntimeOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.config.StaticDir = dir
|
rt.config.StaticDir = dir
|
||||||
|
rt.configuredFrom.libpodStaticDirSet = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -225,6 +247,7 @@ func WithTmpDir(dir string) RuntimeOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.config.TmpDir = dir
|
rt.config.TmpDir = dir
|
||||||
|
rt.configuredFrom.libpodTmpDirSet = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,7 @@ type Runtime struct {
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
imageRuntime *image.Runtime
|
imageRuntime *image.Runtime
|
||||||
firewallBackend firewall.FirewallBackend
|
firewallBackend firewall.FirewallBackend
|
||||||
|
configuredFrom *runtimeConfiguredFrom
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuntimeConfig contains configuration options used to set up the runtime
|
// RuntimeConfig contains configuration options used to set up the runtime
|
||||||
|
@ -174,6 +175,20 @@ type RuntimeConfig struct {
|
||||||
EnableLabeling bool `toml:"label"`
|
EnableLabeling bool `toml:"label"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runtimeConfiguredFrom is a struct used during early runtime init to help
|
||||||
|
// assemble the full RuntimeConfig struct from defaults.
|
||||||
|
// It indicated whether several fields in the runtime configuration were set
|
||||||
|
// explicitly.
|
||||||
|
// If they were not, we may override them with information from the database,
|
||||||
|
// if it exists and differs from what is present in the system already.
|
||||||
|
type runtimeConfiguredFrom struct {
|
||||||
|
storageGraphDriverSet bool
|
||||||
|
storageGraphRootSet bool
|
||||||
|
storageRunRootSet bool
|
||||||
|
libpodStaticDirSet bool
|
||||||
|
libpodTmpDirSet bool
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultRuntimeConfig = RuntimeConfig{
|
defaultRuntimeConfig = RuntimeConfig{
|
||||||
// Leave this empty so containers/storage will use its defaults
|
// Leave this empty so containers/storage will use its defaults
|
||||||
|
@ -251,6 +266,7 @@ func SetXdgRuntimeDir(val string) error {
|
||||||
func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
||||||
runtime = new(Runtime)
|
runtime = new(Runtime)
|
||||||
runtime.config = new(RuntimeConfig)
|
runtime.config = new(RuntimeConfig)
|
||||||
|
runtime.configuredFrom = new(runtimeConfiguredFrom)
|
||||||
|
|
||||||
// Copy the default configuration
|
// Copy the default configuration
|
||||||
tmpDir, err := getDefaultTmpDir()
|
tmpDir, err := getDefaultTmpDir()
|
||||||
|
@ -260,6 +276,16 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
||||||
deepcopier.Copy(defaultRuntimeConfig).To(runtime.config)
|
deepcopier.Copy(defaultRuntimeConfig).To(runtime.config)
|
||||||
runtime.config.TmpDir = tmpDir
|
runtime.config.TmpDir = tmpDir
|
||||||
|
|
||||||
|
if rootless.IsRootless() {
|
||||||
|
// If we're rootless, override the default storage config
|
||||||
|
storageConf, err := util.GetDefaultStoreOptions()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error retrieving rootless storage config")
|
||||||
|
}
|
||||||
|
runtime.config.StorageConfig = storageConf
|
||||||
|
runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
|
||||||
|
}
|
||||||
|
|
||||||
configPath := ConfigPath
|
configPath := ConfigPath
|
||||||
foundConfig := true
|
foundConfig := true
|
||||||
rootlessConfigPath := ""
|
rootlessConfigPath := ""
|
||||||
|
@ -305,6 +331,25 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error reading configuration file %s", configPath)
|
return nil, errors.Wrapf(err, "error reading configuration file %s", configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is ugly, but we need to decode twice.
|
||||||
|
// Once to check if libpod static and tmp dirs were explicitly
|
||||||
|
// set (not enough to check if they're not the default value,
|
||||||
|
// might have been explicitly configured to the default).
|
||||||
|
// A second time to actually get a usable config.
|
||||||
|
tmpConfig := new(RuntimeConfig)
|
||||||
|
if _, err := toml.Decode(string(contents), tmpConfig); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error decoding configuration file %s",
|
||||||
|
configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tmpConfig.StaticDir != "" {
|
||||||
|
runtime.configuredFrom.libpodStaticDirSet = true
|
||||||
|
}
|
||||||
|
if tmpConfig.TmpDir != "" {
|
||||||
|
runtime.configuredFrom.libpodTmpDirSet = true
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := toml.Decode(string(contents), runtime.config); err != nil {
|
if _, err := toml.Decode(string(contents), runtime.config); err != nil {
|
||||||
return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath)
|
return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath)
|
||||||
}
|
}
|
||||||
|
@ -346,6 +391,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
||||||
func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime *Runtime, err error) {
|
func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime *Runtime, err error) {
|
||||||
runtime = new(Runtime)
|
runtime = new(Runtime)
|
||||||
runtime.config = new(RuntimeConfig)
|
runtime.config = new(RuntimeConfig)
|
||||||
|
runtime.configuredFrom = new(runtimeConfiguredFrom)
|
||||||
|
|
||||||
// Set two fields not in the TOML config
|
// Set two fields not in the TOML config
|
||||||
runtime.config.StateType = defaultRuntimeConfig.StateType
|
runtime.config.StateType = defaultRuntimeConfig.StateType
|
||||||
|
@ -424,6 +470,77 @@ func makeRuntime(runtime *Runtime) (err error) {
|
||||||
runtime.config.ConmonPath)
|
runtime.config.ConmonPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make the static files directory if it does not exist
|
||||||
|
if err := os.MkdirAll(runtime.config.StaticDir, 0700); err != nil {
|
||||||
|
// The directory is allowed to exist
|
||||||
|
if !os.IsExist(err) {
|
||||||
|
return errors.Wrapf(err, "error creating runtime static files directory %s",
|
||||||
|
runtime.config.StaticDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the state
|
||||||
|
switch runtime.config.StateType {
|
||||||
|
case InMemoryStateStore:
|
||||||
|
state, err := NewInMemoryState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
runtime.state = state
|
||||||
|
case SQLiteStateStore:
|
||||||
|
return errors.Wrapf(ErrInvalidArg, "SQLite state is currently disabled")
|
||||||
|
case BoltDBStateStore:
|
||||||
|
dbPath := filepath.Join(runtime.config.StaticDir, "bolt_state.db")
|
||||||
|
|
||||||
|
state, err := NewBoltState(dbPath, runtime)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
runtime.state = state
|
||||||
|
default:
|
||||||
|
return errors.Wrapf(ErrInvalidArg, "unrecognized state type passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab config from the database so we can reset some defaults
|
||||||
|
dbConfig, err := runtime.state.GetDBConfig()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error retrieving runtime configuration from database")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset defaults if they were not explicitly set
|
||||||
|
if !runtime.configuredFrom.storageGraphDriverSet && dbConfig.GraphDriver != "" {
|
||||||
|
runtime.config.StorageConfig.GraphDriverName = dbConfig.GraphDriver
|
||||||
|
}
|
||||||
|
if !runtime.configuredFrom.storageGraphRootSet && dbConfig.StorageRoot != "" {
|
||||||
|
runtime.config.StorageConfig.GraphRoot = dbConfig.StorageRoot
|
||||||
|
}
|
||||||
|
if !runtime.configuredFrom.storageRunRootSet && dbConfig.StorageTmp != "" {
|
||||||
|
runtime.config.StorageConfig.RunRoot = dbConfig.StorageTmp
|
||||||
|
}
|
||||||
|
if !runtime.configuredFrom.libpodStaticDirSet && dbConfig.LibpodRoot != "" {
|
||||||
|
runtime.config.StaticDir = dbConfig.LibpodRoot
|
||||||
|
}
|
||||||
|
if !runtime.configuredFrom.libpodTmpDirSet && dbConfig.LibpodTmp != "" {
|
||||||
|
runtime.config.TmpDir = dbConfig.LibpodTmp
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
logrus.Debugf("Using static dir %s", runtime.config.StaticDir)
|
||||||
|
logrus.Debugf("Using tmp dir %s", runtime.config.TmpDir)
|
||||||
|
|
||||||
|
// Validate our config against the database, now that we've set our
|
||||||
|
// final storage configuration
|
||||||
|
if err := runtime.state.ValidateDBConfig(runtime); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := runtime.state.SetNamespace(runtime.config.Namespace); err != nil {
|
||||||
|
return errors.Wrapf(err, "error setting libpod namespace in state")
|
||||||
|
}
|
||||||
|
logrus.Debugf("Set libpod namespace to %q", runtime.config.Namespace)
|
||||||
|
|
||||||
// Set up containers/storage
|
// Set up containers/storage
|
||||||
var store storage.Store
|
var store storage.Store
|
||||||
if rootless.SkipStorageSetup() {
|
if rootless.SkipStorageSetup() {
|
||||||
|
@ -491,15 +608,6 @@ func makeRuntime(runtime *Runtime) (err error) {
|
||||||
}
|
}
|
||||||
runtime.ociRuntime = ociRuntime
|
runtime.ociRuntime = ociRuntime
|
||||||
|
|
||||||
// Make the static files directory if it does not exist
|
|
||||||
if err := os.MkdirAll(runtime.config.StaticDir, 0755); err != nil {
|
|
||||||
// The directory is allowed to exist
|
|
||||||
if !os.IsExist(err) {
|
|
||||||
return errors.Wrapf(err, "error creating runtime static files directory %s",
|
|
||||||
runtime.config.StaticDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a directory to hold container lockfiles
|
// Make a directory to hold container lockfiles
|
||||||
lockDir := filepath.Join(runtime.config.TmpDir, "lock")
|
lockDir := filepath.Join(runtime.config.TmpDir, "lock")
|
||||||
if err := os.MkdirAll(lockDir, 0755); err != nil {
|
if err := os.MkdirAll(lockDir, 0755); err != nil {
|
||||||
|
@ -540,33 +648,6 @@ func makeRuntime(runtime *Runtime) (err error) {
|
||||||
}
|
}
|
||||||
runtime.firewallBackend = fwBackend
|
runtime.firewallBackend = fwBackend
|
||||||
|
|
||||||
// Set up the state
|
|
||||||
switch runtime.config.StateType {
|
|
||||||
case InMemoryStateStore:
|
|
||||||
state, err := NewInMemoryState()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
runtime.state = state
|
|
||||||
case SQLiteStateStore:
|
|
||||||
return errors.Wrapf(ErrInvalidArg, "SQLite state is currently disabled")
|
|
||||||
case BoltDBStateStore:
|
|
||||||
dbPath := filepath.Join(runtime.config.StaticDir, "bolt_state.db")
|
|
||||||
|
|
||||||
state, err := NewBoltState(dbPath, runtime.lockDir, runtime)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
runtime.state = state
|
|
||||||
default:
|
|
||||||
return errors.Wrapf(ErrInvalidArg, "unrecognized state type passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runtime.state.SetNamespace(runtime.config.Namespace); err != nil {
|
|
||||||
return errors.Wrapf(err, "error setting libpod namespace in state")
|
|
||||||
}
|
|
||||||
logrus.Debugf("Set libpod namespace to %q", runtime.config.Namespace)
|
|
||||||
|
|
||||||
// We now need to see if the system has restarted
|
// We now need to see if the system has restarted
|
||||||
// We check for the presence of a file in our tmp directory to verify this
|
// We check for the presence of a file in our tmp directory to verify this
|
||||||
// This check must be locked to prevent races
|
// This check must be locked to prevent races
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
package libpod
|
package libpod
|
||||||
|
|
||||||
|
// DBConfig is a set of Libpod runtime configuration settings that are saved
|
||||||
|
// in a State when it is first created, and can subsequently be retrieved.
|
||||||
|
type DBConfig struct {
|
||||||
|
LibpodRoot string
|
||||||
|
LibpodTmp string
|
||||||
|
StorageRoot string
|
||||||
|
StorageTmp string
|
||||||
|
GraphDriver string
|
||||||
|
}
|
||||||
|
|
||||||
// State is a storage backend for libpod's current state.
|
// State is a storage backend for libpod's current state.
|
||||||
// A State is only initialized once per instance of libpod.
|
// A State is only initialized once per instance of libpod.
|
||||||
// As such, initialization methods for State implementations may safely assume
|
// As such, initialization methods for State implementations may safely assume
|
||||||
|
@ -21,6 +31,22 @@ type State interface {
|
||||||
// Refresh clears container and pod states after a reboot
|
// Refresh clears container and pod states after a reboot
|
||||||
Refresh() error
|
Refresh() error
|
||||||
|
|
||||||
|
// GetDBConfig retrieves several paths configured within the database
|
||||||
|
// when it was created - namely, Libpod root and tmp dirs, c/storage
|
||||||
|
// root and tmp dirs, and c/storage graph driver.
|
||||||
|
// This is not implemented by the in-memory state, as it has no need to
|
||||||
|
// validate runtime configuration.
|
||||||
|
GetDBConfig() (*DBConfig, error)
|
||||||
|
|
||||||
|
// ValidateDBConfig validates the config in the given Runtime struct
|
||||||
|
// against paths stored in the configured database.
|
||||||
|
// Libpod root and tmp dirs and c/storage root and tmp dirs and graph
|
||||||
|
// driver are validated.
|
||||||
|
// This is not implemented by the in-memory state, as it has no need to
|
||||||
|
// validate runtime configuration that may change over multiple runs of
|
||||||
|
// the program.
|
||||||
|
ValidateDBConfig(runtime *Runtime) error
|
||||||
|
|
||||||
// SetNamespace() sets the namespace for the store, and will determine
|
// SetNamespace() sets the namespace for the store, and will determine
|
||||||
// what containers are retrieved with container and pod retrieval calls.
|
// what containers are retrieved with container and pod retrieval calls.
|
||||||
// A namespace of "", the empty string, acts as no namespace, and
|
// A namespace of "", the empty string, acts as no namespace, and
|
||||||
|
|
|
@ -45,11 +45,16 @@ func getEmptyBoltState() (s State, p string, p2 string, err error) {
|
||||||
dbPath := filepath.Join(tmpDir, "db.sql")
|
dbPath := filepath.Join(tmpDir, "db.sql")
|
||||||
lockDir := filepath.Join(tmpDir, "locks")
|
lockDir := filepath.Join(tmpDir, "locks")
|
||||||
|
|
||||||
|
if err := os.Mkdir(lockDir, 0755); err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
runtime := new(Runtime)
|
runtime := new(Runtime)
|
||||||
runtime.config = new(RuntimeConfig)
|
runtime.config = new(RuntimeConfig)
|
||||||
runtime.config.StorageConfig = storage.StoreOptions{}
|
runtime.config.StorageConfig = storage.StoreOptions{}
|
||||||
|
runtime.lockDir = lockDir
|
||||||
|
|
||||||
state, err := NewBoltState(dbPath, lockDir, runtime)
|
state, err := NewBoltState(dbPath, runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,7 +313,7 @@ func getTomlStorage(storeOptions *storage.StoreOptions) *tomlConfig {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultStoreOptions returns the storage ops for containers
|
// GetDefaultStoreOptions returns the default storage options for containers.
|
||||||
func GetDefaultStoreOptions() (storage.StoreOptions, error) {
|
func GetDefaultStoreOptions() (storage.StoreOptions, error) {
|
||||||
storageOpts := storage.DefaultStoreOptions
|
storageOpts := storage.DefaultStoreOptions
|
||||||
if rootless.IsRootless() {
|
if rootless.IsRootless() {
|
||||||
|
|
Loading…
Reference in New Issue