From 11799f4e0ec6256c65691828fb73501bda5d7eec Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 12 Mar 2019 15:53:08 -0400 Subject: Add named volumes for each container to database Signed-off-by: Matthew Heon --- libpod/options.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'libpod/options.go') diff --git a/libpod/options.go b/libpod/options.go index 24f126e66..86f1747ce 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1255,6 +1255,38 @@ func withIsInfra() CtrCreateOption { } } +// WithNamedVolumes adds the given named volumes to the container. +func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return ErrCtrFinalized + } + + destinations := make(map[string]bool) + + for _, vol := range volumes { + // First check if libpod has the volumes + _, err := ctr.runtime.GetVolume(vol.Name) + if err != nil { + return errors.Wrapf(err, "error retrieving volume %s to add to container", vol.Name) + } + + if _, ok := destinations[vol.Dest]; ok { + return errors.Wrapf(err, "two volumes found with destination %s", vol.Dest) + } + destinations[vol.Dest] = true + + ctr.config.NamedVolumes = append(ctr.config.NamedVolumes, &ContainerNamedVolume{ + Name: vol.Name, + Dest: vol.Dest, + Options: vol.Options, + }) + } + + return nil + } +} + // Volume Creation Options // WithVolumeName sets the name of the volume. -- cgit v1.2.3-54-g00ecf From ee770ad5b54845e345384be3e01c700e93926b44 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 22 Mar 2019 14:23:18 -0400 Subject: Create non-existing named volumes at container create Replaces old functionality we used for handling image volumes. Signed-off-by: Matthew Heon --- libpod/options.go | 53 ++++++++++++++++++++++++++------------------------- libpod/runtime_ctr.go | 49 ++++++++++++++++++++++------------------------- 2 files changed, 50 insertions(+), 52 deletions(-) (limited to 'libpod/options.go') diff --git a/libpod/options.go b/libpod/options.go index 86f1747ce..4f35a5c8c 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1265,14 +1265,11 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { destinations := make(map[string]bool) for _, vol := range volumes { - // First check if libpod has the volumes - _, err := ctr.runtime.GetVolume(vol.Name) - if err != nil { - return errors.Wrapf(err, "error retrieving volume %s to add to container", vol.Name) - } + // 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(err, "two volumes found with destination %s", vol.Dest) + return errors.Wrapf(ErrInvalidArg, "two volumes found with destination %s", vol.Dest) } destinations[vol.Dest] = true @@ -1306,68 +1303,72 @@ func WithVolumeName(name string) VolumeCreateOption { } } -// WithVolumeUID sets the uid of the owner. -func WithVolumeUID(uid int) VolumeCreateOption { +// WithVolumeLabels sets the labels of the volume. +func WithVolumeLabels(labels map[string]string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return ErrVolumeFinalized } - volume.config.UID = uid + + volume.config.Labels = make(map[string]string) + for key, value := range labels { + volume.config.Labels[key] = value + } + return nil } } -// WithVolumeGID sets the gid of the owner. -func WithVolumeGID(gid int) VolumeCreateOption { +// WithVolumeDriver sets the driver of the volume. +func WithVolumeDriver(driver string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return ErrVolumeFinalized } - volume.config.GID = gid + + volume.config.Driver = driver + return nil } } -// WithVolumeLabels sets the labels of the volume. -func WithVolumeLabels(labels map[string]string) VolumeCreateOption { +// WithVolumeOptions sets the options of the volume. +func WithVolumeOptions(options map[string]string) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return ErrVolumeFinalized } - volume.config.Labels = make(map[string]string) - for key, value := range labels { - volume.config.Labels[key] = value + volume.config.Options = make(map[string]string) + for key, value := range options { + volume.config.Options[key] = value } return nil } } -// WithVolumeDriver sets the driver of the volume. -func WithVolumeDriver(driver string) VolumeCreateOption { +// WithVolumeUID sets the UID that the volume will be created as. +func WithVolumeUID(uid int) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return ErrVolumeFinalized } - volume.config.Driver = driver + volume.config.UID = uid return nil } } -// WithVolumeOptions sets the options of the volume. -func WithVolumeOptions(options map[string]string) VolumeCreateOption { +// WithVolumeGID sets the GID that the volume will be created as. +func WithVolumeGID(gid int) VolumeCreateOption { return func(volume *Volume) error { if volume.valid { return ErrVolumeFinalized } - volume.config.Options = make(map[string]string) - for key, value := range options { - volume.config.Options[key] = value - } + volume.config.GID = gid return nil } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index ec43d5dcb..fafbc9969 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -99,9 +99,6 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. ctr.state.State = ContainerStateConfigured ctr.runtime = r - ctr.valid = true - ctr.state.State = ContainerStateConfigured - var pod *Pod if ctr.config.Pod != "" { // Get the pod from state @@ -173,29 +170,29 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid") } - // // Go through the volume mounts and check for named volumes - // // If the named volme already exists continue, otherwise create - // // the storage for the named volume. - // for i, vol := range ctr.config.Spec.Mounts { - // if vol.Source[0] != '/' && isNamedVolume(vol.Source) { - // volInfo, err := r.state.Volume(vol.Source) - // if err != nil { - // newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source), withSetCtrSpecific()) - // if err != nil { - // return nil, errors.Wrapf(err, "error creating named volume %q", vol.Source) - // } - // ctr.config.Spec.Mounts[i].Source = newVol.MountPoint() - // if err := os.Chown(ctr.config.Spec.Mounts[i].Source, ctr.RootUID(), ctr.RootGID()); err != nil { - // return nil, errors.Wrapf(err, "cannot chown %q to %d:%d", ctr.config.Spec.Mounts[i].Source, ctr.RootUID(), ctr.RootGID()) - // } - // if err := ctr.copyWithTarFromImage(ctr.config.Spec.Mounts[i].Destination, ctr.config.Spec.Mounts[i].Source); err != nil && !os.IsNotExist(err) { - // return nil, errors.Wrapf(err, "Failed to copy content into new volume mount %q", vol.Source) - // } - // continue - // } - // ctr.config.Spec.Mounts[i].Source = volInfo.MountPoint() - // } - // } + // Go through named volumes and add them. + // If they don't exist they will be created using basic options. + for _, vol := range ctr.config.NamedVolumes { + // Check if it exists already + _, err := r.state.Volume(vol.Name) + if err == nil { + // The volume exists, we're good + continue + } else if errors.Cause(err) != ErrNoSuchVolume { + return nil, errors.Wrapf(err, "error retrieving named volume %s for new container", vol.Name) + } + + // The volume does not exist, so we need to create it. + newVol, err := r.newVolume(ctx, WithVolumeName(vol.Name), withSetCtrSpecific(), + WithVolumeUID(ctr.RootUID()), WithVolumeGID(ctr.RootGID())) + if err != nil { + return nil, errors.Wrapf(err, "error creating named volume %q", vol.Name) + } + + if err := ctr.copyWithTarFromImage(vol.Dest, newVol.MountPoint()); err != nil && !os.IsNotExist(err) { + return nil, errors.Wrapf(err, "Failed to copy content into new volume mount %q", vol.Name) + } + } if ctr.config.LogPath == "" { ctr.config.LogPath = filepath.Join(ctr.config.StaticDir, "ctr.log") -- cgit v1.2.3-54-g00ecf From 1fdc89f616fead07b9b49e949f7c7cebba951070 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 3 Apr 2019 19:49:09 -0400 Subject: Drop LocalVolumes from our the database We were never using it. It's actually a potentially quite sizable field (very expensive to decode an array of structs!). Removing it should do no harm. Signed-off-by: Matthew Heon --- libpod/container.go | 3 --- libpod/options.go | 19 ------------------- pkg/spec/createconfig.go | 27 ++++++++++----------------- pkg/spec/spec.go | 9 ++++----- 4 files changed, 14 insertions(+), 44 deletions(-) (limited to 'libpod/options.go') diff --git a/libpod/container.go b/libpod/container.go index 74dc5be5c..6d5e063ab 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -356,9 +356,6 @@ type ContainerConfig struct { // ExitCommand is the container's exit command. // This Command will be executed when the container exits ExitCommand []string `json:"exitCommand,omitempty"` - // LocalVolumes are the built-in volumes we get from the --volumes-from flag - // It picks up the built-in volumes of the container used by --volumes-from - LocalVolumes []spec.Mount // IsInfra is a bool indicating whether this container is an infra container used for // sharing kernel namespaces in a pod IsInfra bool `json:"pause"` diff --git a/libpod/options.go b/libpod/options.go index 4f35a5c8c..9326e54e4 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -13,7 +13,6 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/cri-o/ocicni/pkg/ocicni" - spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) @@ -1111,24 +1110,6 @@ func WithUserVolumes(volumes []string) CtrCreateOption { } } -// WithLocalVolumes sets the built-in volumes of the container retrieved -// from a container passed in to the --volumes-from flag. -// This stores the built-in volume information in the Config so we can -// add them when creating the container. -func WithLocalVolumes(volumes []spec.Mount) CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return ErrCtrFinalized - } - - if volumes != nil { - ctr.config.LocalVolumes = append(ctr.config.LocalVolumes, volumes...) - } - - return nil - } -} - // WithEntrypoint sets the entrypoint of the container. // This is not used to change the container's spec, but will instead be used // during commit to populate the entrypoint of the new image. diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index bcaa2333b..e71d9d3db 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -22,18 +22,16 @@ import ( "golang.org/x/sys/unix" ) -type mountType string - // Type constants const ( bps = iota iops // TypeBind is the type for mounting host dir - TypeBind mountType = "bind" + TypeBind = "bind" // TypeVolume is the type for remote storage volumes - // TypeVolume mountType = "volume" // re-enable upon use + // TypeVolume = "volume" // re-enable upon use // TypeTmpfs is the type for mounting tmpfs - TypeTmpfs mountType = "tmpfs" + TypeTmpfs = "tmpfs" ) // CreateResourceConfig represents resource elements in CreateConfig @@ -137,8 +135,7 @@ type CreateConfig struct { SeccompProfilePath string //SecurityOpts SecurityOpts []string Rootfs string - LocalVolumes []spec.Mount //Keeps track of the built-in volumes of container used in the --volumes-from flag - Syslog bool // Whether to enable syslog on exit commands + Syslog bool // Whether to enable syslog on exit commands } func u32Ptr(i int64) *uint32 { u := uint32(i); return &u } @@ -172,9 +169,9 @@ func (c *CreateConfig) AddContainerInitBinary(path string) error { c.Command = append([]string{"/dev/init", "--"}, c.Command...) c.Mounts = append(c.Mounts, spec.Mount{ Destination: "/dev/init", - Type: "bind", + Type: TypeBind, Source: path, - Options: []string{"bind", "ro"}, + Options: []string{TypeBind, "ro"}, }) return nil } @@ -219,7 +216,7 @@ func (c *CreateConfig) initFSMounts() []spec.Mount { // GetVolumeMounts takes user provided input for bind mounts and creates Mount structs func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, error) { - m := c.LocalVolumes + m := []spec.Mount{} for _, i := range c.Volumes { var options []string spliti := strings.Split(i, ":") @@ -259,7 +256,7 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e // Should tmpfs also be handled as named volumes? Wouldn't be hard // This will cause a new local Volume to be created on your system mount.Source = stringid.GenerateNonCryptoID() - mount.Options = append(mount.Options, "bind") + mount.Options = append(mount.Options, TypeBind) } m = append(m, mount) } @@ -306,7 +303,7 @@ func (c *CreateConfig) GetVolumesFrom() error { return errors.Errorf("error retrieving container %s spec", ctr.ID()) } for _, mnt := range spec.Mounts { - if mnt.Type != "bind" { + if mnt.Type != TypeBind { continue } if _, exists := userVolumes[mnt.Destination]; exists { @@ -453,10 +450,6 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l options = append(options, libpod.WithNamedVolumes(c.NamedVolumes)) } - if len(c.LocalVolumes) != 0 { - options = append(options, libpod.WithLocalVolumes(c.LocalVolumes)) - } - if len(c.Command) != 0 { options = append(options, libpod.WithCommand(c.Command)) } @@ -568,7 +561,7 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l options = append(options, libpod.WithPrivileged(c.Privileged)) - useImageVolumes := c.ImageVolumeType == "bind" + useImageVolumes := c.ImageVolumeType == TypeBind // Gather up the options for NewContainer which consist of With... funcs options = append(options, libpod.WithRootFSFromImage(c.ImageID, c.Image, useImageVolumes)) options = append(options, libpod.WithSecLabels(c.LabelOpts)) diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 53aad21d7..9b6bd089e 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -20,7 +20,6 @@ import ( ) const cpuPeriod = 100000 -const bindMount = "bind" func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.Mount { if len(mounts) > 0 { @@ -56,7 +55,7 @@ func splitNamedVolumes(mounts []spec.Mount) ([]spec.Mount, []*libpod.ContainerNa namedVolumes := make([]*libpod.ContainerNamedVolume, 0) for _, mount := range mounts { // If it's not a named volume, append unconditionally - if mount.Type != bindMount { + if mount.Type != TypeBind { newMounts = append(newMounts, mount) continue } @@ -128,7 +127,7 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } sysMnt := spec.Mount{ Destination: "/sys", - Type: bindMount, + Type: TypeBind, Source: "/sys", Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"}, } @@ -155,7 +154,7 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint g.RemoveMount("/dev/mqueue") devMqueue := spec.Mount{ Destination: "/dev/mqueue", - Type: bindMount, + Type: TypeBind, Source: "/dev/mqueue", Options: []string{"bind", "nosuid", "noexec", "nodev"}, } @@ -165,7 +164,7 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint g.RemoveMount("/proc") procMount := spec.Mount{ Destination: "/proc", - Type: bindMount, + Type: TypeBind, Source: "/proc", Options: []string{"rbind", "nosuid", "noexec", "nodev"}, } -- cgit v1.2.3-54-g00ecf