Skip to content

Commit

Permalink
Volumes refactor and external plugin implementation.
Browse files Browse the repository at this point in the history
Signed by all authors:

Signed-off-by: Michael Crosby <[email protected]>
Signed-off-by: Arnaud Porterie <[email protected]>
Signed-off-by: David Calavera <[email protected]>
Signed-off-by: Jeff Lindsay <[email protected]>
Signed-off-by: Alexander Morozov <[email protected]>
Signed-off-by: Luke Marsden <[email protected]>
Signed-off-by: David Calavera <[email protected]>
  • Loading branch information
calavera committed May 22, 2015
1 parent 23e8dff commit 81fa9fe
Show file tree
Hide file tree
Showing 43 changed files with 1,527 additions and 1,180 deletions.
17 changes: 2 additions & 15 deletions api/client/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"path/filepath"
"reflect"
"strings"
"text/template"
"time"

"github.com/docker/docker/cliconfig"
"github.com/docker/docker/pkg/homedir"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/utils"
)

// DockerCli represents the docker command line client.
Expand Down Expand Up @@ -178,19 +177,7 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, a
tr := &http.Transport{
TLSClientConfig: tlsConfig,
}

// Why 32? See https://github.com/docker/docker/pull/8035.
timeout := 32 * time.Second
if proto == "unix" {
// No need for compression in local communications.
tr.DisableCompression = true
tr.Dial = func(_, _ string) (net.Conn, error) {
return net.DialTimeout(proto, addr, timeout)
}
} else {
tr.Proxy = http.ProxyFromEnvironment
tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
}
utils.ConfigureTCPTransport(tr, proto, addr)

configFile, e := cliconfig.Load(filepath.Join(homedir.Get(), ".docker"))
if e != nil {
Expand Down
2 changes: 1 addition & 1 deletion builder/internals.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ func (b *Builder) clearTmp() {
fmt.Fprintf(b.OutStream, "Error removing intermediate container %s: %v\n", stringid.TruncateID(c), err)
return
}
b.Daemon.DeleteVolumes(tmp.VolumePaths())
b.Daemon.DeleteVolumes(tmp)
delete(b.TmpContainers, c)
fmt.Fprintf(b.OutStream, "Removing intermediate container %s\n", stringid.TruncateID(c))
}
Expand Down
169 changes: 126 additions & 43 deletions daemon/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ import (
"github.com/docker/docker/pkg/broadcastwriter"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/jsonlog"
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
)

var (
Expand All @@ -48,46 +50,37 @@ type StreamConfig struct {
// CommonContainer holds the settings for a container which are applicable
// across all platforms supported by the daemon.
type CommonContainer struct {
StreamConfig

*State `json:"State"` // Needed for remote api version <= 1.11
root string // Path to the "home" of the container, including metadata.
basefs string // Path to the graphdriver mountpoint

ID string

Created time.Time

Path string
Args []string

Config *runconfig.Config
ImageID string `json:"Image"`

NetworkSettings *network.Settings

ResolvConfPath string
HostnamePath string
HostsPath string
LogPath string
Name string
Driver string
ExecDriver string

command *execdriver.Command
StreamConfig

daemon *Daemon
ID string
Created time.Time
Path string
Args []string
Config *runconfig.Config
ImageID string `json:"Image"`
NetworkSettings *network.Settings
ResolvConfPath string
HostnamePath string
HostsPath string
LogPath string
Name string
Driver string
ExecDriver string
MountLabel, ProcessLabel string
RestartCount int
UpdateDns bool
MountPoints map[string]*mountPoint

// Maps container paths to volume paths. The key in this is the path to which
// the volume is being mounted inside the container. Value is the path of the
// volume on disk
Volumes map[string]string
hostConfig *runconfig.HostConfig
command *execdriver.Command

monitor *containerMonitor
execCommands *execStore
daemon *Daemon
// logDriver for closing
logDriver logger.Logger
logCopier *logger.Copier
Expand Down Expand Up @@ -259,9 +252,6 @@ func (container *Container) Start() (err error) {
return err
}
container.verifyDaemonSettings()
if err := container.prepareVolumes(); err != nil {
return err
}
linkedEnv, err := container.setupLinkedContainers()
if err != nil {
return err
Expand All @@ -273,10 +263,13 @@ func (container *Container) Start() (err error) {
if err := populateCommand(container, env); err != nil {
return err
}
if err := container.setupMounts(); err != nil {

mounts, err := container.setupMounts()
if err != nil {
return err
}

container.command.Mounts = mounts
return container.waitForStart()
}

Expand Down Expand Up @@ -571,27 +564,38 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) {
if err := container.Mount(); err != nil {
return nil, err
}
var paths []string
unmount := func() {
for _, p := range paths {
syscall.Unmount(p, 0)
}
}
defer func() {
if err != nil {
// unmount any volumes
unmount()
// unmount the container's rootfs
container.Unmount()
}
}()

if err = container.mountVolumes(); err != nil {
container.unmountVolumes()
mounts, err := container.setupMounts()
if err != nil {
return nil, err
}
defer func() {
for _, m := range mounts {
dest, err := container.GetResourcePath(m.Destination)
if err != nil {
container.unmountVolumes()
return nil, err
}
}()

paths = append(paths, dest)
if err := mount.Mount(m.Source, dest, "bind", "rbind,ro"); err != nil {
return nil, err
}
}
basePath, err := container.GetResourcePath(resource)
if err != nil {
return nil, err
}

stat, err := os.Stat(basePath)
if err != nil {
return nil, err
Expand All @@ -605,18 +609,16 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) {
filter = []string{filepath.Base(basePath)}
basePath = filepath.Dir(basePath)
}

archive, err := archive.TarWithOptions(basePath, &archive.TarOptions{
Compression: archive.Uncompressed,
IncludeFiles: filter,
})
if err != nil {
return nil, err
}

return ioutils.NewReadCloserWrapper(archive, func() error {
err := archive.Close()
container.unmountVolumes()
unmount()
container.Unmount()
return err
}),
Expand Down Expand Up @@ -1007,3 +1009,84 @@ func copyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error)
}
return written, err
}

func (container *Container) networkMounts() []execdriver.Mount {
var mounts []execdriver.Mount
if container.ResolvConfPath != "" {
mounts = append(mounts, execdriver.Mount{
Source: container.ResolvConfPath,
Destination: "/etc/resolv.conf",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
if container.HostnamePath != "" {
mounts = append(mounts, execdriver.Mount{
Source: container.HostnamePath,
Destination: "/etc/hostname",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
if container.HostsPath != "" {
mounts = append(mounts, execdriver.Mount{
Source: container.HostsPath,
Destination: "/etc/hosts",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
return mounts
}

func (container *Container) AddLocalMountPoint(name, destination string, rw bool) {
container.MountPoints[destination] = &mountPoint{
Name: name,
Driver: volume.DefaultDriverName,
Destination: destination,
RW: rw,
}
}

func (container *Container) AddMountPointWithVolume(destination string, vol volume.Volume, rw bool) {
container.MountPoints[destination] = &mountPoint{
Name: vol.Name(),
Driver: vol.DriverName(),
Destination: destination,
RW: rw,
Volume: vol,
}
}

func (container *Container) IsDestinationMounted(destination string) bool {
return container.MountPoints[destination] != nil
}

func (container *Container) PrepareMountPoints() error {
for _, config := range container.MountPoints {
if len(config.Driver) > 0 {
v, err := createVolume(config.Name, config.Driver)
if err != nil {
return err
}
config.Volume = v
}
}
return nil
}

func (container *Container) RemoveMountPoints() error {
for _, m := range container.MountPoints {
if m.Volume != nil {
if err := removeVolume(m.Volume); err != nil {
return err
}
}
}
return nil
}

func (container *Container) ShouldRestart() bool {
return container.hostConfig.RestartPolicy.Name == "always" ||
(container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0)
}
9 changes: 1 addition & 8 deletions daemon/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,7 @@ type Container struct {
// Fields below here are platform specific.

AppArmorProfile string

// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
// Easier than migrating older container configs :)
VolumesRW map[string]bool

AppliedVolumesFrom map[string]struct{}

activeLinks map[string]*links.Link
activeLinks map[string]*links.Link
}

func killProcessDirectly(container *Container) error {
Expand Down
6 changes: 0 additions & 6 deletions daemon/container_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ type Container struct {
// removed in subsequent PRs.

AppArmorProfile string

// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
// Easier than migrating older container configs :)
VolumesRW map[string]bool

AppliedVolumesFrom map[string]struct{}
// ---- END OF TEMPORARY DECLARATION ----

}
Expand Down
Loading

0 comments on commit 81fa9fe

Please sign in to comment.