aboutsummaryrefslogtreecommitdiff
path: root/libpod/runtime.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/runtime.go')
-rw-r--r--libpod/runtime.go253
1 files changed, 161 insertions, 92 deletions
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 97eb565cc..53c9a1209 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -10,6 +10,7 @@ import (
"strings"
"sync"
"syscall"
+ "time"
"github.com/BurntSushi/toml"
is "github.com/containers/image/storage"
@@ -73,14 +74,17 @@ var (
OverrideConfigPath = etcDir + "/containers/libpod.conf"
// DefaultInfraImage to use for infra container
- DefaultInfraImage = "k8s.gcr.io/pause:3.1"
+
// DefaultInfraCommand to be run in an infra container
- DefaultInfraCommand = "/pause"
// DefaultSHMLockPath is the default path for SHM locks
DefaultSHMLockPath = "/libpod_lock"
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
+
+ // DefaultDetachKeys is the default keys sequence for detaching a
+ // container
+ DefaultDetachKeys = "ctrl-p,ctrl-q"
)
// A RuntimeOption is a functional option which alters the Runtime created by
@@ -121,6 +125,9 @@ type Runtime struct {
// mechanism to read and write even logs
eventer events.Eventer
+
+ // noStore indicates whether we need to interact with a store or not
+ noStore bool
}
// RuntimeConfig contains configuration options used to set up the runtime
@@ -232,10 +239,15 @@ type RuntimeConfig struct {
// pods.
NumLocks uint32 `toml:"num_locks,omitempty"`
+ // LockType is the type of locking to use.
+ LockType string `toml:"lock_type,omitempty"`
+
// EventsLogger determines where events should be logged
EventsLogger string `toml:"events_logger"`
// EventsLogFilePath is where the events log is stored.
- EventsLogFilePath string `toml:-"events_logfile_path"`
+ EventsLogFilePath string `toml:"-events_logfile_path"`
+ //DetachKeys is the sequence of keys used to detach a container
+ DetachKeys string `toml:"detach_keys"`
}
// runtimeConfiguredFrom is a struct used during early runtime init to help
@@ -302,15 +314,57 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
NoPivotRoot: false,
CNIConfigDir: etcDir + "/cni/net.d/",
CNIPluginDir: []string{"/usr/libexec/cni", "/usr/lib/cni", "/usr/local/lib/cni", "/opt/cni/bin"},
- InfraCommand: DefaultInfraCommand,
- InfraImage: DefaultInfraImage,
+ InfraCommand: define.DefaultInfraCommand,
+ InfraImage: define.DefaultInfraImage,
EnablePortReservation: true,
EnableLabeling: true,
NumLocks: 2048,
EventsLogger: events.DefaultEventerType.String(),
+ DetachKeys: DefaultDetachKeys,
+ LockType: "shm",
}, nil
}
+// SetXdgRuntimeDir ensures the XDG_RUNTIME_DIR env variable is set
+// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
+// It internally calls EnableLinger() so that the user's processes are not
+// killed once the session is terminated. EnableLinger() also attempts to
+// get the runtime directory when XDG_RUNTIME_DIR is not specified.
+func SetXdgRuntimeDir() error {
+ if !rootless.IsRootless() {
+ return nil
+ }
+
+ runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
+
+ runtimeDirLinger, err := rootless.EnableLinger()
+ if err != nil {
+ return errors.Wrapf(err, "error enabling user session")
+ }
+ if runtimeDir == "" && runtimeDirLinger != "" {
+ if _, err := os.Stat(runtimeDirLinger); err != nil && os.IsNotExist(err) {
+ chWait := make(chan error)
+ defer close(chWait)
+ if _, err := WaitForFile(runtimeDirLinger, chWait, time.Second*10); err != nil {
+ return errors.Wrapf(err, "waiting for directory '%s'", runtimeDirLinger)
+ }
+ }
+ runtimeDir = runtimeDirLinger
+ }
+
+ if runtimeDir == "" {
+ var err error
+ runtimeDir, err = util.GetRootlessRuntimeDir()
+ if err != nil {
+ return err
+ }
+ }
+ if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil {
+ return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
+ }
+ return nil
+}
+
func getDefaultTmpDir() (string, error) {
if !rootless.IsRootless() {
return "/var/run/libpod", nil
@@ -333,25 +387,6 @@ func getDefaultTmpDir() (string, error) {
return filepath.Join(libpodRuntimeDir, "tmp"), nil
}
-// SetXdgRuntimeDir ensures the XDG_RUNTIME_DIR env variable is set
-// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
-func SetXdgRuntimeDir(val string) error {
- if !rootless.IsRootless() {
- return nil
- }
- if val == "" {
- var err error
- val, err = util.GetRootlessRuntimeDir()
- if err != nil {
- return err
- }
- }
- if err := os.Setenv("XDG_RUNTIME_DIR", val); err != nil {
- return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
- }
- return nil
-}
-
// NewRuntime creates a new container runtime
// Options can be passed to override the default configuration for the runtime
func NewRuntime(ctx context.Context, options ...RuntimeOption) (runtime *Runtime, err error) {
@@ -373,7 +408,7 @@ func NewRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
func homeDir() (string, error) {
home := os.Getenv("HOME")
if home == "" {
- usr, err := user.Current()
+ usr, err := user.LookupId(fmt.Sprintf("%d", rootless.GetRootlessUID()))
if err != nil {
return "", errors.Wrapf(err, "unable to resolve HOME directory")
}
@@ -391,28 +426,33 @@ func getRootlessConfigPath() (string, error) {
return filepath.Join(home, ".config/containers/libpod.conf"), nil
}
-func getConfigPath() string {
+func getConfigPath() (string, error) {
if rootless.IsRootless() {
- rootlessConfigPath, err := getRootlessConfigPath()
+ path, err := getRootlessConfigPath()
if err != nil {
- if _, err := os.Stat(rootlessConfigPath); err == nil {
- return rootlessConfigPath
- }
+ return "", err
+ }
+ if _, err := os.Stat(path); err == nil {
+ return path, nil
}
+ return "", err
}
if _, err := os.Stat(OverrideConfigPath); err == nil {
// Use the override configuration path
- return OverrideConfigPath
+ return OverrideConfigPath, nil
}
if _, err := os.Stat(ConfigPath); err == nil {
- return ConfigPath
+ return ConfigPath, nil
}
- return ""
+ return "", nil
}
// DefaultRuntimeConfig reads default config path and returns the RuntimeConfig
func DefaultRuntimeConfig() (*RuntimeConfig, error) {
- configPath := getConfigPath()
+ configPath, err := getConfigPath()
+ if err != nil {
+ return nil, err
+ }
contents, err := ioutil.ReadFile(configPath)
if err != nil {
@@ -460,8 +500,10 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes")
- configPath := getConfigPath()
- rootlessConfigPath := ""
+ configPath, err := getConfigPath()
+ if err != nil {
+ return nil, err
+ }
if rootless.IsRootless() {
home, err := homeDir()
if err != nil {
@@ -473,23 +515,6 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
runtime.config.SignaturePolicyPath = newPath
}
}
-
- rootlessConfigPath, err = getRootlessConfigPath()
- if err != nil {
- return nil, err
- }
-
- runtimeDir, err := util.GetRootlessRuntimeDir()
- if err != nil {
- return nil, err
- }
-
- // containers/image uses XDG_RUNTIME_DIR to locate the auth file.
- // So make sure the env variable is set.
- if err := SetXdgRuntimeDir(runtimeDir); err != nil {
- return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
- }
-
}
if userConfigPath != "" {
@@ -599,7 +624,13 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
return nil, errors.Wrapf(err, "error configuring runtime")
}
}
- if rootlessConfigPath != "" {
+
+ if rootless.IsRootless() && configPath == "" {
+ configPath, err := getRootlessConfigPath()
+ if err != nil {
+ return nil, err
+ }
+
// storage.conf
storageConfFile, err := storage.DefaultConfigFile(rootless.IsRootless())
if err != nil {
@@ -612,16 +643,20 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
}
if configPath != "" {
- os.MkdirAll(filepath.Dir(rootlessConfigPath), 0755)
- file, err := os.OpenFile(rootlessConfigPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
+ if err := os.MkdirAll(filepath.Dir(configPath), 0755); err != nil {
+ return nil, err
+ }
+ file, err := os.OpenFile(configPath, 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)
+ return nil, errors.Wrapf(err, "cannot open file %s", configPath)
}
if err == nil {
defer file.Close()
enc := toml.NewEncoder(file)
if err := enc.Encode(runtime.config); err != nil {
- os.Remove(rootlessConfigPath)
+ if removeErr := os.Remove(configPath); removeErr != nil {
+ logrus.Debugf("unable to remove %s: %q", configPath, err)
+ }
}
}
}
@@ -632,6 +667,62 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ..
return runtime, nil
}
+func getLockManager(runtime *Runtime) (lock.Manager, error) {
+ var err error
+ var manager lock.Manager
+
+ switch runtime.config.LockType {
+ case "file":
+ lockPath := filepath.Join(runtime.config.TmpDir, "locks")
+ manager, err = lock.OpenFileLockManager(lockPath)
+ if err != nil {
+ if os.IsNotExist(errors.Cause(err)) {
+ manager, err = lock.NewFileLockManager(lockPath)
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to get new file lock manager")
+ }
+ } else {
+ return nil, err
+ }
+ }
+
+ case "", "shm":
+ lockPath := DefaultSHMLockPath
+ if rootless.IsRootless() {
+ lockPath = fmt.Sprintf("%s_%d", DefaultRootlessSHMLockPath, rootless.GetRootlessUID())
+ }
+ // Set up the lock manager
+ manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks)
+ if err != nil {
+ if os.IsNotExist(errors.Cause(err)) {
+ manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to get new shm lock manager")
+ }
+ } else if errors.Cause(err) == syscall.ERANGE && runtime.doRenumber {
+ logrus.Debugf("Number of locks does not match - removing old locks")
+
+ // ERANGE indicates a lock numbering mismatch.
+ // Since we're renumbering, this is not fatal.
+ // Remove the earlier set of locks and recreate.
+ if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil {
+ return nil, errors.Wrapf(err, "error removing libpod locks file %s", lockPath)
+ }
+
+ manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ return nil, err
+ }
+ }
+ default:
+ return nil, errors.Wrapf(define.ErrInvalidArg, "unknown lock type %s", runtime.config.LockType)
+ }
+ return manager, nil
+}
+
// Make a new runtime based on the given configuration
// Sets up containers/storage, state store, OCI runtime
func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
@@ -760,11 +851,14 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
var store storage.Store
if os.Geteuid() != 0 {
logrus.Debug("Not configuring container store")
+ } else if runtime.noStore {
+ logrus.Debug("No store required. Not opening container store.")
} else {
store, err = storage.GetStore(runtime.config.StorageConfig)
if err != nil {
return err
}
+ err = nil
defer func() {
if err != nil && store != nil {
@@ -1014,37 +1108,10 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
}
}
- lockPath := DefaultSHMLockPath
- if rootless.IsRootless() {
- lockPath = fmt.Sprintf("%s_%d", DefaultRootlessSHMLockPath, rootless.GetRootlessUID())
- }
- // Set up the lock manager
- manager, err := lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks)
+ runtime.lockManager, err = getLockManager(runtime)
if err != nil {
- if os.IsNotExist(errors.Cause(err)) {
- manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
- if err != nil {
- return errors.Wrapf(err, "failed to get new shm lock manager")
- }
- } else if errors.Cause(err) == syscall.ERANGE && runtime.doRenumber {
- logrus.Debugf("Number of locks does not match - removing old locks")
-
- // ERANGE indicates a lock numbering mismatch.
- // Since we're renumbering, this is not fatal.
- // Remove the earlier set of locks and recreate.
- if err := os.Remove(filepath.Join("/dev/shm", lockPath)); err != nil {
- return errors.Wrapf(err, "error removing libpod locks file %s", lockPath)
- }
-
- manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
- if err != nil {
- return err
- }
- } else {
- return err
- }
+ return err
}
- runtime.lockManager = manager
// If we're renumbering locks, do it now.
// It breaks out of normal runtime init, and will not return a valid
@@ -1124,6 +1191,8 @@ func (r *Runtime) Shutdown(force bool) error {
}
var lastError error
+ // If no store was requested, it can bew nil and there is no need to
+ // attempt to shut it down
if r.store != nil {
if _, err := r.store.Shutdown(force); err != nil {
lastError = errors.Wrapf(err, "Error shutting down container storage")
@@ -1191,21 +1260,21 @@ func (r *Runtime) refresh(alivePath string) error {
}
// Info returns the store and host information
-func (r *Runtime) Info() ([]InfoData, error) {
- info := []InfoData{}
+func (r *Runtime) Info() ([]define.InfoData, error) {
+ info := []define.InfoData{}
// get host information
hostInfo, err := r.hostInfo()
if err != nil {
return nil, errors.Wrapf(err, "error getting host info")
}
- info = append(info, InfoData{Type: "host", Data: hostInfo})
+ info = append(info, define.InfoData{Type: "host", Data: hostInfo})
// get store information
storeInfo, err := r.storeInfo()
if err != nil {
return nil, errors.Wrapf(err, "error getting store info")
}
- info = append(info, InfoData{Type: "store", Data: storeInfo})
+ info = append(info, define.InfoData{Type: "store", Data: storeInfo})
reg, err := sysreg.GetRegistries()
if err != nil {
@@ -1225,7 +1294,7 @@ func (r *Runtime) Info() ([]InfoData, error) {
return nil, errors.Wrapf(err, "error getting registries")
}
registries["blocked"] = breg
- info = append(info, InfoData{Type: "registries", Data: registries})
+ info = append(info, define.InfoData{Type: "registries", Data: registries})
return info, nil
}