mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Make native driver use Exec func with different CreateCommand
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
aa9705f832
commit
da0d6dbd7b
5 changed files with 46 additions and 94 deletions
|
@ -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 {
|
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 {
|
||||||
master, console, err = system.CreateMasterAndConsole()
|
// we need to join the rootfs because nsinit will setup the rootfs and chroot
|
||||||
if err != nil {
|
initPath := filepath.Join(c.Rootfs, c.InitPath)
|
||||||
return -1, err
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
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 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
pkg/libcontainer/nsinit/create.go
Normal file
10
pkg/libcontainer/nsinit/create.go
Normal file
|
@ -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
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue