From 020d81f113ea1e11398ea77495cc4b8e05a91d38 Mon Sep 17 00:00:00 2001 From: Qi Wang Date: Thu, 9 Jul 2020 15:46:14 -0400 Subject: Add support for overlay volume mounts in podman. Add support -v for overlay volume mounts in podman. Signed-off-by: Daniel J Walsh Signed-off-by: Qi Wang --- libpod/container.go | 11 +++++++++++ libpod/container_internal.go | 6 ++++++ libpod/container_internal_linux.go | 18 ++++++++++++++++++ libpod/container_internal_unsupported.go | 4 ++++ libpod/container_validate.go | 19 +++++++++++++++++++ libpod/options.go | 29 +++++++++++++++++++---------- libpod/runtime.go | 2 +- 7 files changed, 78 insertions(+), 11 deletions(-) (limited to 'libpod') diff --git a/libpod/container.go b/libpod/container.go index 1ca38ae7e..fda018640 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -262,6 +262,8 @@ type ContainerConfig struct { Mounts []string `json:"mounts,omitempty"` // NamedVolumes lists the named volumes to mount into the container. NamedVolumes []*ContainerNamedVolume `json:"namedVolumes,omitempty"` + // OverlayVolumes lists the overlay volumes to mount into the container. + OverlayVolumes []*ContainerOverlayVolume `json:"overlayVolumes,omitempty"` // Security Config @@ -449,6 +451,15 @@ type ContainerNamedVolume struct { Options []string `json:"options,omitempty"` } +// ContainerOverlayVolume is a overlay volume that will be mounted into the +// container. Each volume is a libpod Volume present in the state. +type ContainerOverlayVolume struct { + // Destination is the absolute path where the mount will be placed in the container. + Dest string `json:"dest"` + // Source specifies the source path of the mount. + Source string `json:"source,omitempty"` +} + // Config accessors // Unlocked diff --git a/libpod/container_internal.go b/libpod/container_internal.go index a79b9e5a8..b2e23b3a8 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1588,6 +1588,12 @@ func (c *Container) cleanupStorage() error { } } + if err := c.cleanupOverlayMounts(); err != nil { + // If the container can't remove content report the error + logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err) + cleanupErr = err + } + if c.config.Rootfs != "" { return cleanupErr } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 255505416..1c21f2ff9 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -20,6 +20,7 @@ import ( cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" + "github.com/containers/buildah/pkg/overlay" "github.com/containers/buildah/pkg/secrets" "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/config" @@ -319,6 +320,19 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } + // Add overlay volumes + for _, overlayVol := range c.config.OverlayVolumes { + contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID()) + if err != nil { + return nil, errors.Wrapf(err, "failed to create TempDir in the %s directory", c.config.StaticDir) + } + overlayMount, err := overlay.Mount(contentDir, overlayVol.Source, overlayVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions()) + if err != nil { + return nil, errors.Wrapf(err, "creating overlay failed %q", overlayVol.Source) + } + g.AddMount(overlayMount) + } + hasHomeSet := false for _, s := range c.config.Spec.Process.Env { if strings.HasPrefix(s, "HOME=") { @@ -1642,3 +1656,7 @@ func (c *Container) copyTimezoneFile(zonePath string) (string, error) { } return localtimeCopy, err } + +func (c *Container) cleanupOverlayMounts() error { + return overlay.CleanupContent(c.config.StaticDir) +} diff --git a/libpod/container_internal_unsupported.go b/libpod/container_internal_unsupported.go index e6d94104c..b58a5116b 100644 --- a/libpod/container_internal_unsupported.go +++ b/libpod/container_internal_unsupported.go @@ -46,6 +46,10 @@ func (c *Container) getOCICgroupPath() (string, error) { return "", define.ErrNotImplemented } +func (c *Container) cleanupOverlayMounts() error { + return nil +} + func (c *Container) getUserOverrides() *lookup.Overrides { return nil } diff --git a/libpod/container_validate.go b/libpod/container_validate.go index c02833359..666ad0aca 100644 --- a/libpod/container_validate.go +++ b/libpod/container_validate.go @@ -99,5 +99,24 @@ func (c *Container) validate() error { return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if using image's /etc/hosts") } + // Check named volume and overlay volumes destination conflits + destinations := make(map[string]bool) + for _, vol := range c.config.NamedVolumes { + // Don't check if they already exist. + // If they don't we will automatically create them. + if _, ok := destinations[vol.Dest]; ok { + return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) + } + destinations[vol.Dest] = true + } + for _, vol := range c.config.OverlayVolumes { + // Don't check if they already exist. + // If they don't we will automatically create them. + if _, ok := destinations[vol.Dest]; ok { + return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) + } + destinations[vol.Dest] = true + } + return nil } diff --git a/libpod/options.go b/libpod/options.go index 32748a3c1..40cf452db 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1380,17 +1380,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { return define.ErrCtrFinalized } - destinations := make(map[string]bool) - for _, vol := range volumes { - // Don't check if they already exist. - // If they don't we will automatically create them. - - if _, ok := destinations[vol.Dest]; ok { - return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest) - } - destinations[vol.Dest] = true - mountOpts, err := util.ProcessOptions(vol.Options, false, "") if err != nil { return errors.Wrapf(err, "error processing options for named volume %q mounted at %q", vol.Name, vol.Dest) @@ -1407,6 +1397,25 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { } } +// WithOverlayVolumes adds the given overlay volumes to the container. +func WithOverlayVolumes(volumes []*ContainerOverlayVolume) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return define.ErrCtrFinalized + } + + for _, vol := range volumes { + + ctr.config.OverlayVolumes = append(ctr.config.OverlayVolumes, &ContainerOverlayVolume{ + Dest: vol.Dest, + Source: vol.Source, + }) + } + + return nil + } +} + // WithHealthCheck adds the healthcheck to the container config func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption { return func(ctr *Container) error { diff --git a/libpod/runtime.go b/libpod/runtime.go index 0075c0e13..b30933b0c 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -577,7 +577,7 @@ func (r *Runtime) Shutdown(force bool) error { } var lastError error - // If no store was requested, it can bew nil and there is no need to + // If no store was requested, it can be nil and there is no need to // attempt to shut it down if r.store != nil { if _, err := r.store.Shutdown(force); err != nil { -- cgit v1.2.3-54-g00ecf