From aac702727ea02b3974a2848748b0713ac583fc84 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 21 Feb 2014 13:27:15 -0800 Subject: [PATCH] Move current tty and pipe impl to lxc driver Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- container.go | 4 +-- execdriver/driver.go | 18 ++++++++-- execdriver/lxc/driver.go | 2 +- execdriver/{ => lxc}/term.go | 68 ++++++++++++++---------------------- execdriver/pipes.go | 23 ++++++++++++ 5 files changed, 68 insertions(+), 47 deletions(-) rename execdriver/{ => lxc}/term.go (58%) create mode 100644 execdriver/pipes.go diff --git a/container.go b/container.go index 218ae1e4a8..ca53bb57c7 100644 --- a/container.go +++ b/container.go @@ -1133,9 +1133,9 @@ func (container *Container) Exposes(p nat.Port) bool { } func (container *Container) GetPtyMaster() (*os.File, error) { - ttyConsole, ok := container.command.Terminal.(*execdriver.TtyConsole) + ttyConsole, ok := container.command.Terminal.(execdriver.TtyTerminal) if !ok { return nil, ErrNoTTY } - return ttyConsole.Master, nil + return ttyConsole.Master(), nil } diff --git a/execdriver/driver.go b/execdriver/driver.go index c9f62f500e..a6d865caf3 100644 --- a/execdriver/driver.go +++ b/execdriver/driver.go @@ -2,6 +2,8 @@ package execdriver import ( "errors" + "io" + "os" "os/exec" ) @@ -57,6 +59,18 @@ type Info interface { IsRunning() bool } +// Terminal in an interface for drivers to implement +// if they want to support Close and Resize calls from +// the core +type Terminal interface { + io.Closer + Resize(height, width int) error +} + +type TtyTerminal interface { + Master() *os.File +} + type Driver interface { Run(c *Command, pipes *Pipes, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code Kill(c *Command, sig int) error @@ -99,8 +113,8 @@ type Command struct { Config []string `json:"config"` // generic values that specific drivers can consume Resources *Resources `json:"resources"` - Terminal Term `json:"-"` - Console string `json:"-"` + Terminal Terminal `json:"-"` // standard or tty terminal + Console string `json:"-"` // dev/console path } // Return the pid of the process diff --git a/execdriver/lxc/driver.go b/execdriver/lxc/driver.go index c18b2e6ab4..5be7ad2219 100644 --- a/execdriver/lxc/driver.go +++ b/execdriver/lxc/driver.go @@ -77,7 +77,7 @@ func (d *driver) Name() string { } func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) { - if err := execdriver.SetTerminal(c, pipes); err != nil { + if err := SetTerminal(c, pipes); err != nil { return -1, err } configPath, err := d.generateLXCConfig(c) diff --git a/execdriver/term.go b/execdriver/lxc/term.go similarity index 58% rename from execdriver/term.go rename to execdriver/lxc/term.go index ec3c368012..d772f60972 100644 --- a/execdriver/term.go +++ b/execdriver/lxc/term.go @@ -1,36 +1,16 @@ -package execdriver +package lxc import ( + "github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/pkg/term" "github.com/kr/pty" "io" "os" ) -type Term interface { - io.Closer - Resize(height, width int) error -} - -type Pipes struct { - Stdin io.ReadCloser - Stdout, Stderr io.Writer -} - -func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes { - p := &Pipes{ - Stdout: stdout, - Stderr: stderr, - } - if useStdin { - p.Stdin = stdin - } - return p -} - -func SetTerminal(command *Command, pipes *Pipes) error { +func SetTerminal(command *execdriver.Command, pipes *execdriver.Pipes) error { var ( - term Term + term execdriver.Terminal err error ) if command.Tty { @@ -46,18 +26,18 @@ func SetTerminal(command *Command, pipes *Pipes) error { } type TtyConsole struct { - Master *os.File - Slave *os.File + master *os.File + slave *os.File } -func NewTtyConsole(command *Command, pipes *Pipes) (*TtyConsole, error) { +func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyConsole, error) { ptyMaster, ptySlave, err := pty.Open() if err != nil { return nil, err } tty := &TtyConsole{ - Master: ptyMaster, - Slave: ptySlave, + master: ptyMaster, + slave: ptySlave, } if err := tty.attach(command, pipes); err != nil { tty.Close() @@ -66,14 +46,18 @@ func NewTtyConsole(command *Command, pipes *Pipes) (*TtyConsole, error) { return tty, nil } -func (t *TtyConsole) Resize(h, w int) error { - return term.SetWinsize(t.Master.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)}) +func (t *TtyConsole) Master() *os.File { + return t.master } -func (t *TtyConsole) attach(command *Command, pipes *Pipes) error { - command.Stdout = t.Slave - command.Stderr = t.Slave - command.Console = t.Slave.Name() +func (t *TtyConsole) Resize(h, w int) error { + return term.SetWinsize(t.master.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)}) +} + +func (t *TtyConsole) attach(command *execdriver.Command, pipes *execdriver.Pipes) error { + command.Stdout = t.slave + command.Stderr = t.slave + command.Console = t.slave.Name() go func() { if wb, ok := pipes.Stdout.(interface { @@ -81,30 +65,30 @@ func (t *TtyConsole) attach(command *Command, pipes *Pipes) error { }); ok { defer wb.CloseWriters() } - io.Copy(pipes.Stdout, t.Master) + io.Copy(pipes.Stdout, t.master) }() if pipes.Stdin != nil { - command.Stdin = t.Slave + command.Stdin = t.slave command.SysProcAttr.Setctty = true go func() { defer pipes.Stdin.Close() - io.Copy(t.Master, pipes.Stdin) + io.Copy(t.master, pipes.Stdin) }() } return nil } func (t *TtyConsole) Close() error { - t.Slave.Close() - return t.Master.Close() + t.slave.Close() + return t.master.Close() } type StdConsole struct { } -func NewStdConsole(command *Command, pipes *Pipes) (*StdConsole, error) { +func NewStdConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*StdConsole, error) { std := &StdConsole{} if err := std.attach(command, pipes); err != nil { @@ -113,7 +97,7 @@ func NewStdConsole(command *Command, pipes *Pipes) (*StdConsole, error) { return std, nil } -func (s *StdConsole) attach(command *Command, pipes *Pipes) error { +func (s *StdConsole) attach(command *execdriver.Command, pipes *execdriver.Pipes) error { command.Stdout = pipes.Stdout command.Stderr = pipes.Stderr diff --git a/execdriver/pipes.go b/execdriver/pipes.go new file mode 100644 index 0000000000..158219f0c5 --- /dev/null +++ b/execdriver/pipes.go @@ -0,0 +1,23 @@ +package execdriver + +import ( + "io" +) + +// Pipes is a wrapper around a containers output for +// stdin, stdout, stderr +type Pipes struct { + Stdin io.ReadCloser + Stdout, Stderr io.Writer +} + +func NewPipes(stdin io.ReadCloser, stdout, stderr io.Writer, useStdin bool) *Pipes { + p := &Pipes{ + Stdout: stdout, + Stderr: stderr, + } + if useStdin { + p.Stdin = stdin + } + return p +}