mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Integrate new structure into docker's native driver
This duplicates some of the Exec code but I think it it worth it because the native driver is more straight forward and does not have the complexity have handling the type issues for now. Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
176c49d7a9
commit
60e4276f5a
5 changed files with 143 additions and 66 deletions
|
@ -27,10 +27,7 @@ const (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
execdriver.RegisterInitFunc(DriverName, func(args *execdriver.InitArgs) error {
|
execdriver.RegisterInitFunc(DriverName, func(args *execdriver.InitArgs) error {
|
||||||
var (
|
var container *libcontainer.Container
|
||||||
container *libcontainer.Container
|
|
||||||
ns = nsinit.NewNsInit(&nsinit.DefaultCommandFactory{})
|
|
||||||
)
|
|
||||||
f, err := os.Open(filepath.Join(args.Root, "container.json"))
|
f, err := os.Open(filepath.Join(args.Root, "container.json"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -41,7 +38,7 @@ func init() {
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
cwd, err := os.Getwd()
|
rootfs, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -49,7 +46,7 @@ func init() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.Init(container, cwd, args.Console, syncPipe, args.Args); err != nil {
|
if err := nsinit.Init(container, rootfs, args.Console, syncPipe, args.Args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -93,35 +90,87 @@ 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 (
|
||||||
term nsinit.Terminal
|
master *os.File
|
||||||
factory = &dockerCommandFactory{c: c, driver: d}
|
console string
|
||||||
pidRoot = filepath.Join(d.root, c.ID)
|
|
||||||
ns = nsinit.NewNsInit(factory)
|
dataPath = filepath.Join(d.root, c.ID)
|
||||||
args = append([]string{c.Entrypoint}, c.Arguments...)
|
args = append([]string{c.Entrypoint}, c.Arguments...)
|
||||||
)
|
)
|
||||||
if err := d.createContainerRoot(c.ID); err != nil {
|
if err := d.createContainerRoot(c.ID); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
defer d.removeContainerRoot(c.ID)
|
defer d.removeContainerRoot(c.ID)
|
||||||
|
|
||||||
if c.Tty {
|
|
||||||
term = &dockerTtyTerm{
|
|
||||||
pipes: pipes,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
term = &dockerStdTerm{
|
|
||||||
pipes: pipes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.Terminal = term
|
|
||||||
if err := d.writeContainerFile(container, c.ID); err != nil {
|
if err := d.writeContainerFile(container, c.ID); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
return ns.Exec(container, term, pidRoot, args, func() {
|
|
||||||
if startCallback != nil {
|
// create a pipe so that we can syncronize with the namespaced process and
|
||||||
startCallback(c)
|
// pass the veth name to the child
|
||||||
|
syncPipe, err := nsinit.NewSyncPipe()
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
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 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 {
|
||||||
|
@ -234,35 +283,40 @@ func getEnv(key string, env []string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerCommandFactory struct {
|
func getTerminal(c *execdriver.Command, pipes *execdriver.Pipes) nsinit.Terminal {
|
||||||
c *execdriver.Command
|
var term nsinit.Terminal
|
||||||
driver *driver
|
if c.Tty {
|
||||||
|
term = &dockerTtyTerm{
|
||||||
|
pipes: pipes,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
term = &dockerStdTerm{
|
||||||
|
pipes: pipes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Terminal = term
|
||||||
|
return term
|
||||||
}
|
}
|
||||||
|
|
||||||
// createCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
|
func setupCommand(d *driver, c *execdriver.Command, container *libcontainer.Container, console string, syncFile *os.File, args []string) {
|
||||||
// defined on the container's configuration and use the current binary as the init with the
|
|
||||||
// args provided
|
|
||||||
func (d *dockerCommandFactory) Create(container *libcontainer.Container, console string, syncFile *os.File, args []string) *exec.Cmd {
|
|
||||||
// we need to join the rootfs because nsinit will setup the rootfs and chroot
|
// we need to join the rootfs because nsinit will setup the rootfs and chroot
|
||||||
initPath := filepath.Join(d.c.Rootfs, d.c.InitPath)
|
initPath := filepath.Join(c.Rootfs, c.InitPath)
|
||||||
|
|
||||||
d.c.Path = d.driver.initPath
|
c.Path = d.initPath
|
||||||
d.c.Args = append([]string{
|
c.Args = append([]string{
|
||||||
initPath,
|
initPath,
|
||||||
"-driver", DriverName,
|
"-driver", DriverName,
|
||||||
"-console", console,
|
"-console", console,
|
||||||
"-pipe", "3",
|
"-pipe", "3",
|
||||||
"-root", filepath.Join(d.driver.root, d.c.ID),
|
"-root", filepath.Join(d.root, c.ID),
|
||||||
"--",
|
"--",
|
||||||
}, args...)
|
}, args...)
|
||||||
|
|
||||||
// set this to nil so that when we set the clone flags anything else is reset
|
// set this to nil so that when we set the clone flags anything else is reset
|
||||||
d.c.SysProcAttr = nil
|
c.SysProcAttr = nil
|
||||||
system.SetCloneFlags(&d.c.Cmd, uintptr(nsinit.GetNamespaceFlags(container.Namespaces)))
|
system.SetCloneFlags(&c.Cmd, uintptr(nsinit.GetNamespaceFlags(container.Namespaces)))
|
||||||
d.c.ExtraFiles = []*os.File{syncFile}
|
c.ExtraFiles = []*os.File{syncFile}
|
||||||
|
|
||||||
d.c.Env = container.Env
|
c.Env = container.Env
|
||||||
d.c.Dir = d.c.Rootfs
|
c.Dir = c.Rootfs
|
||||||
|
|
||||||
return &d.c.Cmd
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,8 @@
|
||||||
package nsinit
|
package nsinit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/pkg/cgroups"
|
"github.com/dotcloud/docker/pkg/cgroups"
|
||||||
|
@ -160,26 +157,6 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy
|
||||||
return pipe.SendToChild(context)
|
return pipe.SendToChild(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WritePid writes the namespaced processes pid to pid and it's start time
|
|
||||||
// to the path specified
|
|
||||||
func WritePid(path string, pid int, startTime string) error {
|
|
||||||
err := ioutil.WriteFile(filepath.Join(path, "pid"), []byte(fmt.Sprint(pid)), 0655)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return ioutil.WriteFile(filepath.Join(path, "start"), []byte(startTime), 0655)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeletePid removes the pid and started file from disk when the container's process
|
|
||||||
// dies and the container is cleanly removed
|
|
||||||
func DeletePid(path string) error {
|
|
||||||
err := os.Remove(filepath.Join(path, "pid"))
|
|
||||||
if serr := os.Remove(filepath.Join(path, "start")); err == nil {
|
|
||||||
err = serr
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNamespaceFlags parses the container's Namespaces options to set the correct
|
// GetNamespaceFlags parses the container's Namespaces options to set the correct
|
||||||
// flags on clone, unshare, and setns
|
// flags on clone, unshare, and setns
|
||||||
func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
||||||
|
|
28
pkg/libcontainer/nsinit/pid.go
Normal file
28
pkg/libcontainer/nsinit/pid.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package nsinit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WritePid writes the namespaced processes pid to pid and it's start time
|
||||||
|
// to the path specified
|
||||||
|
func WritePid(path string, pid int, startTime string) error {
|
||||||
|
err := ioutil.WriteFile(filepath.Join(path, "pid"), []byte(fmt.Sprint(pid)), 0655)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(filepath.Join(path, "start"), []byte(startTime), 0655)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePid removes the pid and started file from disk when the container's process
|
||||||
|
// dies and the container is cleanly removed
|
||||||
|
func DeletePid(path string) error {
|
||||||
|
err := os.Remove(filepath.Join(path, "pid"))
|
||||||
|
if serr := os.Remove(filepath.Join(path, "start")); err == nil {
|
||||||
|
err = serr
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -3,9 +3,22 @@
|
||||||
package nsinit
|
package nsinit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/dotcloud/docker/pkg/cgroups"
|
||||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
|
||||||
|
return libcontainer.ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error {
|
||||||
|
return libcontainer.ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveCgroup, error) {
|
||||||
|
return nil, libcontainer.ErrUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
func GetNamespaceFlags(namespaces libcontainer.Namespaces) (flag int) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package system
|
package system
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,3 +24,7 @@ func GetClockTicks() int {
|
||||||
// just return 100
|
// just return 100
|
||||||
return 100
|
return 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateMasterAndConsole() (*os.File, string, error) {
|
||||||
|
return nil, "", ErrNotSupportedPlatform
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue