summaryrefslogtreecommitdiff
path: root/libpod/volume.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-12-04 16:24:56 -0500
committerMatthew Heon <mheon@redhat.com>2021-01-14 15:35:33 -0500
commitb53cb57680a6fd7b383636ac2d6cd71003532915 (patch)
tree3979d1f9763326cd4db3a80742cec3a031ca99b2 /libpod/volume.go
parent2b7793b6121d336a285fb7b9a7612c221cbf63d2 (diff)
downloadpodman-b53cb57680a6fd7b383636ac2d6cd71003532915.tar.gz
podman-b53cb57680a6fd7b383636ac2d6cd71003532915.tar.bz2
podman-b53cb57680a6fd7b383636ac2d6cd71003532915.zip
Initial implementation of volume plugins
This implements support for mounting and unmounting volumes backed by volume plugins. Support for actually retrieving plugins requires a pull request to land in containers.conf and then that to be vendored, and as such is not yet ready. Given this, this code is only compile tested. However, the code for everything past retrieving the plugin has been written - there is support for creating, removing, mounting, and unmounting volumes, which should allow full functionality once the c/common PR is merged. A major change is the signature of the MountPoint function for volumes, which now, by necessity, returns an error. Named volumes managed by a plugin do not have a mountpoint we control; instead, it is managed entirely by the plugin. As such, we need to cache the path in the DB, and calls to retrieve it now need to access the DB (and may fail as such). Notably absent is support for SELinux relabelling and chowning these volumes. Given that we don't manage the mountpoint for these volumes, I am extremely reluctant to try and modify it - we could easily break the plugin trying to chown or relabel it. Also, we had no less than *5* separate implementations of inspecting a volume floating around in pkg/infra/abi and pkg/api/handlers/libpod. And none of them used volume.Inspect(), the only correct way of inspecting volumes. Remove them all and consolidate to using the correct way. Compat API is likely still doing things the wrong way, but that is an issue for another day. Fixes #4304 Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod/volume.go')
-rw-r--r--libpod/volume.go57
1 files changed, 46 insertions, 11 deletions
diff --git a/libpod/volume.go b/libpod/volume.go
index ed08d375f..4c137cb8e 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/lock"
+ "github.com/containers/podman/v2/libpod/plugin"
)
// Volume is a libpod named volume.
@@ -18,6 +19,7 @@ type Volume struct {
state *VolumeState
valid bool
+ plugin *plugin.VolumePlugin
runtime *Runtime
lock lock.Locker
}
@@ -31,7 +33,7 @@ type VolumeConfig struct {
// Labels for the volume.
Labels map[string]string `json:"labels"`
// The volume driver. Empty string or local does not activate a volume
- // driver, all other volumes will.
+ // driver, all other values will.
Driver string `json:"volumeDriver"`
// The location the volume is mounted at.
MountPoint string `json:"mountPoint"`
@@ -53,6 +55,10 @@ type VolumeConfig struct {
// Volumes are not guaranteed to have a state. Only volumes using the Local
// driver that have mount options set will create a state.
type VolumeState struct {
+ // Mountpoint is the location where the volume was mounted.
+ // This is only used for volumes using a volume plugin, which will mount
+ // at non-standard locations.
+ MountPoint string `json:"mountPoint,omitempty"`
// MountCount is the number of times this volume has been requested to
// be mounted.
// It is incremented on mount() and decremented on unmount().
@@ -115,8 +121,20 @@ func (v *Volume) Labels() map[string]string {
}
// MountPoint returns the volume's mountpoint on the host
-func (v *Volume) MountPoint() string {
- return v.config.MountPoint
+func (v *Volume) MountPoint() (string, error) {
+ // For the sake of performance, avoid locking unless we have to.
+ if v.UsesVolumeDriver() {
+ v.lock.Lock()
+ defer v.lock.Unlock()
+
+ if err := v.update(); err != nil {
+ return "", err
+ }
+
+ return v.state.MountPoint, nil
+ }
+
+ return v.config.MountPoint, nil
}
// Options return the volume's options
@@ -139,14 +157,19 @@ func (v *Volume) UID() (int, error) {
v.lock.Lock()
defer v.lock.Unlock()
- if !v.valid {
- return -1, define.ErrVolumeRemoved
+ if err := v.update(); err != nil {
+ return -1, err
}
+ return v.uid(), nil
+}
+
+// Internal, unlocked accessor for UID.
+func (v *Volume) uid() int {
if v.state.UIDChowned > 0 {
- return v.state.UIDChowned, nil
+ return v.state.UIDChowned
}
- return v.config.UID, nil
+ return v.config.UID
}
// GID returns the GID the volume will be created as.
@@ -154,14 +177,19 @@ func (v *Volume) GID() (int, error) {
v.lock.Lock()
defer v.lock.Unlock()
- if !v.valid {
- return -1, define.ErrVolumeRemoved
+ if err := v.update(); err != nil {
+ return -1, err
}
+ return v.gid(), nil
+}
+
+// Internal, unlocked accessor for GID.
+func (v *Volume) gid() int {
if v.state.GIDChowned > 0 {
- return v.state.GIDChowned, nil
+ return v.state.GIDChowned
}
- return v.config.GID, nil
+ return v.config.GID
}
// CreatedTime returns the time the volume was created at. It was not tracked
@@ -198,3 +226,10 @@ func (v *Volume) IsDangling() (bool, error) {
}
return len(ctrs) == 0, nil
}
+
+// UsesVolumeDriver determines whether the volume uses a volume driver. Volume
+// drivers are pluggable backends for volumes that will manage the storage and
+// mounting.
+func (v *Volume) UsesVolumeDriver() bool {
+ return !(v.config.Driver == define.VolumeDriverLocal || v.config.Driver == "")
+}