aboutsummaryrefslogtreecommitdiff
path: root/pkg/util/utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/util/utils.go')
-rw-r--r--pkg/util/utils.go101
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
}