diff --git a/daemon/archive.go b/daemon/archive.go index 61196c91f5..f4a82478d9 100644 --- a/daemon/archive.go +++ b/daemon/archive.go @@ -142,7 +142,7 @@ func (daemon *Daemon) containerStatPath(container *Container, path string) (stat } defer daemon.Unmount(container) - err = container.mountVolumes() + err = daemon.mountVolumes(container) defer container.unmountVolumes(true) if err != nil { return nil, err @@ -184,7 +184,7 @@ func (daemon *Daemon) containerArchivePath(container *Container, path string) (c } }() - if err = container.mountVolumes(); err != nil { + if err = daemon.mountVolumes(container); err != nil { return nil, nil, err } @@ -239,7 +239,7 @@ func (daemon *Daemon) containerExtractToDir(container *Container, path string, n } defer daemon.Unmount(container) - err = container.mountVolumes() + err = daemon.mountVolumes(container) defer container.unmountVolumes(true) if err != nil { return err @@ -348,7 +348,7 @@ func (daemon *Daemon) containerCopy(container *Container, resource string) (rc i } }() - if err := container.mountVolumes(); err != nil { + if err := daemon.mountVolumes(container); err != nil { return nil, err } diff --git a/daemon/container.go b/daemon/container.go index b02f139473..bc132af2a3 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -498,8 +498,8 @@ func (container *Container) shouldRestart() bool { (container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0) } -func (container *Container) mountVolumes() error { - mounts, err := container.setupMounts() +func (daemon *Daemon) mountVolumes(container *Container) error { + mounts, err := daemon.setupMounts(container) if err != nil { return err } diff --git a/daemon/container_unix.go b/daemon/container_unix.go index d47647412b..a4b9cd5a6d 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -744,14 +744,14 @@ func (daemon *Daemon) updateNetworkSettings(container *Container, n libnetwork.N return nil } -func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error { +func (daemon *Daemon) updateEndpointNetworkSettings(container *Container, n libnetwork.Network, ep libnetwork.Endpoint) error { networkSettings, err := container.buildEndpointInfo(n, ep, container.NetworkSettings) if err != nil { return err } if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") { - networkSettings.Bridge = container.daemon.configStore.Bridge.Iface + networkSettings.Bridge = daemon.configStore.Bridge.Iface } return nil @@ -1006,7 +1006,7 @@ func (daemon *Daemon) connectToNetwork(container *Container, idOrName string, up } }() - if err := container.updateEndpointNetworkSettings(n, ep); err != nil { + if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } @@ -1075,13 +1075,13 @@ func (daemon *Daemon) initializeNetworking(container *Container) error { // called from the libcontainer pre-start hook to set the network // namespace configuration linkage to the libnetwork "sandbox" entity -func (daemon *Daemon) setNetworkNamespaceKey(containerId string, pid int) error { +func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error { path := fmt.Sprintf("/proc/%d/ns/net", pid) var sandbox libnetwork.Sandbox - search := libnetwork.SandboxContainerWalker(&sandbox, containerId) + search := libnetwork.SandboxContainerWalker(&sandbox, containerID) daemon.netController.WalkSandboxes(search) if sandbox == nil { - return derr.ErrorCodeNoSandbox.WithArgs(containerId) + return derr.ErrorCodeNoSandbox.WithArgs(containerID) } return sandbox.SetKey(path) @@ -1126,16 +1126,16 @@ func (container *Container) setupWorkingDirectory() error { return nil } -func (daemon *Daemon) getNetworkedContainer(containerId, connectedContainerId string) (*Container, error) { - nc, err := daemon.Get(connectedContainerId) +func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*Container, error) { + nc, err := daemon.Get(connectedContainerID) if err != nil { return nil, err } - if containerId == nc.ID { + if containerID == nc.ID { return nil, derr.ErrorCodeJoinSelf } if !nc.IsRunning() { - return nil, derr.ErrorCodeJoinRunning.WithArgs(connectedContainerId) + return nil, derr.ErrorCodeJoinRunning.WithArgs(connectedContainerID) } return nc, nil } diff --git a/daemon/container_windows.go b/daemon/container_windows.go index 4029848911..fd2dcb9bdf 100644 --- a/daemon/container_windows.go +++ b/daemon/container_windows.go @@ -149,7 +149,7 @@ func (daemon *Daemon) getSize(container *Container) (int64, int64) { } // setNetworkNamespaceKey is a no-op on Windows. -func (daemon *Daemon) setNetworkNamespaceKey(containerId string, pid int) error { +func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error { return nil } diff --git a/daemon/create.go b/daemon/create.go index b27a20eed4..aaf0f1329b 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -119,7 +119,7 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re } defer daemon.Unmount(container) - if err := createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil { + if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil { return nil, err } diff --git a/daemon/create_unix.go b/daemon/create_unix.go index 66138db967..4d84997e93 100644 --- a/daemon/create_unix.go +++ b/daemon/create_unix.go @@ -15,7 +15,7 @@ import ( ) // createContainerPlatformSpecificSettings performs platform specific container create functionality -func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { +func (daemon *Daemon) createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { for spec := range config.Volumes { name := stringid.GenerateNonCryptoID() destination := filepath.Clean(spec) @@ -45,7 +45,7 @@ func createContainerPlatformSpecificSettings(container *Container, config *runco } } - v, err := container.daemon.createVolume(name, volumeDriver, nil) + v, err := daemon.createVolume(name, volumeDriver, nil) if err != nil { return err } diff --git a/daemon/create_windows.go b/daemon/create_windows.go index 1ea465f71c..a95e667b74 100644 --- a/daemon/create_windows.go +++ b/daemon/create_windows.go @@ -10,7 +10,7 @@ import ( ) // createContainerPlatformSpecificSettings performs platform specific container create functionality -func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { +func (daemon *Daemon) createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { for spec := range config.Volumes { mp, err := volume.ParseMountSpec(spec, hostConfig.VolumeDriver) @@ -41,7 +41,7 @@ func createContainerPlatformSpecificSettings(container *Container, config *runco // Create the volume in the volume driver. If it doesn't exist, // a new one will be created. - v, err := container.daemon.createVolume(mp.Name, volumeDriver, nil) + v, err := daemon.createVolume(mp.Name, volumeDriver, nil) if err != nil { return err } diff --git a/daemon/daemon.go b/daemon/daemon.go index de9a1157c2..13e3f33103 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -194,7 +194,7 @@ func (daemon *Daemon) load(id string) (*Container, error) { // Register makes a container object usable by the daemon as func (daemon *Daemon) Register(container *Container) error { - if container.daemon != nil || daemon.Exists(container.ID) { + if daemon.Exists(container.ID) { return fmt.Errorf("Container is already loaded") } if err := validateID(container.ID); err != nil { @@ -204,8 +204,6 @@ func (daemon *Daemon) Register(container *Container) error { return err } - container.daemon = daemon - // Attach to stdout and stderr container.stderr = new(broadcaster.Unbuffered) container.stdout = new(broadcaster.Unbuffered) @@ -954,7 +952,8 @@ func (daemon *Daemon) Unmount(container *Container) error { return daemon.driver.Put(container.ID) } -func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) { +// Run uses the execution driver to run a given container +func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) { hooks := execdriver.Hooks{ Start: startCallback, } @@ -1303,6 +1302,12 @@ func (daemon *Daemon) SearchRegistryForImages(term string, return daemon.RegistryService.Search(term, authConfig, headers) } +// IsShuttingDown tells whether the daemon is shutting down or not +func (daemon *Daemon) IsShuttingDown() bool { + return daemon.shutdown +} + +// GetContainerStats collects all the stats published by a container func (daemon *Daemon) GetContainerStats(container *Container) (*execdriver.ResourceStats, error) { stats, err := daemon.stats(container) if err != nil { diff --git a/daemon/exec.go b/daemon/exec.go index 6ebacd6643..bf0335ee49 100644 --- a/daemon/exec.go +++ b/daemon/exec.go @@ -331,7 +331,7 @@ func (d *Daemon) containerExecIds() map[string]struct{} { return ids } -func (daemon *Daemon) containerExec(container *Container, ec *ExecConfig) error { +func (d *Daemon) containerExec(container *Container, ec *ExecConfig) error { container.Lock() defer container.Unlock() @@ -350,7 +350,7 @@ func (daemon *Daemon) containerExec(container *Container, ec *ExecConfig) error // We use a callback here instead of a goroutine and an chan for // synchronization purposes - cErr := promise.Go(func() error { return daemon.monitorExec(container, ec, callback) }) + cErr := promise.Go(func() error { return d.monitorExec(container, ec, callback) }) // Exec should not return until the process is actually running select { @@ -362,13 +362,13 @@ func (daemon *Daemon) containerExec(container *Container, ec *ExecConfig) error return nil } -func (daemon *Daemon) monitorExec(container *Container, ExecConfig *ExecConfig, callback execdriver.DriverCallback) error { +func (d *Daemon) monitorExec(container *Container, ExecConfig *ExecConfig, callback execdriver.DriverCallback) error { var ( err error exitCode int ) pipes := execdriver.NewPipes(ExecConfig.streamConfig.stdin, ExecConfig.streamConfig.stdout, ExecConfig.streamConfig.stderr, ExecConfig.OpenStdin) - exitCode, err = daemon.Exec(container, ExecConfig, pipes, callback) + exitCode, err = d.Exec(container, ExecConfig, pipes, callback) if err != nil { logrus.Errorf("Error running command in existing container %s: %s", container.ID, err) } diff --git a/daemon/monitor.go b/daemon/monitor.go index 4f37d0ef12..fa89d1d6c7 100644 --- a/daemon/monitor.go +++ b/daemon/monitor.go @@ -25,6 +25,10 @@ type containerSupervisor interface { Cleanup(*Container) // StartLogging starts the logging driver for the container StartLogging(*Container) error + // Run starts a container + Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) + // IsShuttingDown tells whether the supervisor is shutting down or not + IsShuttingDown() bool } // containerMonitor monitors the execution of a container's main process. @@ -156,7 +160,7 @@ func (m *containerMonitor) Start() error { m.lastStartTime = time.Now() - if exitStatus, err = m.container.daemon.run(m.container, pipes, m.callback); err != nil { + if exitStatus, err = m.supervisor.Run(m.container, pipes, m.callback); err != nil { // if we receive an internal error from the initial start of a container then lets // return it instead of entering the restart loop if m.container.RestartCount == 0 { @@ -236,7 +240,7 @@ func (m *containerMonitor) shouldRestart(exitCode int) bool { // do not restart if the user or docker has requested that this container be stopped if m.shouldStop { - m.container.HasBeenManuallyStopped = !m.container.daemon.shutdown + m.container.HasBeenManuallyStopped = !m.supervisor.IsShuttingDown() return false } diff --git a/daemon/mounts.go b/daemon/mounts.go index 91d5c0953c..9d195fa8ae 100644 --- a/daemon/mounts.go +++ b/daemon/mounts.go @@ -26,7 +26,7 @@ func (daemon *Daemon) removeMountPoints(container *Container, rm bool) error { if m.Volume == nil { continue } - container.daemon.volumes.Decrement(m.Volume) + daemon.volumes.Decrement(m.Volume) if rm { err := daemon.volumes.Remove(m.Volume) // ErrVolumeInUse is ignored because having this diff --git a/daemon/start.go b/daemon/start.go index 2943133b96..8fe2fa84dd 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -118,7 +118,7 @@ func (daemon *Daemon) containerStart(container *Container) (err error) { } } - mounts, err := container.setupMounts() + mounts, err := daemon.setupMounts(container) if err != nil { return err } diff --git a/daemon/stats_collector_windows.go b/daemon/stats_collector_windows.go index f16d7ee380..e63f37b0d6 100644 --- a/daemon/stats_collector_windows.go +++ b/daemon/stats_collector_windows.go @@ -6,7 +6,7 @@ import "time" // for a registered container at the specified interval. The collector allows // non-running containers to be added and will start processing stats when // they are started. -func newStatsCollector(interval time.Duration) *statsCollector { +func (daemon *Daemon) newStatsCollector(interval time.Duration) *statsCollector { return &statsCollector{} } diff --git a/daemon/volumes_unix.go b/daemon/volumes_unix.go index b2a3c27b67..a7ac991105 100644 --- a/daemon/volumes_unix.go +++ b/daemon/volumes_unix.go @@ -58,7 +58,7 @@ func copyOwnership(source, destination string) error { // setupMounts iterates through each of the mount points for a container and // calls Setup() on each. It also looks to see if is a network mount such as // /etc/resolv.conf, and if it is not, appends it to the array of mounts. -func (container *Container) setupMounts() ([]execdriver.Mount, error) { +func (daemon *Daemon) setupMounts(container *Container) ([]execdriver.Mount, error) { var mounts []execdriver.Mount for _, m := range container.MountPoints { path, err := m.Setup() @@ -79,7 +79,7 @@ func (container *Container) setupMounts() ([]execdriver.Mount, error) { // if we are going to mount any of the network files from container // metadata, the ownership must be set properly for potential container // remapped root (user namespaces) - rootUID, rootGID := container.daemon.GetRemappedUIDGID() + rootUID, rootGID := daemon.GetRemappedUIDGID() for _, mount := range netMounts { if err := os.Chown(mount.Source, rootUID, rootGID); err != nil { return nil, err diff --git a/daemon/volumes_windows.go b/daemon/volumes_windows.go index 5c6182da53..73ec171902 100644 --- a/daemon/volumes_windows.go +++ b/daemon/volumes_windows.go @@ -3,17 +3,18 @@ package daemon import ( + "sort" + "github.com/docker/docker/daemon/execdriver" derr "github.com/docker/docker/errors" "github.com/docker/docker/volume" - "sort" ) // setupMounts configures the mount points for a container by appending each // of the configured mounts on the container to the execdriver mount structure // which will ultimately be passed into the exec driver during container creation. // It also ensures each of the mounts are lexographically sorted. -func (container *Container) setupMounts() ([]execdriver.Mount, error) { +func (daemon *Daemon) setupMounts(container *Container) ([]execdriver.Mount, error) { var mnts []execdriver.Mount for _, mount := range container.MountPoints { // type is volume.MountPoint // If there is no source, take it from the volume path