Ver Fonte

Make native driver use Exec func with different CreateCommand
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby há 11 anos atrás
pai
commit
da0d6dbd7b

+ 27 - 89
daemon/execdriver/native/driver.go

@@ -90,9 +90,6 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 	d.activeContainers[c.ID] = &c.Cmd
 	d.activeContainers[c.ID] = &c.Cmd
 
 
 	var (
 	var (
-		master  *os.File
-		console string
-
 		dataPath = filepath.Join(d.root, c.ID)
 		dataPath = filepath.Join(d.root, c.ID)
 		args     = append([]string{c.Entrypoint}, c.Arguments...)
 		args     = append([]string{c.Entrypoint}, c.Arguments...)
 	)
 	)
@@ -105,72 +102,36 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 		return -1, err
 		return -1, err
 	}
 	}
 
 
-	// create a pipe so that we can syncronize with the namespaced process and
-	// pass the veth name to the child
-	syncPipe, err := nsinit.NewSyncPipe()
-	if err != nil {
-		return -1, err
-	}
 	term := getTerminal(c, pipes)
 	term := getTerminal(c, pipes)
 
 
-	if container.Tty {
-		master, console, err = system.CreateMasterAndConsole()
-		if err != nil {
-			return -1, err
-		}
-		term.SetMaster(master)
-	}
-
-	setupCommand(d, c, container, console, syncPipe.Child(), args)
-	if err := term.Attach(&c.Cmd); err != nil {
-		return -1, err
-	}
-	defer term.Close()
-
-	if err := c.Start(); err != nil {
-		return -1, err
-	}
-
-	started, err := system.GetProcessStartTime(c.Process.Pid)
-	if err != nil {
-		return -1, err
-	}
-	if err := nsinit.WritePid(dataPath, c.Process.Pid, started); err != nil {
-		c.Process.Kill()
-		return -1, err
-	}
-	defer nsinit.DeletePid(dataPath)
-
-	// Do this before syncing with child so that no children
-	// can escape the cgroup
-	cleaner, err := nsinit.SetupCgroups(container, c.Process.Pid)
-	if err != nil {
-		c.Process.Kill()
-		return -1, err
-	}
-	if cleaner != nil {
-		defer cleaner.Cleanup()
-	}
-
-	if err := nsinit.InitializeNetworking(container, c.Process.Pid, syncPipe); err != nil {
-		c.Process.Kill()
-		return -1, err
-	}
-
-	// Sync with child
-	syncPipe.Close()
-
-	if startCallback != nil {
-		startCallback(c)
-	}
-
-	if err := c.Wait(); err != nil {
-		if _, ok := err.(*exec.ExitError); !ok {
-			return -1, err
+	return nsinit.Exec(container, term, c.Rootfs, dataPath, args, func(container *libcontainer.Container, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
+		// we need to join the rootfs because nsinit will setup the rootfs and chroot
+		initPath := filepath.Join(c.Rootfs, c.InitPath)
+
+		c.Path = d.initPath
+		c.Args = append([]string{
+			initPath,
+			"-driver", DriverName,
+			"-console", console,
+			"-pipe", "3",
+			"-root", filepath.Join(d.root, c.ID),
+			"--",
+		}, args...)
+
+		// set this to nil so that when we set the clone flags anything else is reset
+		c.SysProcAttr = nil
+		system.SetCloneFlags(&c.Cmd, uintptr(nsinit.GetNamespaceFlags(container.Namespaces)))
+		c.ExtraFiles = []*os.File{child}
+
+		c.Env = container.Env
+		c.Dir = c.Rootfs
+
+		return &c.Cmd
+	}, func() {
+		if startCallback != nil {
+			startCallback(c)
 		}
 		}
-	}
-	return c.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
-
+	})
 }
 }
 
 
 func (d *driver) Kill(p *execdriver.Command, sig int) error {
 func (d *driver) Kill(p *execdriver.Command, sig int) error {
@@ -297,26 +258,3 @@ func getTerminal(c *execdriver.Command, pipes *execdriver.Pipes) nsinit.Terminal
 	c.Terminal = term
 	c.Terminal = term
 	return term
 	return term
 }
 }
-
-func setupCommand(d *driver, c *execdriver.Command, container *libcontainer.Container, console string, syncFile *os.File, args []string) {
-	// we need to join the rootfs because nsinit will setup the rootfs and chroot
-	initPath := filepath.Join(c.Rootfs, c.InitPath)
-
-	c.Path = d.initPath
-	c.Args = append([]string{
-		initPath,
-		"-driver", DriverName,
-		"-console", console,
-		"-pipe", "3",
-		"-root", filepath.Join(d.root, c.ID),
-		"--",
-	}, args...)
-
-	// set this to nil so that when we set the clone flags anything else is reset
-	c.SysProcAttr = nil
-	system.SetCloneFlags(&c.Cmd, uintptr(nsinit.GetNamespaceFlags(container.Namespaces)))
-	c.ExtraFiles = []*os.File{syncFile}
-
-	c.Env = container.Env
-	c.Dir = c.Rootfs
-}

+ 10 - 0
pkg/libcontainer/nsinit/create.go

@@ -0,0 +1,10 @@
+package nsinit
+
+import (
+	"os"
+	"os/exec"
+
+	"github.com/dotcloud/docker/pkg/libcontainer"
+)
+
+type CreateCommand func(container *libcontainer.Container, console, rootfs, dataPath, init string, childPipe *os.File, args []string) *exec.Cmd

+ 4 - 4
pkg/libcontainer/nsinit/exec.go

@@ -17,7 +17,7 @@ import (
 
 
 // Exec performes setup outside of a namespace so that a container can be
 // Exec performes setup outside of a namespace so that a container can be
 // executed.  Exec is a high level function for working with container namespaces.
 // executed.  Exec is a high level function for working with container namespaces.
-func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, startCallback func()) (int, error) {
+func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
 	var (
 	var (
 		master  *os.File
 		master  *os.File
 		console string
 		console string
@@ -39,7 +39,7 @@ func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath str
 		term.SetMaster(master)
 		term.SetMaster(master)
 	}
 	}
 
 
-	command := CreateCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.child, args)
+	command := createCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.child, args)
 	if err := term.Attach(command); err != nil {
 	if err := term.Attach(command); err != nil {
 		return -1, err
 		return -1, err
 	}
 	}
@@ -90,7 +90,7 @@ func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath str
 	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
 	return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
 }
 }
 
 
-// CreateCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
+// DefaultCreateCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
 // defined on the container's configuration and use the current binary as the init with the
 // defined on the container's configuration and use the current binary as the init with the
 // args provided
 // args provided
 //
 //
@@ -99,7 +99,7 @@ func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath str
 // root: the path to the container json file and information
 // root: the path to the container json file and information
 // pipe: sync pipe to syncronize the parent and child processes
 // pipe: sync pipe to syncronize the parent and child processes
 // args: the arguemnts to pass to the container to run as the user's program
 // args: the arguemnts to pass to the container to run as the user's program
-func CreateCommand(container *libcontainer.Container, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
+func DefaultCreateCommand(container *libcontainer.Container, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
 	// get our binary name from arg0 so we can always reexec ourself
 	// get our binary name from arg0 so we can always reexec ourself
 	env := []string{
 	env := []string{
 		"console=" + console,
 		"console=" + console,

+ 1 - 1
pkg/libcontainer/nsinit/nsinit/main.go

@@ -39,7 +39,7 @@ func main() {
 			exitCode, err = nsinit.ExecIn(container, nspid, os.Args[2:])
 			exitCode, err = nsinit.ExecIn(container, nspid, os.Args[2:])
 		} else {
 		} else {
 			term := nsinit.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty)
 			term := nsinit.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty)
-			exitCode, err = nsinit.Exec(container, term, "", dataPath, os.Args[2:], nil)
+			exitCode, err = nsinit.Exec(container, term, "", dataPath, os.Args[2:], nsinit.DefaultCreateCommand, nil)
 		}
 		}
 
 
 		if err != nil {
 		if err != nil {

+ 4 - 0
pkg/libcontainer/nsinit/unsupported.go

@@ -7,6 +7,10 @@ import (
 	"github.com/dotcloud/docker/pkg/libcontainer"
 	"github.com/dotcloud/docker/pkg/libcontainer"
 )
 )
 
 
+func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
+	return -1, libcontainer.ErrUnsupported
+}
+
 func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
 func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
 	return libcontainer.ErrUnsupported
 	return libcontainer.ErrUnsupported
 }
 }