Add MountTempFromSource and RemoveTemp interfaces
These interfaces can be used to setup a graphdriver mountpoint of the source directory for use within a container. The RemoveTemp interface umounts the mountpoint and then removes all of the modified data in the graphdriver for this source directory. The primary use case of these interfaces is for container engines that want to mount a directory from the host system into the container. The source dirctory then can be modified without actually changing the directory on the host. Containers will use these interfaces for sharing packaing cache directories like /var/cache/dnf, to help speed up container builds. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
e90620ceae
commit
e9695564db
|
|
@ -165,6 +165,24 @@ func setContainerBigData(flags *mflag.FlagSet, action string, m storage.Store, a
|
|||
return 0
|
||||
}
|
||||
|
||||
func MountTempContainerSource(flags *mflag.FlagSet, action string, m storage.Store, args []string) int {
|
||||
mountpoint, err := m.MountTempFromSource(args[0], args[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%+v\n", err)
|
||||
return 1
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s\n", mountpoint)
|
||||
return 0
|
||||
}
|
||||
|
||||
func RemoveTempContainerSource(flags *mflag.FlagSet, action string, m storage.Store, args []string) int {
|
||||
if err := m.RemoveTemp(args[0]); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%+v\n", err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getContainerDir(flags *mflag.FlagSet, action string, m storage.Store, args []string) int {
|
||||
path, err := m.ContainerDirectory(args[0])
|
||||
if err != nil {
|
||||
|
|
@ -305,5 +323,19 @@ func init() {
|
|||
addFlags: func(flags *mflag.FlagSet, cmd *command) {
|
||||
flags.BoolVar(&jsonOutput, []string{"-json", "j"}, jsonOutput, "Prefer JSON output")
|
||||
},
|
||||
},
|
||||
command{
|
||||
names: []string{"mount-temp"},
|
||||
optionsHelp: "[options [...]] containerNameOrID srcdir",
|
||||
usage: "Mount srcdir for use by the container",
|
||||
action: MountTempContainerSource,
|
||||
minArgs: 2,
|
||||
},
|
||||
command{
|
||||
names: []string{"remove-temp"},
|
||||
optionsHelp: "[options [...]] mountdir",
|
||||
usage: "Remove mount from use by the container",
|
||||
action: RemoveTempContainerSource,
|
||||
minArgs: 1,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -742,3 +742,14 @@ func (a *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMapp
|
|||
func (a *Driver) SupportsShifting() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
func (a *Driver) MountTempFromSource(sourcedir, source, mountLabel string) (string, error) {
|
||||
return "", fmt.Errorf("aufs driver does not support mount temp options")
|
||||
}
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
func (a *Driver) RemoveTemp(mountpoint string) error {
|
||||
return fmt.Errorf("aufs driver does not support mount temp options")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -685,3 +685,14 @@ func (d *Driver) Exists(id string) bool {
|
|||
func (d *Driver) AdditionalImageStores() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
func (d *Driver) MountTempFromSource(sourcedir, source, mountLabel string) (string, error) {
|
||||
return "", fmt.Errorf("btrfs driver does not support mount temp options")
|
||||
}
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
func (d *Driver) RemoveTemp(source string) error {
|
||||
return fmt.Errorf("btrfs driver does not support mount temp options")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,3 +242,14 @@ func (d *Driver) Exists(id string) bool {
|
|||
func (d *Driver) AdditionalImageStores() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
func (d *Driver) MountTempFromSource(sourcedir, source, mountLabel string) (string, error) {
|
||||
return "", fmt.Errorf("devmapper driver does not support mount temp options")
|
||||
}
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
func (d *Driver) RemoveTemp(mountpoint string) error {
|
||||
return fmt.Errorf("devmapper driver does not support mount temp options")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,13 @@ type ProtoDriver interface {
|
|||
Cleanup() error
|
||||
// AdditionalImageStores returns additional image stores supported by the driver
|
||||
AdditionalImageStores() []string
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
MountTempFromSource(sourcedir, source, mountLabel string) (string, error)
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
RemoveTemp(mountpoint string) error
|
||||
}
|
||||
|
||||
// DiffDriver is the interface to use to implement graph diffs
|
||||
|
|
|
|||
|
|
@ -1109,6 +1109,41 @@ func (d *Driver) SupportsShifting() bool {
|
|||
return d.options.mountProgram != ""
|
||||
}
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
func (d *Driver) MountTempFromSource(sourceDir, source, mountLabel string) (string, error) {
|
||||
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
upperDir := filepath.Join(sourceDir, "upper")
|
||||
workDir := filepath.Join(sourceDir, "work")
|
||||
mergeDir := filepath.Join(sourceDir, "merge")
|
||||
if err := idtools.MkdirAllAs(upperDir, 0700, rootUID, rootGID); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create the overlay %s directory", upperDir)
|
||||
}
|
||||
if err := idtools.MkdirAllAs(workDir, 0700, rootUID, rootGID); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create the overlay %s directory", workDir)
|
||||
}
|
||||
if err := idtools.MkdirAllAs(mergeDir, 0700, rootUID, rootGID); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create the overlay %s directory", mergeDir)
|
||||
}
|
||||
|
||||
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s,private", source, upperDir, workDir)
|
||||
mountData := label.FormatMountLabel(opts, mountLabel)
|
||||
if err := mount.Mount("none", mergeDir, "overlay", mountData); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to mount overlay %s directory", mergeDir)
|
||||
}
|
||||
return mergeDir, nil
|
||||
}
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
func (d *Driver) RemoveTemp(mountpoint string) error {
|
||||
mount.Unmount(mountpoint) //Attempt to umount source
|
||||
return os.RemoveAll(path.Dir(mountpoint))
|
||||
}
|
||||
|
||||
// dumbJoin is more or less a dumber version of filepath.Join, but one which
|
||||
// won't Clean() the path, allowing us to append ".." as a component and trust
|
||||
// pathname resolution to do some non-obvious work.
|
||||
|
|
|
|||
|
|
@ -219,3 +219,14 @@ func (d *Driver) AdditionalImageStores() []string {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
func (d *Driver) MountTempFromSource(id, source, mountLabel string) (string, error) {
|
||||
return "", fmt.Errorf("vfs driver does not support mount temp options")
|
||||
}
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
func (d *Driver) RemoveTemp(mountpoint string) error {
|
||||
return fmt.Errorf("vfs driver does not support mount temp options")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -447,3 +447,14 @@ func (d *Driver) Exists(id string) bool {
|
|||
func (d *Driver) AdditionalImageStores() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
func (d *Driver) MountTempFromSource(sourcedir, source, mountLabel string) (string, error) {
|
||||
return "", fmt.Errorf("zfs driver does not support mount temp options")
|
||||
}
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
func (d *Driver) RemoveTemp(mountpoint string) error {
|
||||
return fmt.Errorf("zfs driver does not support mount temp options")
|
||||
}
|
||||
|
|
|
|||
43
store.go
43
store.go
|
|
@ -446,6 +446,13 @@ type Store interface {
|
|||
// GID maps (if any are defined) don't contain corresponding IDs.
|
||||
ContainerParentOwners(id string) ([]int, []int, error)
|
||||
|
||||
// MountTempFromSource mounts a source directory from the host using
|
||||
// graphdriver and returns the mountpoint
|
||||
MountTempFromSource(id, source string) (string, error)
|
||||
|
||||
// RemoveTemp removes temporary mountpoint from host using graphdriver
|
||||
RemoveTemp(mountpoint string) error
|
||||
|
||||
// Lookup returns the ID of a layer, image, or container with the specified
|
||||
// name or ID.
|
||||
Lookup(name string) (string, error)
|
||||
|
|
@ -1455,6 +1462,42 @@ func (s *store) ImageBigDataSize(id, key string) (int64, error) {
|
|||
return -1, ErrSizeUnknown
|
||||
}
|
||||
|
||||
func (s *store) MountTempFromSource(id, source string) (string, error) {
|
||||
rcstore, err := s.ContainerStore()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
container, err := rcstore.Get(id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
driver, err := s.GraphDriver()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
middleDir := s.graphDriverName + "-containers"
|
||||
sourcedir := filepath.Join(s.GraphRoot(), middleDir, id, strings.Replace(source, "/", "_", -1))
|
||||
|
||||
return driver.MountTempFromSource(sourcedir, source, container.MountLabel())
|
||||
}
|
||||
|
||||
func (s *store) RemoveTemp(source string) error {
|
||||
rcstore, err := s.ContainerStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rcstore.RLock()
|
||||
defer rcstore.Unlock()
|
||||
driver, err := s.GraphDriver()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return driver.RemoveTemp(source)
|
||||
}
|
||||
|
||||
func (s *store) ImageBigDataDigest(id, key string) (digest.Digest, error) {
|
||||
ristore, err := s.ImageStore()
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue