Improve parsing of mounts

Specifically, we were needlessly doing a double lookup to find which config mounts were user volumes. Improve this by refactoring a bit of code from inspect

Signed-off-by: Peter Hunt <pehunt@redhat.com>
This commit is contained in:
Peter Hunt 2019-07-02 11:40:14 -04:00
parent 341f5e22e5
commit aeabc45cce
3 changed files with 112 additions and 97 deletions

View File

@ -368,23 +368,8 @@ func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]InspectMount, error)
return inspectMounts, nil
}
// We need to parse all named volumes and mounts into maps, so we don't
// end up with repeated lookups for each user volume.
// Map destination to struct, as destination is what is stored in
// UserVolumes.
namedVolumes := make(map[string]*ContainerNamedVolume)
mounts := make(map[string]spec.Mount)
for _, namedVol := range c.config.NamedVolumes {
namedVolumes[namedVol.Dest] = namedVol
}
for _, mount := range ctrSpec.Mounts {
mounts[mount.Destination] = mount
}
for _, vol := range c.config.UserVolumes {
// We need to look up the volumes.
// First: is it a named volume?
if volume, ok := namedVolumes[vol]; ok {
namedVolumes, mounts := c.sortUserVolumes(ctrSpec)
for _, volume := range namedVolumes {
mountStruct := InspectMount{}
mountStruct.Type = "volume"
mountStruct.Destination = volume.Dest
@ -402,7 +387,8 @@ func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]InspectMount, error)
parseMountOptionsForInspect(volume.Options, &mountStruct)
inspectMounts = append(inspectMounts, mountStruct)
} else if mount, ok := mounts[vol]; ok {
}
for _, mount := range mounts {
// It's a mount.
// Is it a tmpfs? If so, discard.
if mount.Type == "tmpfs" {
@ -418,9 +404,6 @@ func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]InspectMount, error)
inspectMounts = append(inspectMounts, mountStruct)
}
// We couldn't find a mount. Log a warning.
logrus.Warnf("Could not find mount at destination %q when building inspect output for container %s", vol, c.ID())
}
return inspectMounts, nil
}

View File

@ -1534,3 +1534,34 @@ func (c *Container) prepareCheckpointExport() (err error) {
return nil
}
// sortUserVolumes sorts the volumes specified for a container
// between named and normal volumes
func (c *Container) sortUserVolumes(ctrSpec *spec.Spec) ([]*ContainerNamedVolume, []spec.Mount) {
namedUserVolumes := []*ContainerNamedVolume{}
userMounts := []spec.Mount{}
// We need to parse all named volumes and mounts into maps, so we don't
// end up with repeated lookups for each user volume.
// Map destination to struct, as destination is what is stored in
// UserVolumes.
namedVolumes := make(map[string]*ContainerNamedVolume)
mounts := make(map[string]spec.Mount)
for _, namedVol := range c.config.NamedVolumes {
namedVolumes[namedVol.Dest] = namedVol
}
for _, mount := range ctrSpec.Mounts {
mounts[mount.Destination] = mount
}
for _, vol := range c.config.UserVolumes {
if volume, ok := namedVolumes[vol]; ok {
namedUserVolumes = append(namedUserVolumes, volume)
} else if mount, ok := mounts[vol]; ok {
userMounts = append(userMounts, mount)
} else {
logrus.Warnf("Could not find mount at destination %q when parsing user volumes for container %s", vol, c.ID())
}
}
return namedUserVolumes, userMounts
}

View File

@ -340,11 +340,31 @@ func libpodMaxAndMinToResourceList(c *Container) (v1.ResourceList, v1.ResourceLi
return maxResources, minResources
}
func generateKubeVolumeMount(hostSourcePath string, mounts []specs.Mount) (v1.VolumeMount, v1.Volume, error) {
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, error) {
var vms []v1.VolumeMount
var vos []v1.Volume
// TjDO when named volumes are supported in play kube, also parse named volumes here
_, mounts := c.sortUserVolumes(c.config.Spec)
for _, m := range mounts {
vm, vo, err := generateKubeVolumeMount(m)
if err != nil {
return vms, vos, err
}
vms = append(vms, vm)
vos = append(vos, vo)
}
return vms, vos, nil
}
// generateKubeVolumeMount takes a user specfied mount and returns
// a kubernetes VolumeMount (to be added to the container) and a kubernetes Volume
// (to be added to the pod)
func generateKubeVolumeMount(m specs.Mount) (v1.VolumeMount, v1.Volume, error) {
vm := v1.VolumeMount{}
vo := v1.Volume{}
for _, m := range mounts {
if m.Destination == hostSourcePath {
name, err := convertVolumePathToName(m.Source)
if err != nil {
return vm, vo, err
@ -370,11 +390,9 @@ func generateKubeVolumeMount(hostSourcePath string, mounts []specs.Mount) (v1.Vo
hostPathType = v1.HostPathFile
}
vo.HostPath.Type = &hostPathType
return vm, vo, nil
}
}
return vm, vo, errors.New("unable to find mount source")
}
func isHostPathDirectory(hostPathSource string) (bool, error) {
info, err := os.Stat(hostPathSource)
@ -400,23 +418,6 @@ func convertVolumePathToName(hostSourcePath string) (string, error) {
return strings.Replace(strings.Trim(hostSourcePath, "/"), "/", "-", -1), nil
}
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, error) {
// At this point, I dont think we can distinguish between the default
// volume mounts and user added ones. For now, we pass them all.
var vms []v1.VolumeMount
var vos []v1.Volume
for _, hostSourcePath := range c.config.UserVolumes {
vm, vo, err := generateKubeVolumeMount(hostSourcePath, c.config.Spec.Mounts)
if err != nil {
return vms, vos, err
}
vms = append(vms, vm)
vos = append(vos, vo)
}
return vms, vos, nil
}
func determineCapAddDropFromCapabilities(defaultCaps, containerCaps []string) *v1.Capabilities {
var (
drop []v1.Capability