Move creation and attach to driver
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
Michael Crosby 2014-02-21 12:32:14 -08:00
Родитель 8c783c1c13
Коммит 1e74287698
7 изменённых файлов: 159 добавлений и 161 удалений

Просмотреть файл

@ -55,7 +55,6 @@ type Container struct {
Driver string
command *execdriver.Command
console execdriver.Console
stdout *utils.WriteBroadcaster
stderr *utils.WriteBroadcaster
stdin io.ReadCloser
@ -531,6 +530,9 @@ func (container *Container) Start() (err error) {
}
populateCommand(container)
if err := execdriver.NewTerminal(container.command); err != nil {
return err
}
// Setup logging of stdout and stderr to disk
if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
@ -541,16 +543,6 @@ func (container *Container) Start() (err error) {
}
container.waitLock = make(chan struct{})
container.console, err = execdriver.NewConsole(
container.stdin, container.stdout, container.stderr,
container.Config.OpenStdin, container.Config.Tty)
if err != nil {
return err
}
if err := container.console.AttachTo(container.command); err != nil {
return err
}
callbackLock := make(chan struct{})
callback := func(command *execdriver.Command) {
container.State.SetRunning(command.Pid())
@ -790,7 +782,8 @@ func (container *Container) monitor(callback execdriver.StartCallback) error {
populateCommand(container)
err = container.runtime.RestoreCommand(container)
} else {
exitCode, err = container.runtime.Run(container, callback)
pipes := execdriver.NewPipes(container.stdin, container.stdout, container.stderr, container.Config.OpenStdin)
exitCode, err = container.runtime.Run(container, pipes, callback)
}
if err != nil {
@ -845,9 +838,9 @@ func (container *Container) cleanup() {
if err := container.stderr.Close(); err != nil {
utils.Errorf("%s: Error close stderr: %s", container.ID, err)
}
if container.console != nil {
if err := container.console.Close(); err != nil {
utils.Errorf("%s: Error closing console: %s", container.ID, err)
if container.command.Terminal != nil {
if err := container.command.Terminal.Close(); err != nil {
utils.Errorf("%s: Error closing terminal: %s", container.ID, err)
}
}
@ -939,7 +932,7 @@ func (container *Container) Wait() int {
}
func (container *Container) Resize(h, w int) error {
return container.console.Resize(h, w)
return container.command.Terminal.Resize(h, w)
}
func (container *Container) ExportRw() (archive.Archive, error) {
@ -1143,7 +1136,7 @@ func (container *Container) Exposes(p nat.Port) bool {
}
func (container *Container) GetPtyMaster() (*os.File, error) {
ttyConsole, ok := container.console.(*execdriver.TtyConsole)
ttyConsole, ok := container.command.Terminal.(*execdriver.TtyConsole)
if !ok {
return nil, ErrNoTTY
}

Просмотреть файл

@ -37,7 +37,7 @@ func NewDriver() (*driver, error) {
return &driver{}, nil
}
func (d *driver) Run(c *execdriver.Command, startCallback execdriver.StartCallback) (int, error) {
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
params := []string{
"chroot",
c.Rootfs,

Просмотреть файл

@ -1,137 +0,0 @@
package execdriver
import (
"github.com/dotcloud/docker/pkg/term"
"github.com/kr/pty"
"io"
"os"
)
type Console interface {
io.Closer
Resize(height, width int) error
AttachTo(command *Command) error
}
type pipes struct {
Stdin io.ReadCloser
Stdout, Stderr io.WriteCloser
}
func (p *pipes) Close() error {
if p.Stderr != nil {
p.Stdin.Close()
}
if p.Stdout != nil {
p.Stdout.Close()
}
if p.Stderr != nil {
p.Stderr.Close()
}
return nil
}
func NewConsole(stdin io.ReadCloser, stdout, stderr io.WriteCloser, useStdin, tty bool) (Console, error) {
p := &pipes{
Stdout: stdout,
Stderr: stderr,
}
if useStdin {
p.Stdin = stdin
}
if tty {
return NewTtyConsole(p)
}
return NewStdConsole(p)
}
type TtyConsole struct {
Master *os.File
Slave *os.File
pipes *pipes
}
func NewTtyConsole(p *pipes) (*TtyConsole, error) {
ptyMaster, ptySlave, err := pty.Open()
if err != nil {
return nil, err
}
tty := &TtyConsole{
Master: ptyMaster,
Slave: ptySlave,
pipes: p,
}
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) AttachTo(command *Command) error {
command.Stdout = t.Slave
command.Stderr = t.Slave
command.Console = t.Slave.Name()
go func() {
defer t.pipes.Stdout.Close()
io.Copy(t.pipes.Stdout, t.Master)
}()
if t.pipes.Stdin != nil {
command.Stdin = t.Slave
command.SysProcAttr.Setctty = true
go func() {
defer t.pipes.Stdin.Close()
io.Copy(t.Master, t.pipes.Stdin)
}()
}
return nil
}
func (t *TtyConsole) Close() error {
err := t.Slave.Close()
if merr := t.Master.Close(); err == nil {
err = merr
}
return err
}
type StdConsole struct {
pipes *pipes
}
func NewStdConsole(p *pipes) (*StdConsole, error) {
return &StdConsole{p}, nil
}
func (s *StdConsole) AttachTo(command *Command) error {
command.Stdout = s.pipes.Stdout
command.Stderr = s.pipes.Stderr
if s.pipes.Stdin != nil {
stdin, err := command.StdinPipe()
if err != nil {
return err
}
go func() {
defer stdin.Close()
io.Copy(stdin, s.pipes.Stdin)
}()
}
return nil
}
func (s *StdConsole) Resize(h, w int) error {
// we do not need to reside a non tty
return nil
}
func (s *StdConsole) Close() error {
// nothing to close here
return nil
}

Просмотреть файл

@ -58,7 +58,7 @@ type Info interface {
}
type Driver interface {
Run(c *Command, startCallback StartCallback) (int, error) // Run executes the process and blocks until the process exits and returns the exit code
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
Restore(c *Command) error // Wait and try to re-attach on an out of process command
Name() string // Driver name
@ -82,7 +82,6 @@ type Resources struct {
}
// Process wrapps an os/exec.Cmd to add more metadata
// TODO: Rename to Command
type Command struct {
exec.Cmd `json:"-"`
@ -100,7 +99,8 @@ type Command struct {
Config []string `json:"config"` // generic values that specific drivers can consume
Resources *Resources `json:"resources"`
Console string `json:"-"`
Terminal Term `json:"-"`
Console string `json:"-"`
}
// Return the pid of the process

Просмотреть файл

@ -76,7 +76,12 @@ func (d *driver) Name() string {
return fmt.Sprintf("%s-%s", DriverName, version)
}
func (d *driver) Run(c *execdriver.Command, startCallback execdriver.StartCallback) (int, error) {
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
if c.Terminal != nil {
if err := c.Terminal.Attach(pipes); err != nil {
return -1, err
}
}
configPath, err := d.generateLXCConfig(c)
if err != nil {
return -1, err

137
execdriver/term.go Normal file
Просмотреть файл

@ -0,0 +1,137 @@
package execdriver
import (
"github.com/dotcloud/docker/pkg/term"
"github.com/kr/pty"
"io"
"os"
)
type Term interface {
io.Closer
Resize(height, width int) error
Attach(pipes *Pipes) error
}
type Pipes struct {
Stdin io.ReadCloser
Stdout, Stderr io.WriteCloser
}
func NewPipes(stdin io.ReadCloser, stdout, stderr io.WriteCloser, useStdin bool) *Pipes {
p := &Pipes{
Stdout: stdout,
Stderr: stderr,
}
if useStdin {
p.Stdin = stdin
}
return p
}
func NewTerminal(command *Command) error {
var (
term Term
err error
)
if command.Tty {
term, err = NewTtyConsole(command)
} else {
term, err = NewStdConsole(command)
}
if err != nil {
return err
}
command.Terminal = term
return nil
}
type TtyConsole struct {
command *Command
Master *os.File
Slave *os.File
}
func NewTtyConsole(command *Command) (*TtyConsole, error) {
ptyMaster, ptySlave, err := pty.Open()
if err != nil {
return nil, err
}
tty := &TtyConsole{
Master: ptyMaster,
Slave: ptySlave,
command: command,
}
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) Attach(pipes *Pipes) error {
t.command.Stdout = t.Slave
t.command.Stderr = t.Slave
t.command.Console = t.Slave.Name()
go func() {
defer pipes.Stdout.Close()
io.Copy(pipes.Stdout, t.Master)
}()
if pipes.Stdin != nil {
t.command.Stdin = t.Slave
t.command.SysProcAttr.Setctty = true
go func() {
defer pipes.Stdin.Close()
io.Copy(t.Master, pipes.Stdin)
}()
}
return nil
}
func (t *TtyConsole) Close() error {
err := t.Slave.Close()
if merr := t.Master.Close(); err == nil {
err = merr
}
return err
}
type StdConsole struct {
command *Command
}
func NewStdConsole(command *Command) (*StdConsole, error) {
return &StdConsole{command}, nil
}
func (s *StdConsole) Attach(pipes *Pipes) error {
s.command.Stdout = pipes.Stdout
s.command.Stderr = pipes.Stderr
if pipes.Stdin != nil {
stdin, err := s.command.StdinPipe()
if err != nil {
return err
}
go func() {
defer stdin.Close()
io.Copy(stdin, pipes.Stdin)
}()
}
return nil
}
func (s *StdConsole) Resize(h, w int) error {
// we do not need to reside a non tty
return nil
}
func (s *StdConsole) Close() error {
// nothing to close here
return nil
}

Просмотреть файл

@ -812,8 +812,8 @@ func (runtime *Runtime) Diff(container *Container) (archive.Archive, error) {
}), nil
}
func (runtime *Runtime) Run(c *Container, startCallback execdriver.StartCallback) (int, error) {
return runtime.execDriver.Run(c.command, startCallback)
func (runtime *Runtime) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
return runtime.execDriver.Run(c.command, pipes, startCallback)
}
func (runtime *Runtime) Kill(c *Container, sig int) error {