diff options
Diffstat (limited to 'pkg/util/utils.go')
-rw-r--r-- | pkg/util/utils.go | 101 |
1 files changed, 88 insertions, 13 deletions
diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 69f49e72a..f567f2675 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -3,11 +3,13 @@ package util import ( "fmt" "os" + "os/exec" "path/filepath" "strconv" "strings" "syscall" + "github.com/BurntSushi/toml" "github.com/containers/image/types" "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage" @@ -248,49 +250,122 @@ func GetRootlessRuntimeDir() (string, error) { return runtimeDir, nil } -// GetRootlessStorageOpts returns the storage ops for containers running as non root -func GetRootlessStorageOpts() (storage.StoreOptions, error) { - var opts storage.StoreOptions - +// GetRootlessDirInfo returns the parent path of where the storage for containers and +// volumes will be in rootless mode +func GetRootlessDirInfo() (string, string, error) { rootlessRuntime, err := GetRootlessRuntimeDir() if err != nil { - return opts, err + return "", "", err } - opts.RunRoot = rootlessRuntime dataDir := os.Getenv("XDG_DATA_HOME") if dataDir == "" { home := os.Getenv("HOME") if home == "" { - return opts, fmt.Errorf("neither XDG_DATA_HOME nor HOME was set non-empty") + return "", "", fmt.Errorf("neither XDG_DATA_HOME nor HOME was set non-empty") } // runc doesn't like symlinks in the rootfs path, and at least // on CoreOS /home is a symlink to /var/home, so resolve any symlink. resolvedHome, err := filepath.EvalSymlinks(home) if err != nil { - return opts, errors.Wrapf(err, "cannot resolve %s", home) + return "", "", errors.Wrapf(err, "cannot resolve %s", home) } dataDir = filepath.Join(resolvedHome, ".local", "share") } + return dataDir, rootlessRuntime, nil +} + +// GetRootlessStorageOpts returns the storage opts for containers running as non root +func GetRootlessStorageOpts() (storage.StoreOptions, error) { + var opts storage.StoreOptions + + dataDir, rootlessRuntime, err := GetRootlessDirInfo() + if err != nil { + return opts, err + } + opts.RunRoot = rootlessRuntime opts.GraphRoot = filepath.Join(dataDir, "containers", "storage") - opts.GraphDriverName = "vfs" + if path, err := exec.LookPath("fuse-overlayfs"); err == nil { + opts.GraphDriverName = "overlay" + opts.GraphDriverOptions = []string{fmt.Sprintf("overlay.mount_program=%s", path)} + } else { + opts.GraphDriverName = "vfs" + } return opts, nil } -// GetDefaultStoreOptions returns the storage ops for containers -func GetDefaultStoreOptions() (storage.StoreOptions, error) { +// GetRootlessVolumeInfo returns where all the name volumes will be created in rootless mode +func GetRootlessVolumeInfo() (string, error) { + dataDir, _, err := GetRootlessDirInfo() + if err != nil { + return "", err + } + return filepath.Join(dataDir, "containers", "storage", "volumes"), nil +} + +type tomlOptionsConfig struct { + MountProgram string `toml:"mount_program"` +} + +type tomlConfig struct { + Storage struct { + Driver string `toml:"driver"` + RunRoot string `toml:"runroot"` + GraphRoot string `toml:"graphroot"` + Options struct{ tomlOptionsConfig } `toml:"options"` + } `toml:"storage"` +} + +func getTomlStorage(storeOptions *storage.StoreOptions) *tomlConfig { + config := new(tomlConfig) + + config.Storage.Driver = storeOptions.GraphDriverName + config.Storage.RunRoot = storeOptions.RunRoot + config.Storage.GraphRoot = storeOptions.GraphRoot + for _, i := range storeOptions.GraphDriverOptions { + s := strings.Split(i, "=") + if s[0] == "overlay.mount_program" { + config.Storage.Options.MountProgram = s[1] + } + } + + return config +} + +// GetDefaultStoreOptions returns the storage ops for containers and the volume path +// for the volume API +// It also returns the path where all named volumes will be created using the volume API +func GetDefaultStoreOptions() (storage.StoreOptions, string, error) { storageOpts := storage.DefaultStoreOptions + volumePath := "/var/lib/containers/storage" if rootless.IsRootless() { var err error storageOpts, err = GetRootlessStorageOpts() if err != nil { - return storageOpts, err + return storageOpts, volumePath, err + } + volumePath, err = GetRootlessVolumeInfo() + if err != nil { + return storageOpts, volumePath, err } storageConf := filepath.Join(os.Getenv("HOME"), ".config/containers/storage.conf") if _, err := os.Stat(storageConf); err == nil { storage.ReloadConfigurationFile(storageConf, &storageOpts) + } else if os.IsNotExist(err) { + os.MkdirAll(filepath.Dir(storageConf), 0755) + file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if err != nil { + return storageOpts, volumePath, errors.Wrapf(err, "cannot open %s", storageConf) + } + + tomlConfiguration := getTomlStorage(&storageOpts) + defer file.Close() + enc := toml.NewEncoder(file) + if err := enc.Encode(tomlConfiguration); err != nil { + os.Remove(storageConf) + } } } - return storageOpts, nil + return storageOpts, volumePath, nil } |