ソースを参照

Refactor few spec generation ops

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Michael Crosby 6 年 前
コミット
cb902f4430
1 ファイル変更181 行追加158 行削除
  1. 181 158
      daemon/oci_linux.go

+ 181 - 158
daemon/oci_linux.go

@@ -1,6 +1,7 @@
 package daemon // import "github.com/docker/docker/daemon"
 
 import (
+	"context"
 	"fmt"
 	"io"
 	"os"
@@ -10,6 +11,8 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/containerd/containerd/containers"
+	coci "github.com/containerd/containerd/oci"
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/container"
 	daemonconfig "github.com/docker/docker/daemon/config"
@@ -34,104 +37,6 @@ const (
 	inContainerInitPath = "/sbin/" + daemonconfig.DefaultInitBinary
 )
 
-func setResources(s *specs.Spec, r containertypes.Resources) error {
-	weightDevices, err := getBlkioWeightDevices(r)
-	if err != nil {
-		return err
-	}
-	readBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadBps)
-	if err != nil {
-		return err
-	}
-	writeBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteBps)
-	if err != nil {
-		return err
-	}
-	readIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadIOps)
-	if err != nil {
-		return err
-	}
-	writeIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteIOps)
-	if err != nil {
-		return err
-	}
-
-	memoryRes := getMemoryResources(r)
-	cpuRes, err := getCPUResources(r)
-	if err != nil {
-		return err
-	}
-	blkioWeight := r.BlkioWeight
-
-	specResources := &specs.LinuxResources{
-		Memory: memoryRes,
-		CPU:    cpuRes,
-		BlockIO: &specs.LinuxBlockIO{
-			Weight:                  &blkioWeight,
-			WeightDevice:            weightDevices,
-			ThrottleReadBpsDevice:   readBpsDevice,
-			ThrottleWriteBpsDevice:  writeBpsDevice,
-			ThrottleReadIOPSDevice:  readIOpsDevice,
-			ThrottleWriteIOPSDevice: writeIOpsDevice,
-		},
-		Pids: getPidsLimit(r),
-	}
-
-	if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
-		specResources.Devices = s.Linux.Resources.Devices
-	}
-
-	s.Linux.Resources = specResources
-	return nil
-}
-
-func (daemon *Daemon) setDevices(s *specs.Spec, c *container.Container) error {
-	// Build lists of devices allowed and created within the container.
-	var devs []specs.LinuxDevice
-	devPermissions := s.Linux.Resources.Devices
-	if c.HostConfig.Privileged && !rsystem.RunningInUserNS() {
-		hostDevices, err := devices.HostDevices()
-		if err != nil {
-			return err
-		}
-		for _, d := range hostDevices {
-			devs = append(devs, oci.Device(d))
-		}
-		devPermissions = []specs.LinuxDeviceCgroup{
-			{
-				Allow:  true,
-				Access: "rwm",
-			},
-		}
-	} else {
-		for _, deviceMapping := range c.HostConfig.Devices {
-			d, dPermissions, err := oci.DevicesFromPath(deviceMapping.PathOnHost, deviceMapping.PathInContainer, deviceMapping.CgroupPermissions)
-			if err != nil {
-				return err
-			}
-			devs = append(devs, d...)
-			devPermissions = append(devPermissions, dPermissions...)
-		}
-
-		var err error
-		devPermissions, err = oci.AppendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules)
-		if err != nil {
-			return err
-		}
-	}
-
-	s.Linux.Devices = append(s.Linux.Devices, devs...)
-	s.Linux.Resources.Devices = devPermissions
-
-	for _, req := range c.HostConfig.DeviceRequests {
-		if err := daemon.handleDevice(req, s); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
 func (daemon *Daemon) setRlimits(s *specs.Spec, c *container.Container) error {
 	var rlimits []specs.POSIXRlimit
 
@@ -151,17 +56,6 @@ func (daemon *Daemon) setRlimits(s *specs.Spec, c *container.Container) error {
 	return nil
 }
 
-func setUser(s *specs.Spec, c *container.Container) error {
-	uid, gid, additionalGids, err := getUser(c, c.Config.User)
-	if err != nil {
-		return err
-	}
-	s.Process.User.UID = uid
-	s.Process.User.GID = gid
-	s.Process.User.AdditionalGids = additionalGids
-	return nil
-}
-
 func readUserFile(c *container.Container, p string) (io.ReadCloser, error) {
 	fp, err := c.GetResourcePath(p)
 	if err != nil {
@@ -693,74 +587,201 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
 	return nil
 }
 
-func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
-	s := oci.DefaultSpec()
-	if err := daemon.populateCommonSpec(&s, c); err != nil {
-		return nil, err
-	}
+func withCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
+		var cgroupsPath string
+		scopePrefix := "docker"
+		parent := "/docker"
+		useSystemd := UsingSystemd(daemon.configStore)
+		if useSystemd {
+			parent = "system.slice"
+		}
 
-	var cgroupsPath string
-	scopePrefix := "docker"
-	parent := "/docker"
-	useSystemd := UsingSystemd(daemon.configStore)
-	if useSystemd {
-		parent = "system.slice"
-	}
+		if c.HostConfig.CgroupParent != "" {
+			parent = c.HostConfig.CgroupParent
+		} else if daemon.configStore.CgroupParent != "" {
+			parent = daemon.configStore.CgroupParent
+		}
 
-	if c.HostConfig.CgroupParent != "" {
-		parent = c.HostConfig.CgroupParent
-	} else if daemon.configStore.CgroupParent != "" {
-		parent = daemon.configStore.CgroupParent
-	}
+		if useSystemd {
+			cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID
+			logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
+		} else {
+			cgroupsPath = filepath.Join(parent, c.ID)
+		}
+		s.Linux.CgroupsPath = cgroupsPath
+		p := cgroupsPath
+		if useSystemd {
+			initPath, err := cgroups.GetInitCgroup("cpu")
+			if err != nil {
+				return err
+			}
+			_, err = cgroups.GetOwnCgroup("cpu")
+			if err != nil {
+				return err
+			}
+			p = filepath.Join(initPath, s.Linux.CgroupsPath)
+		}
 
-	if useSystemd {
-		cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID
-		logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
-	} else {
-		cgroupsPath = filepath.Join(parent, c.ID)
-	}
-	s.Linux.CgroupsPath = cgroupsPath
+		// Clean path to guard against things like ../../../BAD
+		parentPath := filepath.Dir(p)
+		if !filepath.IsAbs(parentPath) {
+			parentPath = filepath.Clean("/" + parentPath)
+		}
 
-	if err := setResources(&s, c.HostConfig.Resources); err != nil {
-		return nil, fmt.Errorf("linux runtime spec resources: %v", err)
+		if err := daemon.initCgroupsPath(parentPath); err != nil {
+			return fmt.Errorf("linux init cgroups path: %v", err)
+		}
+		return nil
 	}
-	// We merge the sysctls injected above with the HostConfig (latter takes
-	// precedence for backwards-compatibility reasons).
-	for k, v := range c.HostConfig.Sysctls {
-		s.Linux.Sysctl[k] = v
+}
+
+func withContainerDevices(daemon *Daemon, c *container.Container) coci.SpecOpts {
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
+		// Build lists of devices allowed and created within the container.
+		var devs []specs.LinuxDevice
+		devPermissions := s.Linux.Resources.Devices
+		if c.HostConfig.Privileged && !rsystem.RunningInUserNS() {
+			hostDevices, err := devices.HostDevices()
+			if err != nil {
+				return err
+			}
+			for _, d := range hostDevices {
+				devs = append(devs, oci.Device(d))
+			}
+			devPermissions = []specs.LinuxDeviceCgroup{
+				{
+					Allow:  true,
+					Access: "rwm",
+				},
+			}
+		} else {
+			for _, deviceMapping := range c.HostConfig.Devices {
+				d, dPermissions, err := oci.DevicesFromPath(deviceMapping.PathOnHost, deviceMapping.PathInContainer, deviceMapping.CgroupPermissions)
+				if err != nil {
+					return err
+				}
+				devs = append(devs, d...)
+				devPermissions = append(devPermissions, dPermissions...)
+			}
+
+			var err error
+			devPermissions, err = oci.AppendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules)
+			if err != nil {
+				return err
+			}
+		}
+
+		s.Linux.Devices = append(s.Linux.Devices, devs...)
+		s.Linux.Resources.Devices = devPermissions
+
+		for _, req := range c.HostConfig.DeviceRequests {
+			if err := daemon.handleDevice(req, s); err != nil {
+				return err
+			}
+		}
+		return nil
 	}
+}
 
-	p := s.Linux.CgroupsPath
-	if useSystemd {
-		initPath, err := cgroups.GetInitCgroup("cpu")
+func withResources(c *container.Container) coci.SpecOpts {
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
+		r := c.HostConfig.Resources
+		weightDevices, err := getBlkioWeightDevices(r)
 		if err != nil {
-			return nil, err
+			return err
 		}
-		_, err = cgroups.GetOwnCgroup("cpu")
+		readBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadBps)
 		if err != nil {
-			return nil, err
+			return err
+		}
+		writeBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteBps)
+		if err != nil {
+			return err
+		}
+		readIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadIOps)
+		if err != nil {
+			return err
+		}
+		writeIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteIOps)
+		if err != nil {
+			return err
+		}
+
+		memoryRes := getMemoryResources(r)
+		cpuRes, err := getCPUResources(r)
+		if err != nil {
+			return err
+		}
+		blkioWeight := r.BlkioWeight
+
+		specResources := &specs.LinuxResources{
+			Memory: memoryRes,
+			CPU:    cpuRes,
+			BlockIO: &specs.LinuxBlockIO{
+				Weight:                  &blkioWeight,
+				WeightDevice:            weightDevices,
+				ThrottleReadBpsDevice:   readBpsDevice,
+				ThrottleWriteBpsDevice:  writeBpsDevice,
+				ThrottleReadIOPSDevice:  readIOpsDevice,
+				ThrottleWriteIOPSDevice: writeIOpsDevice,
+			},
+			Pids: getPidsLimit(r),
 		}
-		p = filepath.Join(initPath, s.Linux.CgroupsPath)
+
+		if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
+			specResources.Devices = s.Linux.Resources.Devices
+		}
+
+		s.Linux.Resources = specResources
+		return nil
 	}
+}
 
-	// Clean path to guard against things like ../../../BAD
-	parentPath := filepath.Dir(p)
-	if !filepath.IsAbs(parentPath) {
-		parentPath = filepath.Clean("/" + parentPath)
+func withSysctls(c *container.Container) coci.SpecOpts {
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
+		// We merge the sysctls injected above with the HostConfig (latter takes
+		// precedence for backwards-compatibility reasons).
+		for k, v := range c.HostConfig.Sysctls {
+			s.Linux.Sysctl[k] = v
+		}
+		return nil
 	}
+}
 
-	if err := daemon.initCgroupsPath(parentPath); err != nil {
-		return nil, fmt.Errorf("linux init cgroups path: %v", err)
+func withUser(c *container.Container) coci.SpecOpts {
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
+		uid, gid, additionalGids, err := getUser(c, c.Config.User)
+		if err != nil {
+			return err
+		}
+		s.Process.User.UID = uid
+		s.Process.User.GID = gid
+		s.Process.User.AdditionalGids = additionalGids
+		return nil
 	}
-	if err := daemon.setDevices(&s, c); err != nil {
-		return nil, fmt.Errorf("linux runtime spec devices: %v", err)
+}
+
+func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
+	var (
+		opts []coci.SpecOpts
+		s    = oci.DefaultSpec()
+	)
+	if err := daemon.populateCommonSpec(&s, c); err != nil {
+		return nil, err
 	}
+
+	opts = append(opts,
+		withCgroups(daemon, c),
+		withResources(c),
+		withSysctls(c),
+		withContainerDevices(daemon, c),
+		withUser(c),
+	)
+
 	if err := daemon.setRlimits(&s, c); err != nil {
 		return nil, fmt.Errorf("linux runtime spec rlimits: %v", err)
 	}
-	if err := setUser(&s, c); err != nil {
-		return nil, fmt.Errorf("linux spec user: %v", err)
-	}
 	if err := setNamespaces(daemon, &s, c); err != nil {
 		return nil, fmt.Errorf("linux spec namespaces: %v", err)
 	}
@@ -874,7 +895,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
 			return nil, err
 		}
 	}
-	return &s, nil
+	return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
+		ID: c.ID,
+	}, &s, opts...)
 }
 
 func clearReadOnly(m *specs.Mount) {