github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/libpod/runtime.go (about)

     1  package libpod
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"sync"
    10  	"syscall"
    11  
    12  	"github.com/containers/common/pkg/config"
    13  	"github.com/containers/image/v5/pkg/sysregistriesv2"
    14  	is "github.com/containers/image/v5/storage"
    15  	"github.com/containers/image/v5/types"
    16  	"github.com/containers/podman/v2/libpod/define"
    17  	"github.com/containers/podman/v2/libpod/events"
    18  	"github.com/containers/podman/v2/libpod/image"
    19  	"github.com/containers/podman/v2/libpod/lock"
    20  	"github.com/containers/podman/v2/libpod/shutdown"
    21  	"github.com/containers/podman/v2/pkg/cgroups"
    22  	"github.com/containers/podman/v2/pkg/registries"
    23  	"github.com/containers/podman/v2/pkg/rootless"
    24  	"github.com/containers/podman/v2/pkg/util"
    25  	"github.com/containers/storage"
    26  	"github.com/cri-o/ocicni/pkg/ocicni"
    27  	"github.com/docker/docker/pkg/namesgenerator"
    28  	"github.com/pkg/errors"
    29  	"github.com/sirupsen/logrus"
    30  )
    31  
    32  // A RuntimeOption is a functional option which alters the Runtime created by
    33  // NewRuntime
    34  type RuntimeOption func(*Runtime) error
    35  
    36  type storageSet struct {
    37  	RunRootSet         bool
    38  	GraphRootSet       bool
    39  	StaticDirSet       bool
    40  	VolumePathSet      bool
    41  	GraphDriverNameSet bool
    42  	TmpDirSet          bool
    43  }
    44  
    45  // Runtime is the core libpod runtime
    46  type Runtime struct {
    47  	config        *config.Config
    48  	storageConfig storage.StoreOptions
    49  	storageSet    storageSet
    50  
    51  	state             State
    52  	store             storage.Store
    53  	storageService    *storageService
    54  	imageContext      *types.SystemContext
    55  	defaultOCIRuntime OCIRuntime
    56  	ociRuntimes       map[string]OCIRuntime
    57  	runtimeFlags      []string
    58  	netPlugin         ocicni.CNIPlugin
    59  	conmonPath        string
    60  	imageRuntime      *image.Runtime
    61  	lockManager       lock.Manager
    62  
    63  	// doRenumber indicates that the runtime should perform a lock renumber
    64  	// during initialization.
    65  	// Once the runtime has been initialized and returned, this variable is
    66  	// unused.
    67  	doRenumber bool
    68  
    69  	doMigrate bool
    70  	// System migrate can move containers to a new runtime.
    71  	// We make no promises that these migrated containers work on the new
    72  	// runtime, though.
    73  	migrateRuntime string
    74  
    75  	// valid indicates whether the runtime is ready to use.
    76  	// valid is set to true when a runtime is returned from GetRuntime(),
    77  	// and remains true until the runtime is shut down (rendering its
    78  	// storage unusable). When valid is false, the runtime cannot be used.
    79  	valid bool
    80  	lock  sync.RWMutex
    81  
    82  	// mechanism to read and write even logs
    83  	eventer events.Eventer
    84  
    85  	// noStore indicates whether we need to interact with a store or not
    86  	noStore bool
    87  }
    88  
    89  // SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set.
    90  // containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is
    91  // use for the containers.conf configuration file.
    92  func SetXdgDirs() error {
    93  	if !rootless.IsRootless() {
    94  		return nil
    95  	}
    96  
    97  	// Setup XDG_RUNTIME_DIR
    98  	runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
    99  
   100  	if runtimeDir == "" {
   101  		var err error
   102  		runtimeDir, err = util.GetRuntimeDir()
   103  		if err != nil {
   104  			return err
   105  		}
   106  	}
   107  	if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil {
   108  		return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
   109  	}
   110  
   111  	if rootless.IsRootless() && os.Getenv("DBUS_SESSION_BUS_ADDRESS") == "" {
   112  		sessionAddr := filepath.Join(runtimeDir, "bus")
   113  		if _, err := os.Stat(sessionAddr); err == nil {
   114  			os.Setenv("DBUS_SESSION_BUS_ADDRESS", fmt.Sprintf("unix:path=%s", sessionAddr))
   115  		}
   116  	}
   117  
   118  	// Setup XDG_CONFIG_HOME
   119  	if cfgHomeDir := os.Getenv("XDG_CONFIG_HOME"); cfgHomeDir == "" {
   120  		cfgHomeDir, err := util.GetRootlessConfigHomeDir()
   121  		if err != nil {
   122  			return err
   123  		}
   124  		if err := os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil {
   125  			return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME")
   126  		}
   127  	}
   128  	return nil
   129  }
   130  
   131  // NewRuntime creates a new container runtime
   132  // Options can be passed to override the default configuration for the runtime
   133  func NewRuntime(ctx context.Context, options ...RuntimeOption) (*Runtime, error) {
   134  	conf, err := config.NewConfig("")
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	conf.CheckCgroupsAndAdjustConfig()
   139  	return newRuntimeFromConfig(ctx, conf, options...)
   140  }
   141  
   142  // NewRuntimeFromConfig creates a new container runtime using the given
   143  // configuration file for its default configuration. Passed RuntimeOption
   144  // functions can be used to mutate this configuration further.
   145  // An error will be returned if the configuration file at the given path does
   146  // not exist or cannot be loaded
   147  func NewRuntimeFromConfig(ctx context.Context, userConfig *config.Config, options ...RuntimeOption) (*Runtime, error) {
   148  
   149  	return newRuntimeFromConfig(ctx, userConfig, options...)
   150  }
   151  
   152  func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...RuntimeOption) (*Runtime, error) {
   153  	runtime := new(Runtime)
   154  
   155  	if conf.Engine.OCIRuntime == "" {
   156  		conf.Engine.OCIRuntime = "runc"
   157  		// If we're running on cgroups v2, default to using crun.
   158  		if onCgroupsv2, _ := cgroups.IsCgroup2UnifiedMode(); onCgroupsv2 {
   159  			conf.Engine.OCIRuntime = "crun"
   160  		}
   161  	}
   162  
   163  	runtime.config = conf
   164  
   165  	if err := SetXdgDirs(); err != nil {
   166  		return nil, err
   167  	}
   168  
   169  	storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID())
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	runtime.storageConfig = storeOpts
   174  
   175  	// Overwrite config with user-given configuration options
   176  	for _, opt := range options {
   177  		if err := opt(runtime); err != nil {
   178  			return nil, errors.Wrapf(err, "error configuring runtime")
   179  		}
   180  	}
   181  
   182  	if err := shutdown.Start(); err != nil {
   183  		return nil, errors.Wrapf(err, "error starting shutdown signal handler")
   184  	}
   185  
   186  	if err := makeRuntime(ctx, runtime); err != nil {
   187  		return nil, err
   188  	}
   189  
   190  	if err := shutdown.Register("libpod", func(sig os.Signal) error {
   191  		os.Exit(1)
   192  		return nil
   193  	}); err != nil && errors.Cause(err) != shutdown.ErrHandlerExists {
   194  		logrus.Errorf("Error registering shutdown handler for libpod: %v", err)
   195  	}
   196  
   197  	return runtime, nil
   198  }
   199  
   200  func getLockManager(runtime *Runtime) (lock.Manager, error) {
   201  	var err error
   202  	var manager lock.Manager
   203  
   204  	switch runtime.config.Engine.LockType {
   205  	case "file":
   206  		lockPath := filepath.Join(runtime.config.Engine.TmpDir, "locks")
   207  		manager, err = lock.OpenFileLockManager(lockPath)
   208  		if err != nil {
   209  			if os.IsNotExist(errors.Cause(err)) {
   210  				manager, err = lock.NewFileLockManager(lockPath)
   211  				if err != nil {
   212  					return nil, errors.Wrapf(err, "failed to get new file lock manager")
   213  				}
   214  			} else {
   215  				return nil, err
   216  			}
   217  		}
   218  
   219  	case "", "shm":
   220  		lockPath := define.DefaultSHMLockPath
   221  		if rootless.IsRootless() {
   222  			lockPath = fmt.Sprintf("%s_%d", define.DefaultRootlessSHMLockPath, rootless.GetRootlessUID())
   223  		}
   224  		// Set up the lock manager
   225  		manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.Engine.NumLocks)
   226  		if err != nil {
   227  			switch {
   228  			case os.IsNotExist(errors.Cause(err)):
   229  				manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks)
   230  				if err != nil {
   231  					return nil, errors.Wrapf(err, "failed to get new shm lock manager")
   232  				}
   233  			case errors.Cause(err) == syscall.ERANGE && runtime.doRenumber:
   234  				logrus.Debugf("Number of locks does not match - removing old locks")
   235  
   236  				// ERANGE indicates a lock numbering mismatch.
   237  				// Since we're renumbering, this is not fatal.
   238  				// Remove the earlier set of locks and recreate.
   239  				if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil {
   240  					return nil, errors.Wrapf(err, "error removing libpod locks file %s", lockPath)
   241  				}
   242  
   243  				manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks)
   244  				if err != nil {
   245  					return nil, err
   246  				}
   247  			default:
   248  				return nil, err
   249  			}
   250  		}
   251  	default:
   252  		return nil, errors.Wrapf(define.ErrInvalidArg, "unknown lock type %s", runtime.config.Engine.LockType)
   253  	}
   254  	return manager, nil
   255  }
   256  
   257  // Make a new runtime based on the given configuration
   258  // Sets up containers/storage, state store, OCI runtime
   259  func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
   260  	// Find a working conmon binary
   261  	cPath, err := runtime.config.FindConmon()
   262  	if err != nil {
   263  		return err
   264  	}
   265  	runtime.conmonPath = cPath
   266  
   267  	// Make the static files directory if it does not exist
   268  	if err := os.MkdirAll(runtime.config.Engine.StaticDir, 0700); err != nil {
   269  		// The directory is allowed to exist
   270  		if !os.IsExist(err) {
   271  			return errors.Wrap(err, "error creating runtime static files directory")
   272  		}
   273  	}
   274  
   275  	// Set up the state.
   276  	//
   277  	// TODO - if we further break out the state implementation into
   278  	// libpod/state, the config could take care of the code below.  It
   279  	// would further allow to move the types and consts into a coherent
   280  	// package.
   281  	switch runtime.config.Engine.StateType {
   282  	case config.InMemoryStateStore:
   283  		state, err := NewInMemoryState()
   284  		if err != nil {
   285  			return err
   286  		}
   287  		runtime.state = state
   288  	case config.SQLiteStateStore:
   289  		return errors.Wrapf(define.ErrInvalidArg, "SQLite state is currently disabled")
   290  	case config.BoltDBStateStore:
   291  		dbPath := filepath.Join(runtime.config.Engine.StaticDir, "bolt_state.db")
   292  
   293  		state, err := NewBoltState(dbPath, runtime)
   294  		if err != nil {
   295  			return err
   296  		}
   297  		runtime.state = state
   298  	default:
   299  		return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed (%v)", runtime.config.Engine.StateType)
   300  	}
   301  
   302  	// Grab config from the database so we can reset some defaults
   303  	dbConfig, err := runtime.state.GetDBConfig()
   304  	if err != nil {
   305  		return errors.Wrapf(err, "error retrieving runtime configuration from database")
   306  	}
   307  
   308  	runtime.mergeDBConfig(dbConfig)
   309  
   310  	logrus.Debugf("Using graph driver %s", runtime.storageConfig.GraphDriverName)
   311  	logrus.Debugf("Using graph root %s", runtime.storageConfig.GraphRoot)
   312  	logrus.Debugf("Using run root %s", runtime.storageConfig.RunRoot)
   313  	logrus.Debugf("Using static dir %s", runtime.config.Engine.StaticDir)
   314  	logrus.Debugf("Using tmp dir %s", runtime.config.Engine.TmpDir)
   315  	logrus.Debugf("Using volume path %s", runtime.config.Engine.VolumePath)
   316  
   317  	// Validate our config against the database, now that we've set our
   318  	// final storage configuration
   319  	if err := runtime.state.ValidateDBConfig(runtime); err != nil {
   320  		return err
   321  	}
   322  
   323  	if err := runtime.state.SetNamespace(runtime.config.Engine.Namespace); err != nil {
   324  		return errors.Wrapf(err, "error setting libpod namespace in state")
   325  	}
   326  	logrus.Debugf("Set libpod namespace to %q", runtime.config.Engine.Namespace)
   327  
   328  	// Set up containers/storage
   329  	var store storage.Store
   330  	if os.Geteuid() != 0 {
   331  		logrus.Debug("Not configuring container store")
   332  	} else if runtime.noStore {
   333  		logrus.Debug("No store required. Not opening container store.")
   334  	} else if err := runtime.configureStore(); err != nil {
   335  		return err
   336  	}
   337  	defer func() {
   338  		if retErr != nil && store != nil {
   339  			// Don't forcibly shut down
   340  			// We could be opening a store in use by another libpod
   341  			if _, err := store.Shutdown(false); err != nil {
   342  				logrus.Errorf("Error removing store for partially-created runtime: %s", err)
   343  			}
   344  		}
   345  	}()
   346  
   347  	// Setup the eventer
   348  	eventer, err := runtime.newEventer()
   349  	if err != nil {
   350  		return err
   351  	}
   352  	runtime.eventer = eventer
   353  	if runtime.imageRuntime != nil {
   354  		runtime.imageRuntime.Eventer = eventer
   355  	}
   356  
   357  	// Set up containers/image
   358  	if runtime.imageContext == nil {
   359  		runtime.imageContext = &types.SystemContext{}
   360  	}
   361  	runtime.imageContext.SignaturePolicyPath = runtime.config.Engine.SignaturePolicyPath
   362  
   363  	// Create the tmpDir
   364  	if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0751); err != nil {
   365  		// The directory is allowed to exist
   366  		if !os.IsExist(err) {
   367  			return errors.Wrap(err, "error creating tmpdir")
   368  		}
   369  	}
   370  
   371  	// Create events log dir
   372  	if err := os.MkdirAll(filepath.Dir(runtime.config.Engine.EventsLogFilePath), 0700); err != nil {
   373  		// The directory is allowed to exist
   374  		if !os.IsExist(err) {
   375  			return errors.Wrap(err, "error creating events dirs")
   376  		}
   377  	}
   378  
   379  	// Get us at least one working OCI runtime.
   380  	runtime.ociRuntimes = make(map[string]OCIRuntime)
   381  
   382  	// Initialize remaining OCI runtimes
   383  	for name, paths := range runtime.config.Engine.OCIRuntimes {
   384  
   385  		ociRuntime, err := newConmonOCIRuntime(name, paths, runtime.conmonPath, runtime.runtimeFlags, runtime.config)
   386  		if err != nil {
   387  			// Don't fatally error.
   388  			// This will allow us to ship configs including optional
   389  			// runtimes that might not be installed (crun, kata).
   390  			// Only a warnf so default configs don't spec errors.
   391  			logrus.Warnf("Error initializing configured OCI runtime %s: %v", name, err)
   392  			continue
   393  		}
   394  
   395  		runtime.ociRuntimes[name] = ociRuntime
   396  	}
   397  
   398  	// Do we have a default OCI runtime?
   399  	if runtime.config.Engine.OCIRuntime != "" {
   400  		// If the string starts with / it's a path to a runtime
   401  		// executable.
   402  		if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") {
   403  			ociRuntime, err := newConmonOCIRuntime(runtime.config.Engine.OCIRuntime, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.runtimeFlags, runtime.config)
   404  			if err != nil {
   405  				return err
   406  			}
   407  
   408  			runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] = ociRuntime
   409  			runtime.defaultOCIRuntime = ociRuntime
   410  		} else {
   411  			ociRuntime, ok := runtime.ociRuntimes[runtime.config.Engine.OCIRuntime]
   412  			if !ok {
   413  				return errors.Wrapf(define.ErrInvalidArg, "default OCI runtime %q not found", runtime.config.Engine.OCIRuntime)
   414  			}
   415  			runtime.defaultOCIRuntime = ociRuntime
   416  		}
   417  	}
   418  
   419  	// Do we have at least one valid OCI runtime?
   420  	if len(runtime.ociRuntimes) == 0 {
   421  		return errors.Wrapf(define.ErrInvalidArg, "no OCI runtime has been configured")
   422  	}
   423  
   424  	// Do we have a default runtime?
   425  	if runtime.defaultOCIRuntime == nil {
   426  		return errors.Wrapf(define.ErrInvalidArg, "no default OCI runtime was configured")
   427  	}
   428  
   429  	// Make the per-boot files directory if it does not exist
   430  	if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0755); err != nil {
   431  		// The directory is allowed to exist
   432  		if !os.IsExist(err) {
   433  			return errors.Wrapf(err, "error creating runtime temporary files directory")
   434  		}
   435  	}
   436  
   437  	// Set up the CNI net plugin
   438  	if !rootless.IsRootless() {
   439  
   440  		netPlugin, err := ocicni.InitCNI(runtime.config.Network.DefaultNetwork, runtime.config.Network.NetworkConfigDir, runtime.config.Network.CNIPluginDirs...)
   441  		if err != nil {
   442  			return errors.Wrapf(err, "error configuring CNI network plugin")
   443  		}
   444  		runtime.netPlugin = netPlugin
   445  	}
   446  
   447  	// We now need to see if the system has restarted
   448  	// We check for the presence of a file in our tmp directory to verify this
   449  	// This check must be locked to prevent races
   450  	runtimeAliveLock := filepath.Join(runtime.config.Engine.TmpDir, "alive.lck")
   451  	runtimeAliveFile := filepath.Join(runtime.config.Engine.TmpDir, "alive")
   452  	aliveLock, err := storage.GetLockfile(runtimeAliveLock)
   453  	if err != nil {
   454  		return errors.Wrapf(err, "error acquiring runtime init lock")
   455  	}
   456  	// Acquire the lock and hold it until we return
   457  	// This ensures that no two processes will be in runtime.refresh at once
   458  	// TODO: we can't close the FD in this lock, so we should keep it around
   459  	// and use it to lock important operations
   460  	aliveLock.Lock()
   461  	doRefresh := false
   462  	defer func() {
   463  		if aliveLock.Locked() {
   464  			aliveLock.Unlock()
   465  		}
   466  	}()
   467  
   468  	_, err = os.Stat(runtimeAliveFile)
   469  	if err != nil {
   470  		// If we need to refresh, then it is safe to assume there are
   471  		// no containers running.  Create immediately a namespace, as
   472  		// we will need to access the storage.
   473  		if os.Geteuid() != 0 {
   474  			aliveLock.Unlock() // Unlock to avoid deadlock as BecomeRootInUserNS will reexec.
   475  			pausePid, err := util.GetRootlessPauseProcessPidPathGivenDir(runtime.config.Engine.TmpDir)
   476  			if err != nil {
   477  				return errors.Wrapf(err, "could not get pause process pid file path")
   478  			}
   479  			became, ret, err := rootless.BecomeRootInUserNS(pausePid)
   480  			if err != nil {
   481  				return err
   482  			}
   483  			if became {
   484  				os.Exit(ret)
   485  			}
   486  
   487  		}
   488  		// If the file doesn't exist, we need to refresh the state
   489  		// This will trigger on first use as well, but refreshing an
   490  		// empty state only creates a single file
   491  		// As such, it's not really a performance concern
   492  		if os.IsNotExist(err) {
   493  			doRefresh = true
   494  		} else {
   495  			return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile)
   496  		}
   497  	}
   498  
   499  	runtime.lockManager, err = getLockManager(runtime)
   500  	if err != nil {
   501  		return err
   502  	}
   503  
   504  	// If we're renumbering locks, do it now.
   505  	// It breaks out of normal runtime init, and will not return a valid
   506  	// runtime.
   507  	if runtime.doRenumber {
   508  		if err := runtime.renumberLocks(); err != nil {
   509  			return err
   510  		}
   511  	}
   512  
   513  	// If we need to refresh the state, do it now - things are guaranteed to
   514  	// be set up by now.
   515  	if doRefresh {
   516  		// Ensure we have a store before refresh occurs
   517  		if runtime.store == nil {
   518  			if err := runtime.configureStore(); err != nil {
   519  				return err
   520  			}
   521  		}
   522  
   523  		if err2 := runtime.refresh(runtimeAliveFile); err2 != nil {
   524  			return err2
   525  		}
   526  	}
   527  
   528  	// Mark the runtime as valid - ready to be used, cannot be modified
   529  	// further
   530  	runtime.valid = true
   531  
   532  	if runtime.doMigrate {
   533  		if err := runtime.migrate(ctx); err != nil {
   534  			return err
   535  		}
   536  	}
   537  
   538  	return nil
   539  }
   540  
   541  // TmpDir gets the current Libpod temporary files directory.
   542  func (r *Runtime) TmpDir() (string, error) {
   543  	if !r.valid {
   544  		return "", define.ErrRuntimeStopped
   545  	}
   546  
   547  	return r.config.Engine.TmpDir, nil
   548  }
   549  
   550  // GetConfig returns a copy of the configuration used by the runtime
   551  func (r *Runtime) GetConfig() (*config.Config, error) {
   552  	r.lock.RLock()
   553  	defer r.lock.RUnlock()
   554  
   555  	if !r.valid {
   556  		return nil, define.ErrRuntimeStopped
   557  	}
   558  
   559  	config := new(config.Config)
   560  
   561  	// Copy so the caller won't be able to modify the actual config
   562  	if err := JSONDeepCopy(r.config, config); err != nil {
   563  		return nil, errors.Wrapf(err, "error copying config")
   564  	}
   565  
   566  	return config, nil
   567  }
   568  
   569  // DeferredShutdown shuts down the runtime without exposing any
   570  // errors. This is only meant to be used when the runtime is being
   571  // shutdown within a defer statement; else use Shutdown
   572  func (r *Runtime) DeferredShutdown(force bool) {
   573  	_ = r.Shutdown(force)
   574  }
   575  
   576  // Shutdown shuts down the runtime and associated containers and storage
   577  // If force is true, containers and mounted storage will be shut down before
   578  // cleaning up; if force is false, an error will be returned if there are
   579  // still containers running or mounted
   580  func (r *Runtime) Shutdown(force bool) error {
   581  	r.lock.Lock()
   582  	defer r.lock.Unlock()
   583  
   584  	if !r.valid {
   585  		return define.ErrRuntimeStopped
   586  	}
   587  
   588  	r.valid = false
   589  
   590  	// Shutdown all containers if --force is given
   591  	if force {
   592  		ctrs, err := r.state.AllContainers()
   593  		if err != nil {
   594  			logrus.Errorf("Error retrieving containers from database: %v", err)
   595  		} else {
   596  			for _, ctr := range ctrs {
   597  				if err := ctr.StopWithTimeout(r.config.Engine.StopTimeout); err != nil {
   598  					logrus.Errorf("Error stopping container %s: %v", ctr.ID(), err)
   599  				}
   600  			}
   601  		}
   602  	}
   603  
   604  	var lastError error
   605  	// If no store was requested, it can be nil and there is no need to
   606  	// attempt to shut it down
   607  	if r.store != nil {
   608  		if _, err := r.store.Shutdown(force); err != nil {
   609  			lastError = errors.Wrapf(err, "error shutting down container storage")
   610  		}
   611  	}
   612  	if err := r.state.Close(); err != nil {
   613  		if lastError != nil {
   614  			logrus.Errorf("%v", lastError)
   615  		}
   616  		lastError = err
   617  	}
   618  
   619  	return lastError
   620  }
   621  
   622  // Reconfigures the runtime after a reboot
   623  // Refreshes the state, recreating temporary files
   624  // Does not check validity as the runtime is not valid until after this has run
   625  func (r *Runtime) refresh(alivePath string) error {
   626  	logrus.Debugf("Podman detected system restart - performing state refresh")
   627  
   628  	// First clear the state in the database
   629  	if err := r.state.Refresh(); err != nil {
   630  		return err
   631  	}
   632  
   633  	// Next refresh the state of all containers to recreate dirs and
   634  	// namespaces, and all the pods to recreate cgroups.
   635  	// Containers, pods, and volumes must also reacquire their locks.
   636  	ctrs, err := r.state.AllContainers()
   637  	if err != nil {
   638  		return errors.Wrapf(err, "error retrieving all containers from state")
   639  	}
   640  	pods, err := r.state.AllPods()
   641  	if err != nil {
   642  		return errors.Wrapf(err, "error retrieving all pods from state")
   643  	}
   644  	vols, err := r.state.AllVolumes()
   645  	if err != nil {
   646  		return errors.Wrapf(err, "error retrieving all volumes from state")
   647  	}
   648  	// No locks are taken during pod, volume, and container refresh.
   649  	// Furthermore, the pod/volume/container refresh() functions are not
   650  	// allowed to take locks themselves.
   651  	// We cannot assume that any pod/volume/container has a valid lock until
   652  	// after this function has returned.
   653  	// The runtime alive lock should suffice to provide mutual exclusion
   654  	// until this has run.
   655  	for _, ctr := range ctrs {
   656  		if err := ctr.refresh(); err != nil {
   657  			logrus.Errorf("Error refreshing container %s: %v", ctr.ID(), err)
   658  		}
   659  	}
   660  	for _, pod := range pods {
   661  		if err := pod.refresh(); err != nil {
   662  			logrus.Errorf("Error refreshing pod %s: %v", pod.ID(), err)
   663  		}
   664  	}
   665  	for _, vol := range vols {
   666  		if err := vol.refresh(); err != nil {
   667  			logrus.Errorf("Error refreshing volume %s: %v", vol.Name(), err)
   668  		}
   669  	}
   670  
   671  	// Create a file indicating the runtime is alive and ready
   672  	file, err := os.OpenFile(alivePath, os.O_RDONLY|os.O_CREATE, 0644)
   673  	if err != nil {
   674  		return errors.Wrap(err, "error creating runtime status file")
   675  	}
   676  	defer file.Close()
   677  
   678  	r.newSystemEvent(events.Refresh)
   679  
   680  	return nil
   681  }
   682  
   683  // Info returns the store and host information
   684  func (r *Runtime) Info() (*define.Info, error) {
   685  	return r.info()
   686  }
   687  
   688  // generateName generates a unique name for a container or pod.
   689  func (r *Runtime) generateName() (string, error) {
   690  	for {
   691  		name := namesgenerator.GetRandomName(0)
   692  		// Make sure container with this name does not exist
   693  		if _, err := r.state.LookupContainer(name); err == nil {
   694  			continue
   695  		} else if errors.Cause(err) != define.ErrNoSuchCtr {
   696  			return "", err
   697  		}
   698  		// Make sure pod with this name does not exist
   699  		if _, err := r.state.LookupPod(name); err == nil {
   700  			continue
   701  		} else if errors.Cause(err) != define.ErrNoSuchPod {
   702  			return "", err
   703  		}
   704  		return name, nil
   705  	}
   706  	// The code should never reach here.
   707  }
   708  
   709  // Configure store and image runtime
   710  func (r *Runtime) configureStore() error {
   711  	store, err := storage.GetStore(r.storageConfig)
   712  	if err != nil {
   713  		return err
   714  	}
   715  
   716  	r.store = store
   717  	is.Transport.SetStore(store)
   718  
   719  	// Set up a storage service for creating container root filesystems from
   720  	// images
   721  	r.storageService = getStorageService(r.store)
   722  
   723  	ir := image.NewImageRuntimeFromStore(r.store)
   724  	ir.SignaturePolicyPath = r.config.Engine.SignaturePolicyPath
   725  	ir.EventsLogFilePath = r.config.Engine.EventsLogFilePath
   726  	ir.EventsLogger = r.config.Engine.EventsLogger
   727  
   728  	r.imageRuntime = ir
   729  
   730  	return nil
   731  }
   732  
   733  // ImageRuntime returns the imageruntime for image operations.
   734  // If WithNoStore() was used, no image runtime will be available, and this
   735  // function will return nil.
   736  func (r *Runtime) ImageRuntime() *image.Runtime {
   737  	return r.imageRuntime
   738  }
   739  
   740  // SystemContext returns the imagecontext
   741  func (r *Runtime) SystemContext() *types.SystemContext {
   742  	return r.imageContext
   743  }
   744  
   745  // GetOCIRuntimePath retrieves the path of the default OCI runtime.
   746  func (r *Runtime) GetOCIRuntimePath() string {
   747  	return r.defaultOCIRuntime.Path()
   748  }
   749  
   750  // StorageConfig retrieves the storage options for the container runtime
   751  func (r *Runtime) StorageConfig() storage.StoreOptions {
   752  	return r.storageConfig
   753  }
   754  
   755  // GetStore returns the runtime stores
   756  func (r *Runtime) GetStore() storage.Store {
   757  	return r.store
   758  }
   759  
   760  // GetName retrieves the name associated with a given full ID.
   761  // This works for both containers and pods, and does not distinguish between the
   762  // two.
   763  // If the given ID does not correspond to any existing Pod or Container,
   764  // ErrNoSuchCtr is returned.
   765  func (r *Runtime) GetName(id string) (string, error) {
   766  	r.lock.RLock()
   767  	defer r.lock.RUnlock()
   768  
   769  	if !r.valid {
   770  		return "", define.ErrRuntimeStopped
   771  	}
   772  
   773  	return r.state.GetName(id)
   774  }
   775  
   776  // DBConfig is a set of Libpod runtime configuration settings that are saved in
   777  // a State when it is first created, and can subsequently be retrieved.
   778  type DBConfig struct {
   779  	LibpodRoot  string
   780  	LibpodTmp   string
   781  	StorageRoot string
   782  	StorageTmp  string
   783  	GraphDriver string
   784  	VolumePath  string
   785  }
   786  
   787  // mergeDBConfig merges the configuration from the database.
   788  func (r *Runtime) mergeDBConfig(dbConfig *DBConfig) {
   789  
   790  	c := &r.config.Engine
   791  	if !r.storageSet.RunRootSet && dbConfig.StorageTmp != "" {
   792  		if r.storageConfig.RunRoot != dbConfig.StorageTmp &&
   793  			r.storageConfig.RunRoot != "" {
   794  			logrus.Debugf("Overriding run root %q with %q from database",
   795  				r.storageConfig.RunRoot, dbConfig.StorageTmp)
   796  		}
   797  		r.storageConfig.RunRoot = dbConfig.StorageTmp
   798  	}
   799  
   800  	if !r.storageSet.GraphRootSet && dbConfig.StorageRoot != "" {
   801  		if r.storageConfig.GraphRoot != dbConfig.StorageRoot &&
   802  			r.storageConfig.GraphRoot != "" {
   803  			logrus.Debugf("Overriding graph root %q with %q from database",
   804  				r.storageConfig.GraphRoot, dbConfig.StorageRoot)
   805  		}
   806  		r.storageConfig.GraphRoot = dbConfig.StorageRoot
   807  	}
   808  
   809  	if !r.storageSet.GraphDriverNameSet && dbConfig.GraphDriver != "" {
   810  		if r.storageConfig.GraphDriverName != dbConfig.GraphDriver &&
   811  			r.storageConfig.GraphDriverName != "" {
   812  			logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
   813  				r.storageConfig.GraphDriverName, dbConfig.GraphDriver)
   814  		}
   815  		r.storageConfig.GraphDriverName = dbConfig.GraphDriver
   816  	}
   817  
   818  	if !r.storageSet.StaticDirSet && dbConfig.LibpodRoot != "" {
   819  		if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" {
   820  			logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot)
   821  		}
   822  		c.StaticDir = dbConfig.LibpodRoot
   823  	}
   824  
   825  	if !r.storageSet.TmpDirSet && dbConfig.LibpodTmp != "" {
   826  		if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" {
   827  			logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp)
   828  		}
   829  		c.TmpDir = dbConfig.LibpodTmp
   830  		c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log")
   831  	}
   832  
   833  	if !r.storageSet.VolumePathSet && dbConfig.VolumePath != "" {
   834  		if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" {
   835  			logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath)
   836  		}
   837  		c.VolumePath = dbConfig.VolumePath
   838  	}
   839  }
   840  
   841  func (r *Runtime) EnableLabeling() bool {
   842  	return r.config.Containers.EnableLabeling
   843  }
   844  
   845  // Reload reloads the configurations files
   846  func (r *Runtime) Reload() error {
   847  	if err := r.reloadContainersConf(); err != nil {
   848  		return err
   849  	}
   850  	if err := r.reloadStorageConf(); err != nil {
   851  		return err
   852  	}
   853  	if err := reloadRegistriesConf(); err != nil {
   854  		return err
   855  	}
   856  	return nil
   857  }
   858  
   859  // reloadContainersConf reloads the containers.conf
   860  func (r *Runtime) reloadContainersConf() error {
   861  	config, err := config.Reload()
   862  	if err != nil {
   863  		return err
   864  	}
   865  	r.config = config
   866  	logrus.Infof("applied new containers configuration: %v", config)
   867  	return nil
   868  }
   869  
   870  // reloadRegistries reloads the registries.conf
   871  func reloadRegistriesConf() error {
   872  	sysregistriesv2.InvalidateCache()
   873  	registries, err := sysregistriesv2.GetRegistries(&types.SystemContext{SystemRegistriesConfPath: registries.SystemRegistriesConfPath()})
   874  	if err != nil {
   875  		return err
   876  	}
   877  	logrus.Infof("applied new registry configuration: %+v", registries)
   878  	return nil
   879  }
   880  
   881  // reloadStorageConf reloads the storage.conf
   882  func (r *Runtime) reloadStorageConf() error {
   883  	configFile, err := storage.DefaultConfigFile(rootless.IsRootless())
   884  	if err != nil {
   885  		return err
   886  	}
   887  	storage.ReloadConfigurationFile(configFile, &r.storageConfig)
   888  	logrus.Infof("applied new storage configuration: %v", r.storageConfig)
   889  	return nil
   890  }