mirror of
https://github.com/containers/podman.git
synced 2025-12-01 18:49:18 +08:00
new "image" mount type
Add a new "image" mount type to `--mount`. The source of the mount is the name or ID of an image. The destination is the path inside the container. Image mounts further support an optional `rw,readwrite` parameter which if set to "true" will yield the mount writable inside the container. Note that no changes are propagated to the image mount on the host (which in any case is read only). Mounts are overlay mounts. To support read-only overlay mounts, vendor a non-release version of Buildah. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
81
vendor/github.com/containers/buildah/pkg/overlay/overlay.go
generated
vendored
81
vendor/github.com/containers/buildah/pkg/overlay/overlay.go
generated
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/containers/storage/pkg/unshare"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -48,10 +49,36 @@ func TempDir(containerDir string, rootUID, rootGID int) (string, error) {
|
||||
// from the source system. It then mounts up the source directory on to the
|
||||
// generated mount point and returns the mount point to the caller.
|
||||
func Mount(contentDir, source, dest string, rootUID, rootGID int, graphOptions []string) (mount specs.Mount, Err error) {
|
||||
upperDir := filepath.Join(contentDir, "upper")
|
||||
workDir := filepath.Join(contentDir, "work")
|
||||
return mountHelper(contentDir, source, dest, rootUID, rootGID, graphOptions, false)
|
||||
}
|
||||
|
||||
// MountReadOnly creates a subdir of the contentDir based on the source directory
|
||||
// from the source system. It then mounts up the source directory on to the
|
||||
// generated mount point and returns the mount point to the caller. Note that no
|
||||
// upper layer will be created rendering it a read-only mount
|
||||
func MountReadOnly(contentDir, source, dest string, rootUID, rootGID int, graphOptions []string) (mount specs.Mount, Err error) {
|
||||
return mountHelper(contentDir, source, dest, rootUID, rootGID, graphOptions, true)
|
||||
}
|
||||
|
||||
// NOTE: rootUID and rootUID are not yet used.
|
||||
func mountHelper(contentDir, source, dest string, _, _ int, graphOptions []string, readOnly bool) (mount specs.Mount, Err error) {
|
||||
mergeDir := filepath.Join(contentDir, "merge")
|
||||
overlayOptions := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s,private", source, upperDir, workDir)
|
||||
|
||||
// Create overlay mount options for rw/ro.
|
||||
var overlayOptions string
|
||||
if readOnly {
|
||||
// Read-only overlay mounts require two lower layer.
|
||||
lowerTwo := filepath.Join(contentDir, "lower")
|
||||
if err := os.Mkdir(lowerTwo, 0755); err != nil {
|
||||
return mount, err
|
||||
}
|
||||
overlayOptions = fmt.Sprintf("lowerdir=%s:%s,private", source, lowerTwo)
|
||||
} else {
|
||||
// Read-write overlay mounts want a lower, upper and a work layer.
|
||||
workDir := filepath.Join(contentDir, "work")
|
||||
upperDir := filepath.Join(contentDir, "upper")
|
||||
overlayOptions = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s,private", source, upperDir, workDir)
|
||||
}
|
||||
|
||||
if unshare.IsRootless() {
|
||||
mountProgram := ""
|
||||
@@ -90,7 +117,7 @@ func Mount(contentDir, source, dest string, rootUID, rootGID int, graphOptions [
|
||||
/* If a mount_program is not specified, fallback to try mount native overlay. */
|
||||
}
|
||||
|
||||
mount.Source = "overlay"
|
||||
mount.Source = mergeDir
|
||||
mount.Destination = dest
|
||||
mount.Type = "overlay"
|
||||
mount.Options = strings.Split(overlayOptions, ",")
|
||||
@@ -101,18 +128,34 @@ func Mount(contentDir, source, dest string, rootUID, rootGID int, graphOptions [
|
||||
// RemoveTemp removes temporary mountpoint and all content from its parent
|
||||
// directory
|
||||
func RemoveTemp(contentDir string) error {
|
||||
if unshare.IsRootless() {
|
||||
if err := Unmount(contentDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Unmount(contentDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.RemoveAll(contentDir)
|
||||
}
|
||||
|
||||
// Unmount the overlay mountpoint
|
||||
func Unmount(contentDir string) (Err error) {
|
||||
func Unmount(contentDir string) error {
|
||||
mergeDir := filepath.Join(contentDir, "merge")
|
||||
if err := unix.Unmount(mergeDir, 0); err != nil && !os.IsNotExist(err) {
|
||||
|
||||
if unshare.IsRootless() {
|
||||
// Attempt to unmount the FUSE mount using either fusermount or fusermount3.
|
||||
// If they fail, fallback to unix.Unmount
|
||||
for _, v := range []string{"fusermount3", "fusermount"} {
|
||||
err := exec.Command(v, "-u", mergeDir).Run()
|
||||
if err != nil && errors.Cause(err) != exec.ErrNotFound {
|
||||
logrus.Debugf("Error unmounting %s with %s - %v", mergeDir, v, err)
|
||||
}
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// If fusermount|fusermount3 failed to unmount the FUSE file system, attempt unmount
|
||||
}
|
||||
|
||||
// Ignore EINVAL as the specified merge dir is not a mount point
|
||||
if err := unix.Unmount(mergeDir, 0); err != nil && !os.IsNotExist(err) && err != unix.EINVAL {
|
||||
return errors.Wrapf(err, "unmount overlay %s", mergeDir)
|
||||
}
|
||||
return nil
|
||||
@@ -153,14 +196,20 @@ func CleanupMount(contentDir string) (Err error) {
|
||||
func CleanupContent(containerDir string) (Err error) {
|
||||
contentDir := filepath.Join(containerDir, "overlay")
|
||||
|
||||
if unshare.IsRootless() {
|
||||
mergeDir := filepath.Join(contentDir, "merge")
|
||||
if err := unix.Unmount(mergeDir, 0); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "unmount overlay %s", mergeDir)
|
||||
}
|
||||
files, err := ioutil.ReadDir(contentDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "read directory")
|
||||
}
|
||||
for _, f := range files {
|
||||
dir := filepath.Join(contentDir, f.Name())
|
||||
if err := Unmount(dir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(contentDir); err != nil && !os.IsNotExist(err) {
|
||||
return errors.Wrapf(err, "failed to cleanup overlay %s directory", contentDir)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user