From 8d0b06257ba659ee91fa3862ed358cecbee37f73 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Wed, 25 Feb 2015 14:31:39 -0800 Subject: [PATCH] Move tty configuration to Process Now you need to call Process.NewConsole to setup console for process Signed-off-by: Alexander Morozov --- configs/config.go | 3 --- console_linux.go | 4 ++-- container_linux.go | 11 ++++++----- init_linux.go | 1 + nsinit/exec.go | 20 ++++++++------------ nsinit/tty.go | 4 ++-- process.go | 13 +++++++++++++ rootfs_linux.go | 9 ++++----- standard_init_linux.go | 10 +++++----- 9 files changed, 41 insertions(+), 34 deletions(-) diff --git a/configs/config.go b/configs/config.go index 6fcd8666..b07f252b 100644 --- a/configs/config.go +++ b/configs/config.go @@ -49,9 +49,6 @@ type Config struct { // Hostname optionally sets the container's hostname if provided Hostname string `json:"hostname"` - // Console is the path to the console allocated to the container. - Console string `json:"console"` - // Namespaces specifies the container's namespaces that it should setup when cloning the init process // If a namespace is not provided that namespace is shared from the container's parent process Namespaces Namespaces `json:"namespaces"` diff --git a/console_linux.go b/console_linux.go index f7a67a01..afdc2976 100644 --- a/console_linux.go +++ b/console_linux.go @@ -12,9 +12,9 @@ import ( "github.com/docker/libcontainer/label" ) -// NewConsole returns an initalized console that can be used within a container by copying bytes +// newConsole returns an initalized console that can be used within a container by copying bytes // from the master side to the slave that is attached as the tty for the container's init process. -func NewConsole(uid, gid int) (Console, error) { +func newConsole(uid, gid int) (Console, error) { master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0) if err != nil { return nil, err diff --git a/container_linux.go b/container_linux.go index 0b35ded5..3ea08db2 100644 --- a/container_linux.go +++ b/container_linux.go @@ -181,11 +181,12 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe, func (c *linuxContainer) newInitConfig(process *Process) *initConfig { return &initConfig{ - Config: c.config, - Args: process.Args, - Env: process.Env, - User: process.User, - Cwd: process.Cwd, + Config: c.config, + Args: process.Args, + Env: process.Env, + User: process.User, + Cwd: process.Cwd, + Console: process.consolePath, } } diff --git a/init_linux.go b/init_linux.go index 37891102..1c5f6a87 100644 --- a/init_linux.go +++ b/init_linux.go @@ -45,6 +45,7 @@ type initConfig struct { Cwd string `json:"cwd"` User string `json:"user"` Config *configs.Config `json:"config"` + Console string `json:"console"` Networks []*network `json:"network"` } diff --git a/nsinit/exec.go b/nsinit/exec.go index d779bf0d..c2b9b0b0 100644 --- a/nsinit/exec.go +++ b/nsinit/exec.go @@ -41,23 +41,11 @@ func execAction(context *cli.Context) { if err != nil { fatal(err) } - rootuid, err := config.HostUID() - if err != nil { - fatal(err) - } - tty, err := newTty(context, rootuid) - if err != nil { - fatal(err) - } created := false container, err := factory.Load(context.String("id")) if err != nil { - if tty.console != nil { - config.Console = tty.console.Path() - } created = true if container, err = factory.Create(context.String("id"), config); err != nil { - tty.Close() fatal(err) } } @@ -70,6 +58,14 @@ func execAction(context *cli.Context) { Stdout: os.Stdout, Stderr: os.Stderr, } + rootuid, err := config.HostUID() + if err != nil { + fatal(err) + } + tty, err := newTty(context, process, rootuid) + if err != nil { + fatal(err) + } if err := tty.attach(process); err != nil { fatal(err) } diff --git a/nsinit/tty.go b/nsinit/tty.go index 5d417b98..66893974 100644 --- a/nsinit/tty.go +++ b/nsinit/tty.go @@ -9,9 +9,9 @@ import ( "github.com/docker/libcontainer" ) -func newTty(context *cli.Context, rootuid int) (*tty, error) { +func newTty(context *cli.Context, p *libcontainer.Process, rootuid int) (*tty, error) { if context.Bool("tty") { - console, err := libcontainer.NewConsole(rootuid, rootuid) + console, err := p.NewConsole(rootuid) if err != nil { return nil, err } diff --git a/process.go b/process.go index 94648925..8ae74163 100644 --- a/process.go +++ b/process.go @@ -36,6 +36,9 @@ type Process struct { // Stderr is a pointer to a writer which receives the standard error stream. Stderr io.Writer + // consolePath is the path to the console allocated to the container. + consolePath string + ops processOperations } @@ -63,3 +66,13 @@ func (p Process) Signal(sig os.Signal) error { } return p.ops.signal(sig) } + +// NewConsole creates new console for process and returns it +func (p *Process) NewConsole(rootuid int) (Console, error) { + console, err := newConsole(rootuid, rootuid) + if err != nil { + return nil, err + } + p.consolePath = console.Path() + return console, nil +} diff --git a/rootfs_linux.go b/rootfs_linux.go index 7aba21bd..4b3708cf 100644 --- a/rootfs_linux.go +++ b/rootfs_linux.go @@ -41,7 +41,7 @@ var baseMounts = []*configs.Mount{ // setupRootfs sets up the devices, mount points, and filesystems for use inside a // new mount namespace. -func setupRootfs(config *configs.Config) (err error) { +func setupRootfs(config *configs.Config, console *linuxConsole) (err error) { if err := prepareRoot(config); err != nil { return newSystemError(err) } @@ -53,7 +53,7 @@ func setupRootfs(config *configs.Config) (err error) { if err := createDevices(config); err != nil { return newSystemError(err) } - if err := setupPtmx(config); err != nil { + if err := setupPtmx(config, console); err != nil { return newSystemError(err) } // stdin, stdout and stderr could be pointing to /dev/null from parent namespace. @@ -255,7 +255,7 @@ func setReadonly() error { return syscall.Mount("/", "/", "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "") } -func setupPtmx(config *configs.Config) error { +func setupPtmx(config *configs.Config, console *linuxConsole) error { ptmx := filepath.Join(config.Rootfs, "dev/ptmx") if err := os.Remove(ptmx); err != nil && !os.IsNotExist(err) { return err @@ -263,8 +263,7 @@ func setupPtmx(config *configs.Config) error { if err := os.Symlink("pts/ptmx", ptmx); err != nil { return fmt.Errorf("symlink dev ptmx %s", err) } - if config.Console != "" { - console := newConsoleFromPath(config.Console) + if console != nil { return console.mount(config.Rootfs, config.MountLabel, 0, 0) } return nil diff --git a/standard_init_linux.go b/standard_init_linux.go index 28ce1727..db721b8d 100644 --- a/standard_init_linux.go +++ b/standard_init_linux.go @@ -20,9 +20,9 @@ func (l *linuxStandardInit) Init() error { if err := joinExistingNamespaces(l.config.Config.Namespaces); err != nil { return err } - consolePath := l.config.Config.Console - if consolePath != "" { - console := newConsoleFromPath(consolePath) + var console *linuxConsole + if l.config.Console != "" { + console = newConsoleFromPath(l.config.Console) if err := console.dupStdio(); err != nil { return err } @@ -30,7 +30,7 @@ func (l *linuxStandardInit) Init() error { if _, err := syscall.Setsid(); err != nil { return err } - if consolePath != "" { + if console != nil { if err := system.Setctty(); err != nil { return err } @@ -47,7 +47,7 @@ func (l *linuxStandardInit) Init() error { label.Init() // InitializeMountNamespace() can be executed only for a new mount namespace if l.config.Config.Namespaces.Contains(configs.NEWNS) { - if err := setupRootfs(l.config.Config); err != nil { + if err := setupRootfs(l.config.Config, console); err != nil { return err } }