Преглед на файлове

Factor out the native driver config options
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby преди 11 години
родител
ревизия
7c726669cb

+ 4 - 0
runtime/container.go

@@ -364,6 +364,10 @@ func populateCommand(c *Container) {
 		driverConfig = c.hostConfig.PluginOptions
 	)
 
+	if driverConfig == nil {
+		driverConfig = make(map[string][]string)
+	}
+
 	en = &execdriver.Network{
 		Mtu:       c.runtime.config.Mtu,
 		Interface: nil,

+ 27 - 0
runtime/execdriver/native/configuration/caps.go

@@ -0,0 +1,27 @@
+package configuration
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/pkg/libcontainer"
+	"strings"
+)
+
+// i.e: cap +MKNOD cap -NET_ADMIN
+func parseCapOpt(container *libcontainer.Container, opts []string) error {
+	var (
+		value = strings.TrimSpace(opts[0])
+		c     = container.CapabilitiesMask.Get(value[1:])
+	)
+	if c == nil {
+		return fmt.Errorf("%s is not a valid capability", value[1:])
+	}
+	switch value[0] {
+	case '-':
+		c.Enabled = false
+	case '+':
+		c.Enabled = true
+	default:
+		return fmt.Errorf("%c is not a valid modifier for capabilities", value[0])
+	}
+	return nil
+}

+ 35 - 0
runtime/execdriver/native/configuration/net.go

@@ -0,0 +1,35 @@
+package configuration
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/pkg/libcontainer"
+	"os/exec"
+	"path/filepath"
+	"strings"
+)
+
+// i.e: net join <name>
+func parseNetOpt(container *libcontainer.Container, running map[string]*exec.Cmd, opts []string) error {
+	opt := strings.TrimSpace(opts[1])
+	switch opt {
+	case "join":
+		var (
+			id  = strings.TrimSpace(opts[2])
+			cmd = running[id]
+		)
+
+		if cmd == nil || cmd.Process == nil {
+			return fmt.Errorf("%s is not a valid running container to join", id)
+		}
+		nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
+		container.Networks = append(container.Networks, &libcontainer.Network{
+			Type: "netns",
+			Context: libcontainer.Context{
+				"nspath": nspath,
+			},
+		})
+	default:
+		return fmt.Errorf("%s is not a valid network option", opt)
+	}
+	return nil
+}

+ 26 - 0
runtime/execdriver/native/configuration/ns.go

@@ -0,0 +1,26 @@
+package configuration
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/pkg/libcontainer"
+	"strings"
+)
+
+func parseNsOpt(container *libcontainer.Container, opts []string) error {
+	var (
+		value = strings.TrimSpace(opts[0])
+		ns    = container.Namespaces.Get(value[1:])
+	)
+	if ns == nil {
+		return fmt.Errorf("%s is not a valid namespace", value[1:])
+	}
+	switch value[0] {
+	case '-':
+		ns.Enabled = false
+	case '+':
+		ns.Enabled = true
+	default:
+		return fmt.Errorf("%c is not a valid modifier for namespaces", value[0])
+	}
+	return nil
+}

+ 37 - 0
runtime/execdriver/native/configuration/parse.go

@@ -0,0 +1,37 @@
+package configuration
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/pkg/libcontainer"
+	"os/exec"
+	"strings"
+)
+
+// configureCustomOptions takes string commands from the user and allows modification of the
+// container's default configuration.
+//
+// format: <key> <...value>
+// i.e: cgroup devices.allow *:*
+func ParseConfiguration(container *libcontainer.Container, running map[string]*exec.Cmd, opts []string) error {
+	for _, opt := range opts {
+		var (
+			err   error
+			parts = strings.Split(strings.TrimSpace(opt), " ")
+		)
+
+		switch parts[0] {
+		case "cap":
+			err = parseCapOpt(container, parts[1:])
+		case "ns":
+			err = parseNsOpt(container, parts[1:])
+		case "net":
+			err = parseNetOpt(container, running, parts[1:])
+		default:
+			return fmt.Errorf("%s is not a valid configuration option for the native driver", parts[0])
+		}
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}

+ 70 - 0
runtime/execdriver/native/create.go

@@ -0,0 +1,70 @@
+package native
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/pkg/libcontainer"
+	"github.com/dotcloud/docker/runtime/execdriver"
+	"github.com/dotcloud/docker/runtime/execdriver/native/configuration"
+	"os"
+)
+
+// createContainer populates and configures the container type with the
+// data provided by the execdriver.Command
+func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Container, error) {
+	container := getDefaultTemplate()
+
+	container.Hostname = getEnv("HOSTNAME", c.Env)
+	container.Tty = c.Tty
+	container.User = c.User
+	container.WorkingDir = c.WorkingDir
+	container.Env = c.Env
+
+	loopbackNetwork := libcontainer.Network{
+		Mtu:     c.Network.Mtu,
+		Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
+		Gateway: "localhost",
+		Type:    "loopback",
+		Context: libcontainer.Context{},
+	}
+
+	container.Networks = []*libcontainer.Network{
+		&loopbackNetwork,
+	}
+
+	if c.Network.Interface != nil {
+		vethNetwork := libcontainer.Network{
+			Mtu:     c.Network.Mtu,
+			Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
+			Gateway: c.Network.Interface.Gateway,
+			Type:    "veth",
+			Context: libcontainer.Context{
+				"prefix": "veth",
+				"bridge": c.Network.Interface.Bridge,
+			},
+		}
+		container.Networks = append(container.Networks, &vethNetwork)
+	}
+
+	container.Cgroups.Name = c.ID
+	if c.Privileged {
+		container.CapabilitiesMask = nil
+		container.Cgroups.DeviceAccess = true
+		container.Context["apparmor_profile"] = "unconfined"
+	}
+	if c.Resources != nil {
+		container.Cgroups.CpuShares = c.Resources.CpuShares
+		container.Cgroups.Memory = c.Resources.Memory
+		container.Cgroups.MemorySwap = c.Resources.MemorySwap
+	}
+	// check to see if we are running in ramdisk to disable pivot root
+	container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
+
+	for _, m := range c.Mounts {
+		container.Mounts = append(container.Mounts, libcontainer.Mount{m.Source, m.Destination, m.Writable, m.Private})
+	}
+
+	if err := configuration.ParseConfiguration(container, d.activeContainers, c.Config["native"]); err != nil {
+		return nil, err
+	}
+	return container, nil
+}

+ 0 - 126
runtime/execdriver/native/default_template.go

@@ -1,136 +1,10 @@
 package native
 
 import (
-	"fmt"
 	"github.com/dotcloud/docker/pkg/cgroups"
 	"github.com/dotcloud/docker/pkg/libcontainer"
-	"github.com/dotcloud/docker/runtime/execdriver"
-	"os"
-	"path/filepath"
-	"strings"
 )
 
-// createContainer populates and configures the container type with the
-// data provided by the execdriver.Command
-func (d *driver) createContainer(c *execdriver.Command) *libcontainer.Container {
-	container := getDefaultTemplate()
-
-	container.Hostname = getEnv("HOSTNAME", c.Env)
-	container.Tty = c.Tty
-	container.User = c.User
-	container.WorkingDir = c.WorkingDir
-	container.Env = c.Env
-
-	loopbackNetwork := libcontainer.Network{
-		Mtu:     c.Network.Mtu,
-		Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
-		Gateway: "localhost",
-		Type:    "loopback",
-		Context: libcontainer.Context{},
-	}
-
-	container.Networks = []*libcontainer.Network{
-		&loopbackNetwork,
-	}
-
-	if c.Network.Interface != nil {
-		vethNetwork := libcontainer.Network{
-			Mtu:     c.Network.Mtu,
-			Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
-			Gateway: c.Network.Interface.Gateway,
-			Type:    "veth",
-			Context: libcontainer.Context{
-				"prefix": "veth",
-				"bridge": c.Network.Interface.Bridge,
-			},
-		}
-		container.Networks = append(container.Networks, &vethNetwork)
-	}
-
-	container.Cgroups.Name = c.ID
-	if c.Privileged {
-		container.CapabilitiesMask = nil
-		container.Cgroups.DeviceAccess = true
-		container.Context["apparmor_profile"] = "unconfined"
-	}
-	if c.Resources != nil {
-		container.Cgroups.CpuShares = c.Resources.CpuShares
-		container.Cgroups.Memory = c.Resources.Memory
-		container.Cgroups.MemorySwap = c.Resources.MemorySwap
-	}
-	// check to see if we are running in ramdisk to disable pivot root
-	container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
-
-	for _, m := range c.Mounts {
-		container.Mounts = append(container.Mounts, libcontainer.Mount{m.Source, m.Destination, m.Writable, m.Private})
-	}
-
-	d.configureCustomOptions(container, c.Config["native"])
-
-	return container
-}
-
-// configureCustomOptions takes string commands from the user and allows modification of the
-// container's default configuration.
-//
-// format: <key> <value>
-// i.e: cap +MKNOD cap -NET_ADMIN
-// i.e: cgroup devices.allow *:*
-// i.e: net join <name>
-func (d *driver) configureCustomOptions(container *libcontainer.Container, opts []string) {
-	for _, opt := range opts {
-		var (
-			parts = strings.Split(strings.TrimSpace(opt), " ")
-			value = strings.TrimSpace(parts[1])
-		)
-		switch parts[0] {
-		case "cap":
-			c := container.CapabilitiesMask.Get(value[1:])
-			if c == nil {
-				continue
-			}
-			switch value[0] {
-			case '-':
-				c.Enabled = false
-			case '+':
-				c.Enabled = true
-			default:
-				// do error here
-			}
-		case "ns":
-			ns := container.Namespaces.Get(value[1:])
-			switch value[0] {
-			case '-':
-				ns.Enabled = false
-			case '+':
-				ns.Enabled = true
-			default:
-				// error
-			}
-		case "net":
-			switch strings.TrimSpace(parts[1]) {
-			case "join":
-				var (
-					id     = strings.TrimSpace(parts[2])
-					cmd    = d.activeContainers[id]
-					nspath = filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
-				)
-
-				container.Networks = append(container.Networks, &libcontainer.Network{
-					Type: "netns",
-					Context: libcontainer.Context{
-						"nspath": nspath,
-					},
-				})
-			default:
-				// error
-			}
-		default:
-			// error not defined
-		}
-	}
-}
-
 // getDefaultTemplate returns the docker default for
 // the libcontainer configuration file
 func getDefaultTemplate() *libcontainer.Container {

+ 8 - 4
runtime/execdriver/native/driver.go

@@ -59,7 +59,7 @@ func init() {
 type driver struct {
 	root             string
 	initPath         string
-	activeContainers map[string]*execdriver.Command
+	activeContainers map[string]*exec.Cmd
 }
 
 func NewDriver(root, initPath string) (*driver, error) {
@@ -72,16 +72,20 @@ func NewDriver(root, initPath string) (*driver, error) {
 	return &driver{
 		root:             root,
 		initPath:         initPath,
-		activeContainers: make(map[string]*execdriver.Command),
+		activeContainers: make(map[string]*exec.Cmd),
 	}, nil
 }
 
 func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
-	d.activeContainers[c.ID] = c
+	// take the Command and populate the libcontainer.Container from it
+	container, err := d.createContainer(c)
+	if err != nil {
+		return -1, err
+	}
+	d.activeContainers[c.ID] = &c.Cmd
 
 	var (
 		term        nsinit.Terminal
-		container   = d.createContainer(c)
 		factory     = &dockerCommandFactory{c: c, driver: d}
 		stateWriter = &dockerStateWriter{
 			callback: startCallback,