Browse Source

Update executor volumes from swarmkit

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Tonis Tiigi 9 years ago
parent
commit
6586f4f071
1 changed files with 86 additions and 27 deletions
  1. 86 27
      daemon/cluster/executor/container/container.go

+ 86 - 27
daemon/cluster/executor/container/container.go

@@ -88,20 +88,6 @@ func (c *containerConfig) image() string {
 	return reference.WithDefaultTag(ref).String()
 }
 
-func (c *containerConfig) volumes() map[string]struct{} {
-	r := make(map[string]struct{})
-
-	for _, m := range c.spec().Mounts {
-		// pick off all the volume mounts.
-		if m.Type != api.MountTypeVolume || m.Source != "" {
-			continue
-		}
-		r[m.Target] = struct{}{}
-	}
-
-	return r
-}
-
 func (c *containerConfig) config() *enginecontainer.Config {
 	config := &enginecontainer.Config{
 		Labels:     c.labels(),
@@ -159,20 +145,48 @@ func (c *containerConfig) labels() map[string]string {
 	return labels
 }
 
-func (c *containerConfig) bindMounts() []string {
-	var r []string
+// volumes gets placed into the Volumes field on the containerConfig.
+func (c *containerConfig) volumes() map[string]struct{} {
+	r := make(map[string]struct{})
+	// Volumes *only* creates anonymous volumes. The rest is mixed in with
+	// binds, which aren't actually binds. Basically, any volume that
+	// results in a single component must be added here.
+	//
+	// This is reversed engineered from the behavior of the engine API.
+	for _, mount := range c.spec().Mounts {
+		if mount.Type == api.MountTypeVolume && mount.Source == "" {
+			r[mount.Target] = struct{}{}
+		}
+	}
+	return r
+}
+
+func (c *containerConfig) tmpfs() map[string]string {
+	r := make(map[string]string)
 
-	for _, val := range c.spec().Mounts {
-		if val.Type == api.MountTypeBind || (val.Type == api.MountTypeVolume && val.Source != "") {
-			mask := getMountMask(&val)
-			spec := fmt.Sprintf("%s:%s", val.Source, val.Target)
+	for _, spec := range c.spec().Mounts {
+		if spec.Type != api.MountTypeTmpfs {
+			continue
+		}
+
+		r[spec.Target] = getMountMask(&spec)
+	}
+
+	return r
+}
+
+func (c *containerConfig) binds() []string {
+	var r []string
+	for _, mount := range c.spec().Mounts {
+		if mount.Type == api.MountTypeBind || (mount.Type == api.MountTypeVolume && mount.Source != "") {
+			spec := fmt.Sprintf("%s:%s", mount.Source, mount.Target)
+			mask := getMountMask(&mount)
 			if mask != "" {
 				spec = fmt.Sprintf("%s:%s", spec, mask)
 			}
 			r = append(r, spec)
 		}
 	}
-
 	return r
 }
 
@@ -182,7 +196,16 @@ func getMountMask(m *api.Mount) string {
 		maskOpts = append(maskOpts, "ro")
 	}
 
-	if m.BindOptions != nil {
+	switch m.Type {
+	case api.MountTypeVolume:
+		if m.VolumeOptions != nil && m.VolumeOptions.NoCopy {
+			maskOpts = append(maskOpts, "nocopy")
+		}
+	case api.MountTypeBind:
+		if m.BindOptions == nil {
+			break
+		}
+
 		switch m.BindOptions.Propagation {
 		case api.MountPropagationPrivate:
 			maskOpts = append(maskOpts, "private")
@@ -197,20 +220,56 @@ func getMountMask(m *api.Mount) string {
 		case api.MountPropagationRSlave:
 			maskOpts = append(maskOpts, "rslave")
 		}
-	}
+	case api.MountTypeTmpfs:
+		if m.TmpfsOptions == nil {
+			break
+		}
 
-	if m.VolumeOptions != nil {
-		if m.VolumeOptions.NoCopy {
-			maskOpts = append(maskOpts, "nocopy")
+		if m.TmpfsOptions.Mode != 0 {
+			maskOpts = append(maskOpts, fmt.Sprintf("mode=%o", m.TmpfsOptions.Mode))
+		}
+
+		if m.TmpfsOptions.SizeBytes != 0 {
+			// calculate suffix here, making this linux specific, but that is
+			// okay, since API is that way anyways.
+
+			// we do this by finding the suffix that divides evenly into the
+			// value, returing the value itself, with no suffix, if it fails.
+			//
+			// For the most part, we don't enforce any semantic to this values.
+			// The operating system will usually align this and enforce minimum
+			// and maximums.
+			var (
+				size   = m.TmpfsOptions.SizeBytes
+				suffix string
+			)
+			for _, r := range []struct {
+				suffix  string
+				divisor int64
+			}{
+				{"g", 1 << 30},
+				{"m", 1 << 20},
+				{"k", 1 << 10},
+			} {
+				if size%r.divisor == 0 {
+					size = size / r.divisor
+					suffix = r.suffix
+					break
+				}
+			}
+
+			maskOpts = append(maskOpts, fmt.Sprintf("size=%d%s", size, suffix))
 		}
 	}
+
 	return strings.Join(maskOpts, ",")
 }
 
 func (c *containerConfig) hostConfig() *enginecontainer.HostConfig {
 	return &enginecontainer.HostConfig{
 		Resources: c.resources(),
-		Binds:     c.bindMounts(),
+		Binds:     c.binds(),
+		Tmpfs:     c.tmpfs(),
 	}
 }