Move rootless directory handling to the libpod/pkg/util directory

This should allow us to share this code with buildah.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2018-10-22 09:43:03 -04:00
parent 0fefe3b191
commit 2444ac9926
4 changed files with 98 additions and 100 deletions

View File

@ -1,21 +1,16 @@
package libpodruntime package libpodruntime
import ( import (
"fmt"
"os"
"path/filepath"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/pkg/errors"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
// 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 := GetDefaultStoreOptions() storageOpts, err := util.GetDefaultStoreOptions()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -28,7 +23,7 @@ func GetContainerRuntime(c *cli.Context) (*libpod.Runtime, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
storageOpts, err := GetDefaultStoreOptions() storageOpts, err := util.GetDefaultStoreOptions()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -37,51 +32,6 @@ func GetContainerRuntime(c *cli.Context) (*libpod.Runtime, error) {
return GetRuntimeWithStorageOpts(c, &storageOpts) return GetRuntimeWithStorageOpts(c, &storageOpts)
} }
func GetRootlessStorageOpts() (storage.StoreOptions, error) {
var opts storage.StoreOptions
rootlessRuntime, err := libpod.GetRootlessRuntimeDir()
if err != nil {
return opts, err
}
opts.RunRoot = filepath.Join(rootlessRuntime, "run")
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")
}
// 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)
}
dataDir = filepath.Join(resolvedHome, ".local", "share")
}
opts.GraphRoot = filepath.Join(dataDir, "containers", "storage")
opts.GraphDriverName = "vfs"
return opts, nil
}
func GetDefaultStoreOptions() (storage.StoreOptions, error) {
storageOpts := storage.DefaultStoreOptions
if rootless.IsRootless() {
var err error
storageOpts, err = GetRootlessStorageOpts()
if err != nil {
return storageOpts, err
}
storageConf := filepath.Join(os.Getenv("HOME"), ".config/containers/storage.conf")
if _, err := os.Stat(storageConf); err == nil {
storage.ReloadConfigurationFile(storageConf, &storageOpts)
}
}
return storageOpts, nil
}
// GetRuntime generates a new libpod runtime configured by command line options // GetRuntime generates a new libpod runtime configured by command line options
func GetRuntimeWithStorageOpts(c *cli.Context, storageOpts *storage.StoreOptions) (*libpod.Runtime, error) { func GetRuntimeWithStorageOpts(c *cli.Context, storageOpts *storage.StoreOptions) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{} options := []libpod.RuntimeOption{}

View File

@ -17,6 +17,7 @@ import (
"github.com/containers/libpod/pkg/ctime" "github.com/containers/libpod/pkg/ctime"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/coreos/go-systemd/activation" "github.com/coreos/go-systemd/activation"
"github.com/cri-o/ocicni/pkg/ocicni" "github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
@ -230,7 +231,7 @@ func bindPorts(ports []ocicni.PortMapping) ([]*os.File, error) {
func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, restoreContainer bool) (err error) { func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, restoreContainer bool) (err error) {
var stderrBuf bytes.Buffer var stderrBuf bytes.Buffer
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -446,7 +447,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
func (r *OCIRuntime) updateContainerStatus(ctr *Container) error { func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
state := new(spec.State) state := new(spec.State)
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -556,7 +557,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
// Sets time the container was started, but does not save it. // Sets time the container was started, but does not save it.
func (r *OCIRuntime) startContainer(ctr *Container) error { func (r *OCIRuntime) startContainer(ctr *Container) error {
// TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers? // TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers?
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -573,7 +574,7 @@ func (r *OCIRuntime) startContainer(ctr *Container) error {
// killContainer sends the given signal to the given container // killContainer sends the given signal to the given container
func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error { func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error {
logrus.Debugf("Sending signal %d to container %s", signal, ctr.ID()) logrus.Debugf("Sending signal %d to container %s", signal, ctr.ID())
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -636,7 +637,7 @@ func (r *OCIRuntime) stopContainer(ctr *Container, timeout uint) error {
args = []string{"kill", "--all", ctr.ID(), "KILL"} args = []string{"kill", "--all", ctr.ID(), "KILL"}
} }
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -667,7 +668,7 @@ func (r *OCIRuntime) deleteContainer(ctr *Container) error {
// pauseContainer pauses the given container // pauseContainer pauses the given container
func (r *OCIRuntime) pauseContainer(ctr *Container) error { func (r *OCIRuntime) pauseContainer(ctr *Container) error {
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -677,7 +678,7 @@ func (r *OCIRuntime) pauseContainer(ctr *Container) error {
// unpauseContainer unpauses the given container // unpauseContainer unpauses the given container
func (r *OCIRuntime) unpauseContainer(ctr *Container) error { func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -698,7 +699,7 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
return nil, errors.Wrapf(ErrEmptyID, "must provide a session ID for exec") return nil, errors.Wrapf(ErrEmptyID, "must provide a session ID for exec")
} }
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -780,7 +781,7 @@ func (r *OCIRuntime) execStopContainer(ctr *Container, timeout uint) error {
if len(execSessions) == 0 { if len(execSessions) == 0 {
return nil return nil
} }
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,13 +1,11 @@
package libpod package libpod
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"sync" "sync"
"syscall"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
is "github.com/containers/image/storage" is "github.com/containers/image/storage"
@ -17,6 +15,7 @@ import (
"github.com/containers/libpod/pkg/hooks" "github.com/containers/libpod/pkg/hooks"
sysreg "github.com/containers/libpod/pkg/registries" sysreg "github.com/containers/libpod/pkg/registries"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni" "github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/docker/pkg/namesgenerator" "github.com/docker/docker/pkg/namesgenerator"
@ -215,46 +214,12 @@ var (
} }
) )
// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir() (string, error) {
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
uid := fmt.Sprintf("%d", rootless.GetRootlessUID())
if runtimeDir == "" {
tmpDir := filepath.Join("/run", "user", uid)
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
tmpDir := filepath.Join(os.TempDir(), "user", uid)
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
home := os.Getenv("HOME")
if home == "" {
return "", fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
}
resolvedHome, err := filepath.EvalSymlinks(home)
if err != nil {
return "", errors.Wrapf(err, "cannot resolve %s", home)
}
runtimeDir = filepath.Join(resolvedHome, "rundir")
}
return runtimeDir, nil
}
func getDefaultTmpDir() (string, error) { func getDefaultTmpDir() (string, error) {
if !rootless.IsRootless() { if !rootless.IsRootless() {
return "/var/run/libpod", nil return "/var/run/libpod", nil
} }
rootlessRuntimeDir, err := GetRootlessRuntimeDir() rootlessRuntimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return "", err return "", err
} }
@ -269,7 +234,7 @@ func SetXdgRuntimeDir(val string) error {
} }
if val == "" { if val == "" {
var err error var err error
val, err = GetRootlessRuntimeDir() val, err = util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return err return err
} }
@ -309,7 +274,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
foundConfig = false foundConfig = false
} }
runtimeDir, err := GetRootlessRuntimeDir() runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -3,10 +3,13 @@ package util
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"syscall"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/image-spec/specs-go/v1"
@ -210,3 +213,82 @@ func ParseIDMapping(UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap stri
} }
return &options, nil return &options, nil
} }
// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir() (string, error) {
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
uid := fmt.Sprintf("%d", rootless.GetRootlessUID())
if runtimeDir == "" {
tmpDir := filepath.Join("/run", "user", uid)
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
tmpDir := filepath.Join(os.TempDir(), "user", uid)
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
home := os.Getenv("HOME")
if home == "" {
return "", fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
}
resolvedHome, err := filepath.EvalSymlinks(home)
if err != nil {
return "", errors.Wrapf(err, "cannot resolve %s", home)
}
runtimeDir = filepath.Join(resolvedHome, "rundir")
}
return runtimeDir, nil
}
func GetRootlessStorageOpts() (storage.StoreOptions, error) {
var opts storage.StoreOptions
rootlessRuntime, err := GetRootlessRuntimeDir()
if err != nil {
return opts, err
}
opts.RunRoot = filepath.Join(rootlessRuntime, "run")
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")
}
// 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)
}
dataDir = filepath.Join(resolvedHome, ".local", "share")
}
opts.GraphRoot = filepath.Join(dataDir, "containers", "storage")
opts.GraphDriverName = "vfs"
return opts, nil
}
func GetDefaultStoreOptions() (storage.StoreOptions, error) {
storageOpts := storage.DefaultStoreOptions
if rootless.IsRootless() {
var err error
storageOpts, err = GetRootlessStorageOpts()
if err != nil {
return storageOpts, err
}
storageConf := filepath.Join(os.Getenv("HOME"), ".config/containers/storage.conf")
if _, err := os.Stat(storageConf); err == nil {
storage.ReloadConfigurationFile(storageConf, &storageOpts)
}
}
return storageOpts, nil
}