Merge pull request #333 from avagin/api-console

new-api: add Console to ProcessConfig
This commit is contained in:
Mrunal Patel 2015-01-15 12:11:12 -08:00
commit cc411c37bd
5 changed files with 86 additions and 16 deletions

View File

@ -100,7 +100,7 @@ func (c *linuxContainer) StartProcess(config *ProcessConfig) (int, error) {
if state != configs.Destroyed {
glog.Info("start new container process")
return namespaces.ExecIn(config.Args, config.Env, cmd, c.config, c.state)
return namespaces.ExecIn(config.Args, config.Env, config.Console, cmd, c.config, c.state)
}
if err := c.startInitProcess(cmd, config); err != nil {
@ -134,7 +134,7 @@ func (c *linuxContainer) updateStateFile() error {
}
func (c *linuxContainer) startInitProcess(cmd *exec.Cmd, config *ProcessConfig) error {
err := namespaces.Exec(config.Args, config.Env, cmd, c.config, c.cgroupManager, c.state)
err := namespaces.Exec(config.Args, config.Env, config.Console, cmd, c.config, c.cgroupManager, c.state)
if err != nil {
return err
}

View File

@ -19,7 +19,7 @@ import (
// Move this to libcontainer package.
// Exec performs setup outside of a namespace so that a container can be
// executed. Exec is a high level function for working with container namespaces.
func Exec(args []string, env []string, command *exec.Cmd, container *configs.Config, cgroupManager cgroups.Manager, state *configs.State) error {
func Exec(args []string, env []string, console string, command *exec.Cmd, container *configs.Config, cgroupManager cgroups.Manager, state *configs.State) error {
var err error
// create a pipe so that we can syncronize with the namespaced process and
@ -54,8 +54,9 @@ func Exec(args []string, env []string, command *exec.Cmd, container *configs.Con
}
process := processArgs{
Env: append(env[0:], container.Env...),
Args: args,
Env: append(env[0:], container.Env...),
Args: args,
ConsolePath: console,
}
if err := encoder.Encode(process); err != nil {
return terminate(err)

View File

@ -18,7 +18,7 @@ import (
// ExecIn reexec's cmd with _LIBCONTAINER_INITPID=PID so that it is able to run the
// setns code in a single threaded environment joining the existing containers' namespaces.
func ExecIn(args []string, env []string, cmd *exec.Cmd, container *configs.Config, state *configs.State) (int, error) {
func ExecIn(args []string, env []string, console string, cmd *exec.Cmd, container *configs.Config, state *configs.State) (int, error) {
var err error
parent, child, err := newInitPipe()
@ -50,8 +50,9 @@ func ExecIn(args []string, env []string, cmd *exec.Cmd, container *configs.Confi
}
process := processArgs{
Env: append(env[0:], container.Env...),
Args: args,
Env: append(env[0:], container.Env...),
Args: args,
ConsolePath: console,
}
if err := encoder.Encode(process); err != nil {
return terminate(err)

View File

@ -3,13 +3,16 @@ package main
import (
"crypto/md5"
"fmt"
"io"
"log"
"os"
"syscall"
"github.com/codegangsta/cli"
"github.com/docker/docker/pkg/term"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/configs"
consolepkg "github.com/docker/libcontainer/console"
)
var (
@ -50,21 +53,55 @@ func getContainer(context *cli.Context) (libcontainer.Container, error) {
}
func execAction(context *cli.Context) {
var exitCode int
var (
master *os.File
console string
err error
process := &libcontainer.ProcessConfig{
Args: context.Args(),
Env: context.StringSlice("env"),
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
}
sigc = make(chan os.Signal, 10)
stdin = os.Stdin
stdout = os.Stdout
stderr = os.Stderr
exitCode int
)
container, err := getContainer(context)
if err != nil {
log.Fatal(err)
}
if container.Config().Tty {
stdin = nil
stdout = nil
stderr = nil
master, console, err = consolepkg.CreateMasterAndConsole()
if err != nil {
log.Fatal(err)
}
go io.Copy(master, os.Stdin)
go io.Copy(os.Stdout, master)
state, err := term.SetRawTerminal(os.Stdin.Fd())
if err != nil {
log.Fatal(err)
}
defer term.RestoreTerminal(os.Stdin.Fd(), state)
}
process := &libcontainer.ProcessConfig{
Args: context.Args(),
Env: context.StringSlice("env"),
Stdin: stdin,
Stdout: stdout,
Stderr: stderr,
Console: console,
}
pid, err := container.StartProcess(process)
if err != nil {
log.Fatalf("failed to exec: %s", err)
@ -75,6 +112,19 @@ func execAction(context *cli.Context) {
log.Fatalf("Unable to find the %d process: %s", pid, err)
}
go func() {
resizeTty(master)
for sig := range sigc {
switch sig {
case syscall.SIGWINCH:
resizeTty(master)
default:
p.Signal(sig)
}
}
}()
ps, err := p.Wait()
if err != nil {
log.Fatalf("Unable to wait the %d process: %s", pid, err)
@ -92,3 +142,18 @@ func execAction(context *cli.Context) {
os.Exit(exitCode)
}
func resizeTty(master *os.File) {
if master == nil {
return
}
ws, err := term.GetWinsize(os.Stdin.Fd())
if err != nil {
return
}
if err := term.SetWinsize(master.Fd(), ws); err != nil {
return
}
}

View File

@ -21,4 +21,7 @@ type ProcessConfig struct {
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
// Console is the path to the pty slave for use by the master
Console string
}