mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #16305 from estesp/hooks-for-the-hooks-gods
Use libcontainer hook for network namespace info passing to libnetwork's sandbox
This commit is contained in:
commit
ac34ce0307
13 changed files with 122 additions and 40 deletions
|
@ -811,7 +811,7 @@ func (container *Container) exec(ExecConfig *ExecConfig) error {
|
||||||
container.Lock()
|
container.Lock()
|
||||||
defer container.Unlock()
|
defer container.Unlock()
|
||||||
|
|
||||||
callback := func(processConfig *execdriver.ProcessConfig, pid int) {
|
callback := func(processConfig *execdriver.ProcessConfig, pid int) error {
|
||||||
if processConfig.Tty {
|
if processConfig.Tty {
|
||||||
// The callback is called after the process Start()
|
// The callback is called after the process Start()
|
||||||
// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave
|
// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave
|
||||||
|
@ -821,6 +821,7 @@ func (container *Container) exec(ExecConfig *ExecConfig) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(ExecConfig.waitStart)
|
close(ExecConfig.waitStart)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use a callback here instead of a goroutine and an chan for
|
// We use a callback here instead of a goroutine and an chan for
|
||||||
|
@ -837,7 +838,7 @@ func (container *Container) exec(ExecConfig *ExecConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) monitorExec(ExecConfig *ExecConfig, callback execdriver.StartCallback) error {
|
func (container *Container) monitorExec(ExecConfig *ExecConfig, callback execdriver.DriverCallback) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
exitCode int
|
exitCode int
|
||||||
|
|
|
@ -174,8 +174,9 @@ func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.
|
||||||
func populateCommand(c *Container, env []string) error {
|
func populateCommand(c *Container, env []string) error {
|
||||||
var en *execdriver.Network
|
var en *execdriver.Network
|
||||||
if !c.Config.NetworkDisabled {
|
if !c.Config.NetworkDisabled {
|
||||||
en = &execdriver.Network{
|
en = &execdriver.Network{}
|
||||||
NamespacePath: c.NetworkSettings.SandboxKey,
|
if !c.daemon.execDriver.SupportsHooks() || c.hostConfig.NetworkMode.IsHost() {
|
||||||
|
en.NamespacePath = c.NetworkSettings.SandboxKey
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
|
parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
|
||||||
|
@ -405,6 +406,10 @@ func (container *Container) buildSandboxOptions() ([]libnetwork.SandboxOption, e
|
||||||
sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
|
sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
|
||||||
sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
|
sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
|
||||||
sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
|
sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
|
||||||
|
} else if container.daemon.execDriver.SupportsHooks() {
|
||||||
|
// OptionUseExternalKey is mandatory for userns support.
|
||||||
|
// But optional for non-userns support
|
||||||
|
sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
container.HostsPath, err = container.getRootResourcePath("hosts")
|
container.HostsPath, err = container.getRootResourcePath("hosts")
|
||||||
|
@ -947,6 +952,20 @@ func (container *Container) initializeNetworking() error {
|
||||||
return container.buildHostnameFile()
|
return container.buildHostnameFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called from the libcontainer pre-start hook to set the network
|
||||||
|
// namespace configuration linkage to the libnetwork "sandbox" entity
|
||||||
|
func (container *Container) setNetworkNamespaceKey(pid int) error {
|
||||||
|
path := fmt.Sprintf("/proc/%d/ns/net", pid)
|
||||||
|
var sandbox libnetwork.Sandbox
|
||||||
|
search := libnetwork.SandboxContainerWalker(&sandbox, container.ID)
|
||||||
|
container.daemon.netController.WalkSandboxes(search)
|
||||||
|
if sandbox == nil {
|
||||||
|
return fmt.Errorf("no sandbox present for %s", container.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sandbox.SetKey(path)
|
||||||
|
}
|
||||||
|
|
||||||
func (container *Container) getIpcContainer() (*Container, error) {
|
func (container *Container) getIpcContainer() (*Container, error) {
|
||||||
containerID := container.hostConfig.IpcMode.Container()
|
containerID := container.hostConfig.IpcMode.Container()
|
||||||
c, err := container.daemon.Get(containerID)
|
c, err := container.daemon.Get(containerID)
|
||||||
|
|
|
@ -138,6 +138,11 @@ func (container *Container) getSize() (int64, int64) {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setNetworkNamespaceKey is a no-op on Windows.
|
||||||
|
func (container *Container) setNetworkNamespaceKey(pid int) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// allocateNetwork is a no-op on Windows.
|
// allocateNetwork is a no-op on Windows.
|
||||||
func (container *Container) allocateNetwork() error {
|
func (container *Container) allocateNetwork() error {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -875,8 +875,14 @@ func (daemon *Daemon) unmount(container *Container) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) {
|
||||||
return daemon.execDriver.Run(c.command, pipes, startCallback)
|
hooks := execdriver.Hooks{
|
||||||
|
Start: startCallback,
|
||||||
|
}
|
||||||
|
hooks.PreStart = append(hooks.PreStart, func(processConfig *execdriver.ProcessConfig, pid int) error {
|
||||||
|
return c.setNetworkNamespaceKey(pid)
|
||||||
|
})
|
||||||
|
return daemon.execDriver.Run(c.command, pipes, hooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) kill(c *Container, sig int) error {
|
func (daemon *Daemon) kill(c *Container, sig int) error {
|
||||||
|
|
|
@ -267,8 +267,11 @@ func (d *Daemon) ContainerExecStart(execName string, stdin io.ReadCloser, stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec calls the underlying exec driver to run
|
// Exec calls the underlying exec driver to run
|
||||||
func (d *Daemon) Exec(c *Container, ExecConfig *ExecConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
func (d *Daemon) Exec(c *Container, ExecConfig *ExecConfig, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (int, error) {
|
||||||
exitStatus, err := d.execDriver.Exec(c.command, ExecConfig.ProcessConfig, pipes, startCallback)
|
hooks := execdriver.Hooks{
|
||||||
|
Start: startCallback,
|
||||||
|
}
|
||||||
|
exitStatus, err := d.execDriver.Exec(c.command, ExecConfig.ProcessConfig, pipes, hooks)
|
||||||
|
|
||||||
// On err, make sure we don't leave ExitCode at zero
|
// On err, make sure we don't leave ExitCode at zero
|
||||||
if err != nil && exitStatus == 0 {
|
if err != nil && exitStatus == 0 {
|
||||||
|
|
|
@ -24,10 +24,22 @@ var (
|
||||||
ErrDriverNotFound = errors.New("The requested docker init has not been found")
|
ErrDriverNotFound = errors.New("The requested docker init has not been found")
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartCallback defines a callback function.
|
// DriverCallback defines a callback function which is used in "Run" and "Exec".
|
||||||
// It's used by 'Run' and 'Exec', does some work in parent process
|
// This allows work to be done in the parent process when the child is passing
|
||||||
// after child process is started.
|
// through PreStart, Start and PostStop events.
|
||||||
type StartCallback func(*ProcessConfig, int)
|
// Callbacks are provided a processConfig pointer and the pid of the child
|
||||||
|
type DriverCallback func(processConfig *ProcessConfig, pid int) error
|
||||||
|
|
||||||
|
// Hooks is a struct containing function pointers to callbacks
|
||||||
|
// used by any execdriver implementation exploiting hooks capabilities
|
||||||
|
type Hooks struct {
|
||||||
|
// PreStart is called before container's CMD/ENTRYPOINT is executed
|
||||||
|
PreStart []DriverCallback
|
||||||
|
// Start is called after the container's process is full started
|
||||||
|
Start DriverCallback
|
||||||
|
// PostStop is called after the container process exits
|
||||||
|
PostStop []DriverCallback
|
||||||
|
}
|
||||||
|
|
||||||
// Info is driver specific information based on
|
// Info is driver specific information based on
|
||||||
// processes registered with the driver
|
// processes registered with the driver
|
||||||
|
@ -56,11 +68,11 @@ type ExitStatus struct {
|
||||||
type Driver interface {
|
type Driver interface {
|
||||||
// Run executes the process, blocks until the process exits and returns
|
// Run executes the process, blocks until the process exits and returns
|
||||||
// the exit code. It's the last stage on Docker side for running a container.
|
// the exit code. It's the last stage on Docker side for running a container.
|
||||||
Run(c *Command, pipes *Pipes, startCallback StartCallback) (ExitStatus, error)
|
Run(c *Command, pipes *Pipes, hooks Hooks) (ExitStatus, error)
|
||||||
|
|
||||||
// Exec executes the process in an existing container, blocks until the
|
// Exec executes the process in an existing container, blocks until the
|
||||||
// process exits and returns the exit code.
|
// process exits and returns the exit code.
|
||||||
Exec(c *Command, processConfig *ProcessConfig, pipes *Pipes, startCallback StartCallback) (int, error)
|
Exec(c *Command, processConfig *ProcessConfig, pipes *Pipes, hooks Hooks) (int, error)
|
||||||
|
|
||||||
// Kill sends signals to process in container.
|
// Kill sends signals to process in container.
|
||||||
Kill(c *Command, sig int) error
|
Kill(c *Command, sig int) error
|
||||||
|
@ -89,6 +101,9 @@ type Driver interface {
|
||||||
|
|
||||||
// Stats returns resource stats for a running container
|
// Stats returns resource stats for a running container
|
||||||
Stats(id string) (*ResourceStats, error)
|
Stats(id string) (*ResourceStats, error)
|
||||||
|
|
||||||
|
// SupportsHooks refers to the driver capability to exploit pre/post hook functionality
|
||||||
|
SupportsHooks() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ipc settings of the container
|
// Ipc settings of the container
|
||||||
|
|
|
@ -125,7 +125,7 @@ func killNetNsProc(proc *os.Process) {
|
||||||
|
|
||||||
// Run implements the exec driver Driver interface,
|
// Run implements the exec driver Driver interface,
|
||||||
// it calls 'exec.Cmd' to launch lxc commands to run a container.
|
// it calls 'exec.Cmd' to launch lxc commands to run a container.
|
||||||
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execdriver.Hooks) (execdriver.ExitStatus, error) {
|
||||||
var (
|
var (
|
||||||
term execdriver.Terminal
|
term execdriver.Terminal
|
||||||
err error
|
err error
|
||||||
|
@ -324,9 +324,9 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
|
|
||||||
c.ContainerPid = pid
|
c.ContainerPid = pid
|
||||||
|
|
||||||
if startCallback != nil {
|
if hooks.Start != nil {
|
||||||
logrus.Debugf("Invoking startCallback")
|
logrus.Debugf("Invoking startCallback")
|
||||||
startCallback(&c.ProcessConfig, pid)
|
hooks.Start(&c.ProcessConfig, pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
oomKill := false
|
oomKill := false
|
||||||
|
@ -870,7 +870,7 @@ func (t *TtyConsole) Close() error {
|
||||||
|
|
||||||
// Exec implements the exec driver Driver interface,
|
// Exec implements the exec driver Driver interface,
|
||||||
// it is not implemented by lxc.
|
// it is not implemented by lxc.
|
||||||
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) {
|
||||||
return -1, ErrExec
|
return -1, ErrExec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,3 +883,9 @@ func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
||||||
}
|
}
|
||||||
return execdriver.Stats(d.containerDir(id), d.activeContainers[id].container.Cgroups.Memory, d.machineMemory)
|
return execdriver.Stats(d.containerDir(id), d.activeContainers[id].container.Cgroups.Memory, d.machineMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportsHooks implements the execdriver Driver interface.
|
||||||
|
// The LXC execdriver does not support the hook mechanism, which is currently unique to runC/libcontainer.
|
||||||
|
func (d *Driver) SupportsHooks() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
// createContainer populates and configures the container type with the
|
// createContainer populates and configures the container type with the
|
||||||
// data provided by the execdriver.Command
|
// data provided by the execdriver.Command
|
||||||
func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
|
func (d *Driver) createContainer(c *execdriver.Command, hooks execdriver.Hooks) (*configs.Config, error) {
|
||||||
container := execdriver.InitContainer(c)
|
container := execdriver.InitContainer(c)
|
||||||
|
|
||||||
if err := d.createIpc(container, c); err != nil {
|
if err := d.createIpc(container, c); err != nil {
|
||||||
|
@ -33,7 +33,7 @@ func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.createNetwork(container, c); err != nil {
|
if err := d.createNetwork(container, c, hooks); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ func generateIfaceName() (string, error) {
|
||||||
return "", errors.New("Failed to find name for new interface")
|
return "", errors.New("Failed to find name for new interface")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
|
func (d *Driver) createNetwork(container *configs.Config, c *execdriver.Command, hooks execdriver.Hooks) error {
|
||||||
if c.Network == nil {
|
if c.Network == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -135,11 +135,26 @@ func (d *Driver) createNetwork(container *configs.Config, c *execdriver.Command)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Network.NamespacePath == "" {
|
if c.Network.NamespacePath != "" {
|
||||||
return fmt.Errorf("network namespace path is empty")
|
container.Namespaces.Add(configs.NEWNET, c.Network.NamespacePath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// only set up prestart hook if the namespace path is not set (this should be
|
||||||
|
// all cases *except* for --net=host shared networking)
|
||||||
|
container.Hooks = &configs.Hooks{
|
||||||
|
Prestart: []configs.Hook{
|
||||||
|
configs.NewFunctionHook(func(s configs.HookState) error {
|
||||||
|
if len(hooks.PreStart) > 0 {
|
||||||
|
for _, fnHook := range hooks.PreStart {
|
||||||
|
if err := fnHook(&c.ProcessConfig, s.Pid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
container.Namespaces.Add(configs.NEWNET, c.Network.NamespacePath)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,9 +131,9 @@ type execOutput struct {
|
||||||
|
|
||||||
// Run implements the exec driver Driver interface,
|
// Run implements the exec driver Driver interface,
|
||||||
// it calls libcontainer APIs to run a container.
|
// it calls libcontainer APIs to run a container.
|
||||||
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execdriver.Hooks) (execdriver.ExitStatus, error) {
|
||||||
// take the Command and populate the libcontainer.Config from it
|
// take the Command and populate the libcontainer.Config from it
|
||||||
container, err := d.createContainer(c)
|
container, err := d.createContainer(c, hooks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||||
}
|
}
|
||||||
|
@ -165,14 +165,14 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if startCallback != nil {
|
if hooks.Start != nil {
|
||||||
pid, err := p.Pid()
|
pid, err := p.Pid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Signal(os.Kill)
|
p.Signal(os.Kill)
|
||||||
p.Wait()
|
p.Wait()
|
||||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||||
}
|
}
|
||||||
startCallback(&c.ProcessConfig, pid)
|
hooks.Start(&c.ProcessConfig, pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
oom := notifyOnOOM(cont)
|
oom := notifyOnOOM(cont)
|
||||||
|
@ -477,3 +477,9 @@ func setupPipes(container *configs.Config, processConfig *execdriver.ProcessConf
|
||||||
processConfig.Terminal = term
|
processConfig.Terminal = term
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportsHooks implements the execdriver Driver interface.
|
||||||
|
// The libcontainer/runC-based native execdriver does exploit the hook mechanism
|
||||||
|
func (d *Driver) SupportsHooks() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
|
|
||||||
// Exec implements the exec driver Driver interface,
|
// Exec implements the exec driver Driver interface,
|
||||||
// it calls libcontainer APIs to execute a container.
|
// it calls libcontainer APIs to execute a container.
|
||||||
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) {
|
||||||
active := d.activeContainers[c.ID]
|
active := d.activeContainers[c.ID]
|
||||||
if active == nil {
|
if active == nil {
|
||||||
return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
|
return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
|
||||||
|
@ -45,14 +45,14 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if startCallback != nil {
|
if hooks.Start != nil {
|
||||||
pid, err := p.Pid()
|
pid, err := p.Pid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Signal(os.Kill)
|
p.Signal(os.Kill)
|
||||||
p.Wait()
|
p.Wait()
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
startCallback(&c.ProcessConfig, pid)
|
hooks.Start(&c.ProcessConfig, pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
ps, err := p.Wait()
|
ps, err := p.Wait()
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Exec implements the exec driver Driver interface.
|
// Exec implements the exec driver Driver interface.
|
||||||
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
term execdriver.Terminal
|
term execdriver.Terminal
|
||||||
|
@ -69,8 +69,8 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
processConfig.Terminal = term
|
processConfig.Terminal = term
|
||||||
|
|
||||||
// Invoke the start callback
|
// Invoke the start callback
|
||||||
if startCallback != nil {
|
if hooks.Start != nil {
|
||||||
startCallback(&c.ProcessConfig, int(pid))
|
hooks.Start(&c.ProcessConfig, int(pid))
|
||||||
}
|
}
|
||||||
|
|
||||||
if exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid); err != nil {
|
if exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid); err != nil {
|
||||||
|
|
|
@ -77,7 +77,7 @@ type containerInit struct {
|
||||||
const defaultOwner = "docker"
|
const defaultOwner = "docker"
|
||||||
|
|
||||||
// Run implements the exec driver Driver interface
|
// Run implements the exec driver Driver interface
|
||||||
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execdriver.Hooks) (execdriver.ExitStatus, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
term execdriver.Terminal
|
term execdriver.Terminal
|
||||||
|
@ -290,9 +290,8 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
}
|
}
|
||||||
d.Unlock()
|
d.Unlock()
|
||||||
|
|
||||||
// Invoke the start callback
|
if hooks.Start != nil {
|
||||||
if startCallback != nil {
|
hooks.Start(&c.ProcessConfig, int(pid))
|
||||||
startCallback(&c.ProcessConfig, int(pid))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var exitCode int32
|
var exitCode int32
|
||||||
|
@ -305,3 +304,9 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
|
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
|
||||||
return execdriver.ExitStatus{ExitCode: int(exitCode)}, nil
|
return execdriver.ExitStatus{ExitCode: int(exitCode)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportsHooks implements the execdriver Driver interface.
|
||||||
|
// The windows driver does not support the hook mechanism
|
||||||
|
func (d *Driver) SupportsHooks() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -250,7 +250,7 @@ func (m *containerMonitor) shouldRestart(exitCode int) bool {
|
||||||
|
|
||||||
// callback ensures that the container's state is properly updated after we
|
// callback ensures that the container's state is properly updated after we
|
||||||
// received ack from the execution drivers
|
// received ack from the execution drivers
|
||||||
func (m *containerMonitor) callback(processConfig *execdriver.ProcessConfig, pid int) {
|
func (m *containerMonitor) callback(processConfig *execdriver.ProcessConfig, pid int) error {
|
||||||
if processConfig.Tty {
|
if processConfig.Tty {
|
||||||
// The callback is called after the process Start()
|
// The callback is called after the process Start()
|
||||||
// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave
|
// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlave
|
||||||
|
@ -273,6 +273,7 @@ func (m *containerMonitor) callback(processConfig *execdriver.ProcessConfig, pid
|
||||||
if err := m.container.toDiskLocking(); err != nil {
|
if err := m.container.toDiskLocking(); err != nil {
|
||||||
logrus.Errorf("Error saving container to disk: %v", err)
|
logrus.Errorf("Error saving container to disk: %v", err)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetContainer resets the container's IO and ensures that the command is able to be executed again
|
// resetContainer resets the container's IO and ensures that the command is able to be executed again
|
||||||
|
|
Loading…
Add table
Reference in a new issue