Forráskód Böngészése

Move docker init into drivers functions

Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes <guillaume.charmes@docker.com> (github: creack)

Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes <guillaume.charmes@docker.com> (github: crosbymichael)
Guillaume J. Charmes 11 éve
szülő
commit
f7684ea7f6

+ 21 - 1
execdriver/chroot/driver.go

@@ -2,9 +2,29 @@ package chroot
 
 
 import (
 import (
 	"github.com/dotcloud/docker/execdriver"
 	"github.com/dotcloud/docker/execdriver"
+	"github.com/dotcloud/docker/mount"
+	"os"
 	"os/exec"
 	"os/exec"
 )
 )
 
 
+const DriverName = "chroot"
+
+func init() {
+	execdriver.RegisterDockerInitFct(DriverName, func(args *execdriver.DockerInitArgs) error {
+		if err := mount.ForceMount("proc", "proc", "proc", ""); err != nil {
+			return err
+		}
+		defer mount.ForceUnmount("proc")
+		cmd := exec.Command(args.Args[0], args.Args[1:]...)
+
+		cmd.Stderr = os.Stderr
+		cmd.Stdout = os.Stdout
+		cmd.Stdin = os.Stdin
+
+		return cmd.Run()
+	})
+}
+
 type driver struct {
 type driver struct {
 }
 }
 
 
@@ -13,7 +33,7 @@ func NewDriver() (*driver, error) {
 }
 }
 
 
 func (d *driver) Name() string {
 func (d *driver) Name() string {
-	return "chroot"
+	return DriverName
 }
 }
 
 
 func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {
 func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {

+ 41 - 3
execdriver/driver.go

@@ -7,11 +7,49 @@ import (
 )
 )
 
 
 var (
 var (
-	ErrNotRunning         = errors.New("Process could not be started")
-	ErrWaitTimeoutReached = errors.New("Wait timeout reached")
+	ErrNotRunning              = errors.New("Process could not be started")
+	ErrWaitTimeoutReached      = errors.New("Wait timeout reached")
+	ErrDriverAlreadyRegistered = errors.New("A driver already registered this docker init function")
+	ErrDriverNotFound          = errors.New("The requested docker init has not been found")
 )
 )
 
 
-type StartCallback func(*Process)
+var dockerInitFcts map[string]DockerInitFct
+
+type (
+	StartCallback func(*Process)
+	DockerInitFct func(i *DockerInitArgs) error
+)
+
+func RegisterDockerInitFct(name string, fct DockerInitFct) error {
+	if dockerInitFcts == nil {
+		dockerInitFcts = make(map[string]DockerInitFct)
+	}
+	if _, ok := dockerInitFcts[name]; ok {
+		return ErrDriverAlreadyRegistered
+	}
+	dockerInitFcts[name] = fct
+	return nil
+}
+
+func GetDockerInitFct(name string) (DockerInitFct, error) {
+	fct, ok := dockerInitFcts[name]
+	if !ok {
+		return nil, ErrDriverNotFound
+	}
+	return fct, nil
+}
+
+type DockerInitArgs struct {
+	User       string
+	Gateway    string
+	Ip         string
+	WorkDir    string
+	Privileged bool
+	Env        []string
+	Args       []string
+	Mtu        int
+	Driver     string
+}
 
 
 type Driver interface {
 type Driver interface {
 	Run(c *Process, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code
 	Run(c *Process, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code

+ 37 - 1
execdriver/lxc/driver.go

@@ -5,14 +5,50 @@ import (
 	"github.com/dotcloud/docker/execdriver"
 	"github.com/dotcloud/docker/execdriver"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io/ioutil"
 	"io/ioutil"
+	"log"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
 	"path"
 	"path"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
+	"syscall"
 	"time"
 	"time"
 )
 )
 
 
+const DriverName = "lxc"
+
+func init() {
+	execdriver.RegisterDockerInitFct(DriverName, func(args *execdriver.DockerInitArgs) error {
+		if err := setupHostname(args); err != nil {
+			return err
+		}
+
+		if err := setupNetworking(args); err != nil {
+			return err
+		}
+
+		if err := setupCapabilities(args); err != nil {
+			return err
+		}
+		if err := setupWorkingDirectory(args); err != nil {
+			return err
+		}
+
+		if err := changeUser(args); err != nil {
+			return err
+		}
+		path, err := exec.LookPath(args.Args[0])
+		if err != nil {
+			log.Printf("Unable to locate %v", args.Args[0])
+			os.Exit(127)
+		}
+		if err := syscall.Exec(path, args.Args, os.Environ()); err != nil {
+			panic(err)
+		}
+		panic("Unreachable")
+	})
+}
+
 type driver struct {
 type driver struct {
 	root       string // root path for the driver to use
 	root       string // root path for the driver to use
 	apparmor   bool
 	apparmor   bool
@@ -32,7 +68,7 @@ func NewDriver(root string, apparmor bool) (*driver, error) {
 }
 }
 
 
 func (d *driver) Name() string {
 func (d *driver) Name() string {
-	return "lxc"
+	return DriverName
 }
 }
 
 
 func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {
 func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {

+ 153 - 0
execdriver/lxc/init.go

@@ -0,0 +1,153 @@
+package lxc
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/execdriver"
+	"github.com/dotcloud/docker/pkg/netlink"
+	"github.com/dotcloud/docker/utils"
+	"github.com/syndtr/gocapability/capability"
+	"net"
+	"os"
+	"strconv"
+	"strings"
+	"syscall"
+)
+
+func setupHostname(args *execdriver.DockerInitArgs) error {
+	hostname := getEnv(args, "HOSTNAME")
+	if hostname == "" {
+		return nil
+	}
+	return setHostname(hostname)
+}
+
+// Setup networking
+func setupNetworking(args *execdriver.DockerInitArgs) error {
+	if args.Ip != "" {
+		// eth0
+		iface, err := net.InterfaceByName("eth0")
+		if err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+		ip, ipNet, err := net.ParseCIDR(args.Ip)
+		if err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+		if err := netlink.NetworkLinkAddIp(iface, ip, ipNet); err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+		if err := netlink.NetworkSetMTU(iface, args.Mtu); err != nil {
+			return fmt.Errorf("Unable to set MTU: %v", err)
+		}
+		if err := netlink.NetworkLinkUp(iface); err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+
+		// loopback
+		iface, err = net.InterfaceByName("lo")
+		if err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+		if err := netlink.NetworkLinkUp(iface); err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+	}
+	if args.Gateway != "" {
+		gw := net.ParseIP(args.Gateway)
+		if gw == nil {
+			return fmt.Errorf("Unable to set up networking, %s is not a valid gateway IP", args.Gateway)
+		}
+
+		if err := netlink.AddDefaultGw(gw); err != nil {
+			return fmt.Errorf("Unable to set up networking: %v", err)
+		}
+	}
+
+	return nil
+}
+
+// Setup working directory
+func setupWorkingDirectory(args *execdriver.DockerInitArgs) error {
+	if args.WorkDir == "" {
+		return nil
+	}
+	if err := syscall.Chdir(args.WorkDir); err != nil {
+		return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
+	}
+	return nil
+}
+
+// Takes care of dropping privileges to the desired user
+func changeUser(args *execdriver.DockerInitArgs) error {
+	if args.User == "" {
+		return nil
+	}
+	userent, err := utils.UserLookup(args.User)
+	if err != nil {
+		return fmt.Errorf("Unable to find user %v: %v", args.User, err)
+	}
+
+	uid, err := strconv.Atoi(userent.Uid)
+	if err != nil {
+		return fmt.Errorf("Invalid uid: %v", userent.Uid)
+	}
+	gid, err := strconv.Atoi(userent.Gid)
+	if err != nil {
+		return fmt.Errorf("Invalid gid: %v", userent.Gid)
+	}
+
+	if err := syscall.Setgid(gid); err != nil {
+		return fmt.Errorf("setgid failed: %v", err)
+	}
+	if err := syscall.Setuid(uid); err != nil {
+		return fmt.Errorf("setuid failed: %v", err)
+	}
+
+	return nil
+}
+
+func setupCapabilities(args *execdriver.DockerInitArgs) error {
+
+	if args.Privileged {
+		return nil
+	}
+
+	drop := []capability.Cap{
+		capability.CAP_SETPCAP,
+		capability.CAP_SYS_MODULE,
+		capability.CAP_SYS_RAWIO,
+		capability.CAP_SYS_PACCT,
+		capability.CAP_SYS_ADMIN,
+		capability.CAP_SYS_NICE,
+		capability.CAP_SYS_RESOURCE,
+		capability.CAP_SYS_TIME,
+		capability.CAP_SYS_TTY_CONFIG,
+		capability.CAP_MKNOD,
+		capability.CAP_AUDIT_WRITE,
+		capability.CAP_AUDIT_CONTROL,
+		capability.CAP_MAC_OVERRIDE,
+		capability.CAP_MAC_ADMIN,
+	}
+
+	c, err := capability.NewPid(os.Getpid())
+	if err != nil {
+		return err
+	}
+
+	c.Unset(capability.CAPS|capability.BOUNDS, drop...)
+
+	if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
+		return err
+	}
+	return nil
+}
+
+func getEnv(args *execdriver.DockerInitArgs, key string) string {
+	for _, kv := range args.Env {
+		parts := strings.SplitN(kv, "=", 2)
+		if parts[0] == key && len(parts) == 2 {
+			return parts[1]
+		}
+	}
+	return ""
+}

+ 1 - 1
sysinit/sysinit_darwin.go → execdriver/lxc/lxc_init_darwin.go

@@ -1,4 +1,4 @@
-package sysinit
+package lxc
 
 
 func setHostname(hostname string) error {
 func setHostname(hostname string) error {
 	panic("Not supported on darwin")
 	panic("Not supported on darwin")

+ 1 - 1
sysinit/sysinit_linux.go → execdriver/lxc/lxc_init_linux.go

@@ -1,4 +1,4 @@
-package sysinit
+package lxc
 
 
 import (
 import (
 	"syscall"
 	"syscall"

+ 19 - 219
sysinit/sysinit.go

@@ -4,169 +4,17 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"flag"
 	"flag"
 	"fmt"
 	"fmt"
-	"github.com/dotcloud/docker/mount"
-	"github.com/dotcloud/docker/pkg/netlink"
-	"github.com/dotcloud/docker/utils"
-	"github.com/syndtr/gocapability/capability"
+	"github.com/dotcloud/docker/execdriver"
 	"io/ioutil"
 	"io/ioutil"
 	"log"
 	"log"
-	"net"
 	"os"
 	"os"
-	"os/exec"
-	"strconv"
 	"strings"
 	"strings"
-	"syscall"
 )
 )
 
 
-type DockerInitArgs struct {
-	user       string
-	gateway    string
-	ip         string
-	workDir    string
-	privileged bool
-	env        []string
-	args       []string
-	mtu        int
-	driver     string
-}
-
-func setupHostname(args *DockerInitArgs) error {
-	hostname := getEnv(args, "HOSTNAME")
-	if hostname == "" {
-		return nil
-	}
-	return setHostname(hostname)
-}
-
-// Setup networking
-func setupNetworking(args *DockerInitArgs) error {
-	if args.ip != "" {
-		// eth0
-		iface, err := net.InterfaceByName("eth0")
-		if err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		ip, ipNet, err := net.ParseCIDR(args.ip)
-		if err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		if err := netlink.NetworkLinkAddIp(iface, ip, ipNet); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		if err := netlink.NetworkSetMTU(iface, args.mtu); err != nil {
-			return fmt.Errorf("Unable to set MTU: %v", err)
-		}
-		if err := netlink.NetworkLinkUp(iface); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-
-		// loopback
-		iface, err = net.InterfaceByName("lo")
-		if err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		if err := netlink.NetworkLinkUp(iface); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-	}
-	if args.gateway != "" {
-		gw := net.ParseIP(args.gateway)
-		if gw == nil {
-			return fmt.Errorf("Unable to set up networking, %s is not a valid gateway IP", args.gateway)
-		}
-
-		if err := netlink.AddDefaultGw(gw); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-	}
-
-	return nil
-}
-
-// Setup working directory
-func setupWorkingDirectory(args *DockerInitArgs) error {
-	if args.workDir == "" {
-		return nil
-	}
-	if err := syscall.Chdir(args.workDir); err != nil {
-		return fmt.Errorf("Unable to change dir to %v: %v", args.workDir, err)
-	}
-	return nil
-}
-
-func setupMounts(args *DockerInitArgs) error {
-	return mount.ForceMount("proc", "proc", "proc", "")
-}
-
-// Takes care of dropping privileges to the desired user
-func changeUser(args *DockerInitArgs) error {
-	if args.user == "" {
-		return nil
-	}
-	userent, err := utils.UserLookup(args.user)
-	if err != nil {
-		return fmt.Errorf("Unable to find user %v: %v", args.user, err)
-	}
-
-	uid, err := strconv.Atoi(userent.Uid)
-	if err != nil {
-		return fmt.Errorf("Invalid uid: %v", userent.Uid)
-	}
-	gid, err := strconv.Atoi(userent.Gid)
-	if err != nil {
-		return fmt.Errorf("Invalid gid: %v", userent.Gid)
-	}
-
-	if err := syscall.Setgid(gid); err != nil {
-		return fmt.Errorf("setgid failed: %v", err)
-	}
-	if err := syscall.Setuid(uid); err != nil {
-		return fmt.Errorf("setuid failed: %v", err)
-	}
-
-	return nil
-}
-
-func setupCapabilities(args *DockerInitArgs) error {
-
-	if args.privileged {
-		return nil
-	}
-
-	drop := []capability.Cap{
-		capability.CAP_SETPCAP,
-		capability.CAP_SYS_MODULE,
-		capability.CAP_SYS_RAWIO,
-		capability.CAP_SYS_PACCT,
-		capability.CAP_SYS_ADMIN,
-		capability.CAP_SYS_NICE,
-		capability.CAP_SYS_RESOURCE,
-		capability.CAP_SYS_TIME,
-		capability.CAP_SYS_TTY_CONFIG,
-		capability.CAP_MKNOD,
-		capability.CAP_AUDIT_WRITE,
-		capability.CAP_AUDIT_CONTROL,
-		capability.CAP_MAC_OVERRIDE,
-		capability.CAP_MAC_ADMIN,
-	}
-
-	c, err := capability.NewPid(os.Getpid())
-	if err != nil {
-		return err
-	}
-
-	c.Unset(capability.CAPS|capability.BOUNDS, drop...)
-
-	if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
-		return err
-	}
-	return nil
-}
-
 // Clear environment pollution introduced by lxc-start
 // Clear environment pollution introduced by lxc-start
-func setupEnv(args *DockerInitArgs) {
+func setupEnv(args *execdriver.DockerInitArgs) {
 	os.Clearenv()
 	os.Clearenv()
-	for _, kv := range args.env {
+	for _, kv := range args.Env {
 		parts := strings.SplitN(kv, "=", 2)
 		parts := strings.SplitN(kv, "=", 2)
 		if len(parts) == 1 {
 		if len(parts) == 1 {
 			parts = append(parts, "")
 			parts = append(parts, "")
@@ -175,66 +23,18 @@ func setupEnv(args *DockerInitArgs) {
 	}
 	}
 }
 }
 
 
-func getEnv(args *DockerInitArgs, key string) string {
-	for _, kv := range args.env {
-		parts := strings.SplitN(kv, "=", 2)
-		if parts[0] == key && len(parts) == 2 {
-			return parts[1]
-		}
-	}
-	return ""
-}
-
-func executeProgram(args *DockerInitArgs) error {
+func executeProgram(args *execdriver.DockerInitArgs) error {
 	setupEnv(args)
 	setupEnv(args)
-
-	if args.driver == "lxc" {
-		if err := setupHostname(args); err != nil {
-			return err
-		}
-
-		if err := setupNetworking(args); err != nil {
-			return err
-		}
-
-		if err := setupCapabilities(args); err != nil {
-			return err
-		}
-		if err := setupWorkingDirectory(args); err != nil {
-			return err
-		}
-
-		if err := changeUser(args); err != nil {
-			return err
-		}
-	} else if args.driver == "chroot" {
-		if err := setupMounts(args); err != nil {
-			return err
-		}
-		defer mount.ForceUnmount("proc")
-	}
-
-	path, err := exec.LookPath(args.args[0])
+	dockerInitFct, err := execdriver.GetDockerInitFct(args.Driver)
 	if err != nil {
 	if err != nil {
-		log.Printf("Unable to locate %v", args.args[0])
-		os.Exit(127)
+		panic(err)
 	}
 	}
+	return dockerInitFct(args)
 
 
-	if args.driver == "lxc" {
-		if err := syscall.Exec(path, args.args, os.Environ()); err != nil {
-			panic(err)
-		}
+	if args.Driver == "lxc" {
 		// Will never reach
 		// Will never reach
-	} else if args.driver == "chroot" {
-		cmd := exec.Command(path, args.args[1:]...)
-
-		cmd.Stderr = os.Stderr
-		cmd.Stdout = os.Stdout
-		cmd.Stdin = os.Stdin
-
-		return cmd.Run()
+	} else if args.Driver == "chroot" {
 	}
 	}
-	panic("Should not be here")
 
 
 	return nil
 	return nil
 }
 }
@@ -271,16 +71,16 @@ func SysInit() {
 	// Propagate the plugin-specific container env variable
 	// Propagate the plugin-specific container env variable
 	env = append(env, "container="+os.Getenv("container"))
 	env = append(env, "container="+os.Getenv("container"))
 
 
-	args := &DockerInitArgs{
-		user:       *user,
-		gateway:    *gateway,
-		ip:         *ip,
-		workDir:    *workDir,
-		privileged: *privileged,
-		env:        env,
-		args:       flag.Args(),
-		mtu:        *mtu,
-		driver:     *driver,
+	args := &execdriver.DockerInitArgs{
+		User:       *user,
+		Gateway:    *gateway,
+		Ip:         *ip,
+		WorkDir:    *workDir,
+		Privileged: *privileged,
+		Env:        env,
+		Args:       flag.Args(),
+		Mtu:        *mtu,
+		Driver:     *driver,
 	}
 	}
 
 
 	if err := executeProgram(args); err != nil {
 	if err := executeProgram(args); err != nil {