Windows: Factoring out unused fields

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2015-07-16 14:14:58 -07:00
parent 33358f80e5
commit 47c56e4353
26 changed files with 649 additions and 544 deletions

View File

@ -1205,12 +1205,8 @@ func (s *Server) getContainersByName(version version.Version, w http.ResponseWri
return fmt.Errorf("Missing parameter") return fmt.Errorf("Missing parameter")
} }
if version.LessThan("1.20") { if version.LessThan("1.20") && runtime.GOOS != "windows" {
containerJSONRaw, err := s.daemon.ContainerInspectPre120(vars["name"]) return getContainersByNameDownlevel(w, s, vars["name"])
if err != nil {
return err
}
return writeJSON(w, http.StatusOK, containerJSONRaw)
} }
containerJSON, err := s.daemon.ContainerInspect(vars["name"]) containerJSON, err := s.daemon.ContainerInspect(vars["name"])

View File

@ -121,3 +121,13 @@ func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig)
} }
} }
} }
// getContainersByNameDownlevel performs processing for pre 1.20 APIs. This
// is only relevant on non-Windows daemons.
func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error {
containerJSONRaw, err := s.daemon.ContainerInspectPre120(namevar)
if err != nil {
return err
}
return writeJSON(w, http.StatusOK, containerJSONRaw)
}

View File

@ -60,3 +60,9 @@ func allocateDaemonPort(addr string) error {
func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) { func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) {
} }
// getContainersByNameDownlevel performs processing for pre 1.20 APIs. This
// is only relevant on non-Windows daemons.
func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error {
return nil
}

View File

@ -250,7 +250,8 @@ type ContainerJSON struct {
Config *runconfig.Config Config *runconfig.Config
} }
// backcompatibility struct along with ContainerConfig // backcompatibility struct along with ContainerConfig. Note this is not
// used by the Windows daemon.
type ContainerJSONPre120 struct { type ContainerJSONPre120 struct {
*ContainerJSONBase *ContainerJSONBase
Volumes map[string]string Volumes map[string]string

View File

@ -17,7 +17,7 @@ import (
// path does not refer to a directory. // path does not refer to a directory.
var ErrExtractPointNotDirectory = errors.New("extraction point is not a directory") var ErrExtractPointNotDirectory = errors.New("extraction point is not a directory")
// ContainerCopy performs a depracated operation of archiving the resource at // ContainerCopy performs a deprecated operation of archiving the resource at
// the specified path in the conatiner identified by the given name. // the specified path in the conatiner identified by the given name.
func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, error) { func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, error) {
container, err := daemon.Get(name) container, err := daemon.Get(name)
@ -25,7 +25,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err
return nil, err return nil, err
} }
if res[0] == '/' { if res[0] == '/' || res[0] == '\\' {
res = res[1:] res = res[1:]
} }
@ -90,7 +90,7 @@ func (container *Container) StatPath(path string) (stat *types.ContainerPathStat
// Consider the given path as an absolute path in the container. // Consider the given path as an absolute path in the container.
absPath := path absPath := path
if !filepath.IsAbs(absPath) { if !filepath.IsAbs(absPath) {
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join("/", path), path) absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join(string(os.PathSeparator), path), path)
} }
resolvedPath, err := container.GetResourcePath(absPath) resolvedPath, err := container.GetResourcePath(absPath)
@ -157,7 +157,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta
// Consider the given path as an absolute path in the container. // Consider the given path as an absolute path in the container.
absPath := path absPath := path
if !filepath.IsAbs(absPath) { if !filepath.IsAbs(absPath) {
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join("/", path), path) absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join(string(os.PathSeparator), path), path)
} }
resolvedPath, err := container.GetResourcePath(absPath) resolvedPath, err := container.GetResourcePath(absPath)
@ -230,7 +230,7 @@ func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool,
// Consider the given path as an absolute path in the container. // Consider the given path as an absolute path in the container.
absPath := path absPath := path
if !filepath.IsAbs(absPath) { if !filepath.IsAbs(absPath) {
absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join("/", path), path) absPath = archive.PreserveTrailingDotOrSeparator(filepath.Join(string(os.PathSeparator), path), path)
} }
resolvedPath, err := container.GetResourcePath(absPath) resolvedPath, err := container.GetResourcePath(absPath)
@ -261,19 +261,14 @@ func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool,
if err != nil { if err != nil {
return err return err
} }
absPath = filepath.Join("/", baseRel) absPath = filepath.Join(string(os.PathSeparator), baseRel)
// Need to check if the path is in a volume. If it is, it cannot be in a // Need to check if the path is in a volume. If it is, it cannot be in a
// read-only volume. If it is not in a volume, the container cannot be // read-only volume. If it is not in a volume, the container cannot be
// configured with a read-only rootfs. // configured with a read-only rootfs.
var toVolume bool toVolume, err := checkIfPathIsInAVolume(container, absPath)
for _, mnt := range container.MountPoints { if err != nil {
if toVolume = mnt.hasResource(absPath); toVolume { return err
if mnt.RW {
break
}
return ErrVolumeReadonly
}
} }
if !toVolume && container.hostConfig.ReadonlyRootfs { if !toVolume && container.hostConfig.ReadonlyRootfs {

19
daemon/archive_unix.go Normal file
View File

@ -0,0 +1,19 @@
// +build !windows
package daemon
// checkIfPathIsInAVolume checks if the path is in a volume. If it is, it
// cannot be in a read-only volume. If it is not in a volume, the container
// cannot be configured with a read-only rootfs.
func checkIfPathIsInAVolume(container *Container, absPath string) (bool, error) {
var toVolume bool
for _, mnt := range container.MountPoints {
if toVolume = mnt.hasResource(absPath); toVolume {
if mnt.RW {
break
}
return false, ErrVolumeReadonly
}
}
return toVolume, nil
}

10
daemon/archive_windows.go Normal file
View File

@ -0,0 +1,10 @@
package daemon
// checkIfPathIsInAVolume checks if the path is in a volume. If it is, it
// cannot be in a read-only volume. If it is not in a volume, the container
// cannot be configured with a read-only rootfs.
//
// This is a no-op on Windows which does not support volumes.
func checkIfPathIsInAVolume(container *Container, absPath string) (bool, error) {
return false, nil
}

View File

@ -17,11 +17,9 @@ type CommonConfig struct {
AutoRestart bool AutoRestart bool
Bridge bridgeConfig // Bridge holds bridge network specific configuration. Bridge bridgeConfig // Bridge holds bridge network specific configuration.
Context map[string][]string Context map[string][]string
CorsHeaders string
DisableBridge bool DisableBridge bool
Dns []string Dns []string
DnsSearch []string DnsSearch []string
EnableCors bool
ExecDriver string ExecDriver string
ExecOptions []string ExecOptions []string
ExecRoot string ExecRoot string
@ -51,8 +49,6 @@ func (config *Config) InstallCommonFlags(cmd *flag.FlagSet, usageFn func(string)
cmd.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", usageFn("Storage driver to use")) cmd.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", usageFn("Storage driver to use"))
cmd.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, defaultExec, usageFn("Exec driver to use")) cmd.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, defaultExec, usageFn("Exec driver to use"))
cmd.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, usageFn("Set the containers network MTU")) cmd.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, usageFn("Set the containers network MTU"))
cmd.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, usageFn("Enable CORS headers in the remote API, this is deprecated by --api-cors-header"))
cmd.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", usageFn("Set CORS headers in the remote API"))
// FIXME: why the inconsistency between "hosts" and "sockets"? // FIXME: why the inconsistency between "hosts" and "sockets"?
cmd.Var(opts.NewListOptsRef(&config.Dns, opts.ValidateIPAddress), []string{"#dns", "-dns"}, usageFn("DNS server to use")) cmd.Var(opts.NewListOptsRef(&config.Dns, opts.ValidateIPAddress), []string{"#dns", "-dns"}, usageFn("DNS server to use"))
cmd.Var(opts.NewListOptsRef(&config.DnsSearch, opts.ValidateDNSSearch), []string{"-dns-search"}, usageFn("DNS search domains to use")) cmd.Var(opts.NewListOptsRef(&config.DnsSearch, opts.ValidateDNSSearch), []string{"-dns-search"}, usageFn("DNS search domains to use"))

View File

@ -22,6 +22,8 @@ type Config struct {
// Fields below here are platform specific. // Fields below here are platform specific.
CorsHeaders string
EnableCors bool
EnableSelinuxSupport bool EnableSelinuxSupport bool
SocketGroup string SocketGroup string
Ulimits map[string]*ulimit.Ulimit Ulimits map[string]*ulimit.Ulimit
@ -71,6 +73,8 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
cmd.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, usageFn("Enable inter-container communication")) cmd.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, usageFn("Enable inter-container communication"))
cmd.Var(opts.NewIpOpt(&config.Bridge.DefaultIP, "0.0.0.0"), []string{"#ip", "-ip"}, usageFn("Default IP when binding container ports")) cmd.Var(opts.NewIpOpt(&config.Bridge.DefaultIP, "0.0.0.0"), []string{"#ip", "-ip"}, usageFn("Default IP when binding container ports"))
cmd.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, usageFn("Use userland proxy for loopback traffic")) cmd.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, usageFn("Use userland proxy for loopback traffic"))
cmd.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, usageFn("Enable CORS headers in the remote API, this is deprecated by --api-cors-header"))
cmd.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", usageFn("Set CORS headers in the remote API"))
config.attachExperimentalFlags(cmd, usageFn) config.attachExperimentalFlags(cmd, usageFn)
} }

View File

@ -64,28 +64,18 @@ type CommonContainer struct {
Config *runconfig.Config Config *runconfig.Config
ImageID string `json:"Image"` ImageID string `json:"Image"`
NetworkSettings *network.Settings NetworkSettings *network.Settings
ResolvConfPath string
HostnamePath string
HostsPath string
LogPath string LogPath string
Name string Name string
Driver string Driver string
ExecDriver string ExecDriver string
MountLabel, ProcessLabel string MountLabel, ProcessLabel string
RestartCount int RestartCount int
UpdateDns bool
HasBeenStartedBefore bool HasBeenStartedBefore bool
hostConfig *runconfig.HostConfig
MountPoints map[string]*mountPoint command *execdriver.Command
Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility monitor *containerMonitor
VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility execCommands *execStore
daemon *Daemon
hostConfig *runconfig.HostConfig
command *execdriver.Command
monitor *containerMonitor
execCommands *execStore
daemon *Daemon
// logDriver for closing // logDriver for closing
logDriver logger.Logger logDriver logger.Logger
logCopier *logger.Copier logCopier *logger.Copier
@ -1076,94 +1066,6 @@ func copyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error)
return written, err return written, err
} }
func (container *Container) networkMounts() []execdriver.Mount {
var mounts []execdriver.Mount
if container.ResolvConfPath != "" {
label.SetFileLabel(container.ResolvConfPath, container.MountLabel)
mounts = append(mounts, execdriver.Mount{
Source: container.ResolvConfPath,
Destination: "/etc/resolv.conf",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
if container.HostnamePath != "" {
label.SetFileLabel(container.HostnamePath, container.MountLabel)
mounts = append(mounts, execdriver.Mount{
Source: container.HostnamePath,
Destination: "/etc/hostname",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
if container.HostsPath != "" {
label.SetFileLabel(container.HostsPath, container.MountLabel)
mounts = append(mounts, execdriver.Mount{
Source: container.HostsPath,
Destination: "/etc/hosts",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
return mounts
}
func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
container.MountPoints[destination] = &mountPoint{
Name: name,
Source: source,
Destination: destination,
RW: rw,
}
}
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 { func (container *Container) shouldRestart() bool {
return container.hostConfig.RestartPolicy.Name == "always" || return container.hostConfig.RestartPolicy.Name == "always" ||
(container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0) (container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0)

View File

@ -27,12 +27,14 @@ import (
"github.com/docker/docker/pkg/ulimit" "github.com/docker/docker/pkg/ulimit"
"github.com/docker/docker/runconfig" "github.com/docker/docker/runconfig"
"github.com/docker/docker/utils" "github.com/docker/docker/utils"
"github.com/docker/docker/volume"
"github.com/docker/libnetwork" "github.com/docker/libnetwork"
"github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/options" "github.com/docker/libnetwork/options"
"github.com/docker/libnetwork/types" "github.com/docker/libnetwork/types"
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/devices" "github.com/opencontainers/runc/libcontainer/devices"
"github.com/opencontainers/runc/libcontainer/label"
) )
const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
@ -41,9 +43,15 @@ type Container struct {
CommonContainer CommonContainer
// Fields below here are platform specific. // Fields below here are platform specific.
AppArmorProfile string
activeLinks map[string]*links.Link activeLinks map[string]*links.Link
AppArmorProfile string
HostnamePath string
HostsPath string
MountPoints map[string]*mountPoint
ResolvConfPath string
UpdateDns bool
Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility
VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility
} }
func killProcessDirectly(container *Container) error { func killProcessDirectly(container *Container) error {
@ -1150,3 +1158,91 @@ func (container *Container) PrepareStorage() error {
func (container *Container) CleanupStorage() error { func (container *Container) CleanupStorage() error {
return nil return nil
} }
func (container *Container) networkMounts() []execdriver.Mount {
var mounts []execdriver.Mount
if container.ResolvConfPath != "" {
label.SetFileLabel(container.ResolvConfPath, container.MountLabel)
mounts = append(mounts, execdriver.Mount{
Source: container.ResolvConfPath,
Destination: "/etc/resolv.conf",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
if container.HostnamePath != "" {
label.SetFileLabel(container.HostnamePath, container.MountLabel)
mounts = append(mounts, execdriver.Mount{
Source: container.HostnamePath,
Destination: "/etc/hostname",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
if container.HostsPath != "" {
label.SetFileLabel(container.HostsPath, container.MountLabel)
mounts = append(mounts, execdriver.Mount{
Source: container.HostsPath,
Destination: "/etc/hosts",
Writable: !container.hostConfig.ReadonlyRootfs,
Private: true,
})
}
return mounts
}
func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
container.MountPoints[destination] = &mountPoint{
Name: name,
Source: source,
Destination: destination,
RW: rw,
}
}
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
}

View File

@ -22,18 +22,6 @@ type Container struct {
CommonContainer CommonContainer
// Fields below here are platform specific. // Fields below here are platform specific.
// TODO Windows. Further factoring out of unused fields will be necessary.
// ---- START OF TEMPORARY DECLARATION ----
// TODO Windows. Temporarily keeping fields in to assist in compilation
// of the daemon on Windows without affecting many other files in a single
// PR, thus making code review significantly harder. These lines will be
// removed in subsequent PRs.
AppArmorProfile string
// ---- END OF TEMPORARY DECLARATION ----
} }
func killProcessDirectly(container *Container) error { func killProcessDirectly(container *Container) error {
@ -213,3 +201,13 @@ func (container *Container) CleanupStorage() error {
} }
return nil return nil
} }
// TODO Windows. This can be further factored out. Used in daemon.go
func (container *Container) prepareMountPoints() error {
return nil
}
// TODO Windows. This can be further factored out. Used in delete.go
func (container *Container) removeMountPoints() error {
return nil
}

View File

@ -2,15 +2,11 @@ package daemon
import ( import (
"fmt" "fmt"
"os"
"path/filepath"
"strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/graph" "github.com/docker/docker/graph"
"github.com/docker/docker/image" "github.com/docker/docker/image"
"github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/runconfig" "github.com/docker/docker/runconfig"
"github.com/opencontainers/runc/libcontainer/label" "github.com/opencontainers/runc/libcontainer/label"
) )
@ -96,47 +92,10 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos
} }
defer container.Unmount() defer container.Unmount()
for spec := range config.Volumes { if err := createContainerPlatformSpecificSettings(container, config); err != nil {
var ( return nil, nil, err
name, destination string
parts = strings.Split(spec, ":")
)
switch len(parts) {
case 2:
name, destination = parts[0], filepath.Clean(parts[1])
default:
name = stringid.GenerateRandomID()
destination = filepath.Clean(parts[0])
}
// Skip volumes for which we already have something mounted on that
// destination because of a --volume-from.
if container.isDestinationMounted(destination) {
continue
}
path, err := container.GetResourcePath(destination)
if err != nil {
return nil, nil, err
}
stat, err := os.Stat(path)
if err == nil && !stat.IsDir() {
return nil, nil, fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
}
v, err := createVolume(name, config.VolumeDriver)
if err != nil {
return nil, nil, err
}
if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil {
return nil, nil, err
}
if err := container.copyImagePathContent(v, destination); err != nil {
return nil, nil, err
}
container.addMountPointWithVolume(destination, v, true)
} }
if err := container.ToDisk(); err != nil { if err := container.ToDisk(); err != nil {
logrus.Errorf("Error saving new container to disk: %v", err) logrus.Errorf("Error saving new container to disk: %v", err)
return nil, nil, err return nil, nil, err

60
daemon/create_unix.go Normal file
View File

@ -0,0 +1,60 @@
// +build !windows
package daemon
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/runconfig"
"github.com/opencontainers/runc/libcontainer/label"
)
// createContainerPlatformSpecificSettings performs platform specific container create functionality
func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config) error {
for spec := range config.Volumes {
var (
name, destination string
parts = strings.Split(spec, ":")
)
switch len(parts) {
case 2:
name, destination = parts[0], filepath.Clean(parts[1])
default:
name = stringid.GenerateRandomID()
destination = filepath.Clean(parts[0])
}
// Skip volumes for which we already have something mounted on that
// destination because of a --volume-from.
if container.isDestinationMounted(destination) {
continue
}
path, err := container.GetResourcePath(destination)
if err != nil {
return err
}
stat, err := os.Stat(path)
if err == nil && !stat.IsDir() {
return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
}
v, err := createVolume(name, config.VolumeDriver)
if err != nil {
return err
}
if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil {
return err
}
if err := container.copyImagePathContent(v, destination); err != nil {
return err
}
container.addMountPointWithVolume(destination, v, true)
}
return nil
}

10
daemon/create_windows.go Normal file
View File

@ -0,0 +1,10 @@
package daemon
import (
"github.com/docker/docker/runconfig"
)
// createContainerPlatformSpecificSettings performs platform specific container create functionality
func createContainerPlatformSpecificSettings(container *Container, config *runconfig.Config) error {
return nil
}

View File

@ -144,19 +144,17 @@ func (daemon *Daemon) containerRoot(id string) string {
// Load reads the contents of a container from disk // Load reads the contents of a container from disk
// This is typically done at startup. // This is typically done at startup.
func (daemon *Daemon) load(id string) (*Container, error) { func (daemon *Daemon) load(id string) (*Container, error) {
container := &Container{ container := daemon.newBaseContainer(id)
CommonContainer: daemon.newBaseContainer(id),
}
if err := container.FromDisk(); err != nil { if err := container.FromDisk(); err != nil {
return nil, err return nil, err
} }
if container.ID != id { if container.ID != id {
return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) return &container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
} }
return container, nil return &container, nil
} }
// Register makes a container object usable by the daemon as <container.ID> // Register makes a container object usable by the daemon as <container.ID>
@ -478,11 +476,7 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
base.Driver = daemon.driver.String() base.Driver = daemon.driver.String()
base.ExecDriver = daemon.execDriver.Name() base.ExecDriver = daemon.execDriver.Name()
container := &Container{ return &base, err
CommonContainer: base,
}
return container, err
} }
func GetFullContainerName(name string) (string, error) { func GetFullContainerName(name string) (string, error) {
@ -947,18 +941,6 @@ func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.
return nil return nil
} }
func (daemon *Daemon) newBaseContainer(id string) CommonContainer {
return CommonContainer{
ID: id,
State: NewState(),
MountPoints: make(map[string]*mountPoint),
Volumes: make(map[string]string),
VolumesRW: make(map[string]bool),
execCommands: newExecStore(),
root: daemon.containerRoot(id),
}
}
func setDefaultMtu(config *Config) { func setDefaultMtu(config *Config) {
// do nothing if the config does not have the default 0 value. // do nothing if the config does not have the default 0 value.
if config.Mtu != 0 { if config.Mtu != 0 {

View File

@ -539,3 +539,17 @@ func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.
return nil return nil
} }
func (daemon *Daemon) newBaseContainer(id string) Container {
return Container{
CommonContainer: CommonContainer{
ID: id,
State: NewState(),
execCommands: newExecStore(),
root: daemon.containerRoot(id),
},
MountPoints: make(map[string]*mountPoint),
Volumes: make(map[string]string),
VolumesRW: make(map[string]bool),
}
}

View File

@ -169,3 +169,14 @@ func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.
} }
return nil return nil
} }
func (daemon *Daemon) newBaseContainer(id string) Container {
return Container{
CommonContainer: CommonContainer{
ID: id,
State: NewState(),
execCommands: newExecStore(),
root: daemon.containerRoot(id),
},
}
}

View File

@ -21,53 +21,11 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
return nil, err return nil, err
} }
mountPoints := make([]types.MountPoint, 0, len(container.MountPoints)) mountPoints := addMountPoints(container)
for _, m := range container.MountPoints {
mountPoints = append(mountPoints, types.MountPoint{
Name: m.Name,
Source: m.Path(),
Destination: m.Destination,
Driver: m.Driver,
Mode: m.Mode,
RW: m.RW,
})
}
return &types.ContainerJSON{base, mountPoints, container.Config}, nil return &types.ContainerJSON{base, mountPoints, container.Config}, nil
} }
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONPre120, error) {
container, err := daemon.Get(name)
if err != nil {
return nil, err
}
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container)
if err != nil {
return nil, err
}
volumes := make(map[string]string)
volumesRW := make(map[string]bool)
for _, m := range container.MountPoints {
volumes[m.Destination] = m.Path()
volumesRW[m.Destination] = m.RW
}
config := &types.ContainerConfig{
container.Config,
container.hostConfig.Memory,
container.hostConfig.MemorySwap,
container.hostConfig.CPUShares,
container.hostConfig.CpusetCpus,
}
return &types.ContainerJSONPre120{base, volumes, volumesRW, config}, nil
}
func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) { func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
// make a copy to play with // make a copy to play with
hostConfig := *container.hostConfig hostConfig := *container.hostConfig
@ -104,9 +62,6 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
State: containerState, State: containerState,
Image: container.ImageID, Image: container.ImageID,
NetworkSettings: container.NetworkSettings, NetworkSettings: container.NetworkSettings,
ResolvConfPath: container.ResolvConfPath,
HostnamePath: container.HostnamePath,
HostsPath: container.HostsPath,
LogPath: container.LogPath, LogPath: container.LogPath,
Name: container.Name, Name: container.Name,
RestartCount: container.RestartCount, RestartCount: container.RestartCount,
@ -114,11 +69,13 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON
ExecDriver: container.ExecDriver, ExecDriver: container.ExecDriver,
MountLabel: container.MountLabel, MountLabel: container.MountLabel,
ProcessLabel: container.ProcessLabel, ProcessLabel: container.ProcessLabel,
AppArmorProfile: container.AppArmorProfile,
ExecIDs: container.GetExecIDs(), ExecIDs: container.GetExecIDs(),
HostConfig: &hostConfig, HostConfig: &hostConfig,
} }
// Now set any platform-specific fields
contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
contJSONBase.GraphDriver.Name = container.Driver contJSONBase.GraphDriver.Name = container.Driver
graphDriverData, err := daemon.driver.GetMetadata(container.ID) graphDriverData, err := daemon.driver.GetMetadata(container.ID)
if err != nil { if err != nil {

62
daemon/inspect_unix.go Normal file
View File

@ -0,0 +1,62 @@
// +build !windows
package daemon
import "github.com/docker/docker/api/types"
// This sets platform-specific fields
func setPlatformSpecificContainerFields(container *Container, contJSONBase *types.ContainerJSONBase) *types.ContainerJSONBase {
contJSONBase.AppArmorProfile = container.AppArmorProfile
contJSONBase.ResolvConfPath = container.ResolvConfPath
contJSONBase.HostnamePath = container.HostnamePath
contJSONBase.HostsPath = container.HostsPath
return contJSONBase
}
func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONPre120, error) {
container, err := daemon.Get(name)
if err != nil {
return nil, err
}
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container)
if err != nil {
return nil, err
}
volumes := make(map[string]string)
volumesRW := make(map[string]bool)
for _, m := range container.MountPoints {
volumes[m.Destination] = m.Path()
volumesRW[m.Destination] = m.RW
}
config := &types.ContainerConfig{
container.Config,
container.hostConfig.Memory,
container.hostConfig.MemorySwap,
container.hostConfig.CPUShares,
container.hostConfig.CpusetCpus,
}
return &types.ContainerJSONPre120{base, volumes, volumesRW, config}, nil
}
func addMountPoints(container *Container) []types.MountPoint {
mountPoints := make([]types.MountPoint, 0, len(container.MountPoints))
for _, m := range container.MountPoints {
mountPoints = append(mountPoints, types.MountPoint{
Name: m.Name,
Source: m.Path(),
Destination: m.Destination,
Driver: m.Driver,
Mode: m.Mode,
RW: m.RW,
})
}
return mountPoints
}

12
daemon/inspect_windows.go Normal file
View File

@ -0,0 +1,12 @@
package daemon
import "github.com/docker/docker/api/types"
// This sets platform-specific fields
func setPlatformSpecificContainerFields(container *Container, contJSONBase *types.ContainerJSONBase) *types.ContainerJSONBase {
return contJSONBase
}
func addMountPoints(container *Container) []types.MountPoint {
return nil
}

View File

@ -8,20 +8,17 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume" "github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
"github.com/docker/docker/volume/local"
"github.com/opencontainers/runc/libcontainer/label"
) )
// ErrVolumeReadonly is used to signal an error when trying to copy data into // ErrVolumeReadonly is used to signal an error when trying to copy data into
// a volume mount that is not writable. // a volume mount that is not writable.
var ErrVolumeReadonly = errors.New("mounted volume is marked read-only") var ErrVolumeReadonly = errors.New("mounted volume is marked read-only")
// TODO Windows. Further platform refactoring can still be done in volumes*.go
type mountPoint struct { type mountPoint struct {
Name string Name string
Destination string Destination string
@ -70,73 +67,6 @@ func (m *mountPoint) Path() string {
return m.Source return m.Source
} }
// BackwardsCompatible decides whether this mount point can be
// used in old versions of Docker or not.
// Only bind mounts and local volumes can be used in old versions of Docker.
func (m *mountPoint) BackwardsCompatible() bool {
return len(m.Source) > 0 || m.Driver == volume.DefaultDriverName
}
func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
bind := &mountPoint{
RW: true,
}
arr := strings.Split(spec, ":")
switch len(arr) {
case 2:
bind.Destination = arr[1]
case 3:
bind.Destination = arr[1]
mode := arr[2]
isValid, isRw := volume.ValidateMountMode(mode)
if !isValid {
return nil, fmt.Errorf("invalid mode for volumes-from: %s", mode)
}
bind.RW = isRw
// Mode field is used by SELinux to decide whether to apply label
bind.Mode = mode
default:
return nil, fmt.Errorf("Invalid volume specification: %s", spec)
}
name, source, err := parseVolumeSource(arr[0])
if err != nil {
return nil, err
}
if len(source) == 0 {
bind.Driver = config.VolumeDriver
if len(bind.Driver) == 0 {
bind.Driver = volume.DefaultDriverName
}
} else {
bind.Source = filepath.Clean(source)
}
bind.Name = name
bind.Destination = filepath.Clean(bind.Destination)
return bind, nil
}
func parseVolumesFrom(spec string) (string, string, error) {
if len(spec) == 0 {
return "", "", fmt.Errorf("malformed volumes-from specification: %s", spec)
}
specParts := strings.SplitN(spec, ":", 2)
id := specParts[0]
mode := "rw"
if len(specParts) == 2 {
mode = specParts[1]
if isValid, _ := volume.ValidateMountMode(mode); !isValid {
return "", "", fmt.Errorf("invalid mode for volumes-from: %s", mode)
}
}
return id, mode, nil
}
func copyExistingContents(source, destination string) error { func copyExistingContents(source, destination string) error {
volList, err := ioutil.ReadDir(source) volList, err := ioutil.ReadDir(source)
if err != nil { if err != nil {
@ -156,211 +86,3 @@ func copyExistingContents(source, destination string) error {
} }
return copyOwnership(source, destination) return copyOwnership(source, destination)
} }
// registerMountPoints initializes the container mount points with the configured volumes and bind mounts.
// It follows the next sequence to decide what to mount in each final destination:
//
// 1. Select the previously configured mount points for the containers, if any.
// 2. Select the volumes mounted from another containers. Overrides previously configured mount point destination.
// 3. Select the bind mounts set by the client. Overrides previously configured mount point destinations.
func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runconfig.HostConfig) error {
binds := map[string]bool{}
mountPoints := map[string]*mountPoint{}
// 1. Read already configured mount points.
for name, point := range container.MountPoints {
mountPoints[name] = point
}
// 2. Read volumes from other containers.
for _, v := range hostConfig.VolumesFrom {
containerID, mode, err := parseVolumesFrom(v)
if err != nil {
return err
}
c, err := daemon.Get(containerID)
if err != nil {
return err
}
for _, m := range c.MountPoints {
cp := &mountPoint{
Name: m.Name,
Source: m.Source,
RW: m.RW && volume.ReadWrite(mode),
Driver: m.Driver,
Destination: m.Destination,
}
if len(cp.Source) == 0 {
v, err := createVolume(cp.Name, cp.Driver)
if err != nil {
return err
}
cp.Volume = v
}
mountPoints[cp.Destination] = cp
}
}
// 3. Read bind mounts
for _, b := range hostConfig.Binds {
// #10618
bind, err := parseBindMount(b, container.MountLabel, container.Config)
if err != nil {
return err
}
if binds[bind.Destination] {
return fmt.Errorf("Duplicate bind mount %s", bind.Destination)
}
if len(bind.Name) > 0 && len(bind.Driver) > 0 {
// create the volume
v, err := createVolume(bind.Name, bind.Driver)
if err != nil {
return err
}
bind.Volume = v
bind.Source = v.Path()
// Since this is just a named volume and not a typical bind, set to shared mode `z`
if bind.Mode == "" {
bind.Mode = "z"
}
}
if err := label.Relabel(bind.Source, container.MountLabel, bind.Mode); err != nil {
return err
}
binds[bind.Destination] = true
mountPoints[bind.Destination] = bind
}
// Keep backwards compatible structures
bcVolumes := map[string]string{}
bcVolumesRW := map[string]bool{}
for _, m := range mountPoints {
if m.BackwardsCompatible() {
bcVolumes[m.Destination] = m.Path()
bcVolumesRW[m.Destination] = m.RW
}
}
container.Lock()
container.MountPoints = mountPoints
container.Volumes = bcVolumes
container.VolumesRW = bcVolumesRW
container.Unlock()
return nil
}
// TODO Windows. Factor out as not relevant (as Windows daemon support not in pre-1.7)
// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7.
// It reads the container configuration and creates valid mount points for the old volumes.
func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
// Inspect old structures only when we're upgrading from old versions
// to versions >= 1.7 and the MountPoints has not been populated with volumes data.
if len(container.MountPoints) == 0 && len(container.Volumes) > 0 {
for destination, hostPath := range container.Volumes {
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
rw := container.VolumesRW != nil && container.VolumesRW[destination]
if strings.HasPrefix(hostPath, vfsPath) {
id := filepath.Base(hostPath)
if err := migrateVolume(id, hostPath); err != nil {
return err
}
container.addLocalMountPoint(id, destination, rw)
} else { // Bind mount
id, source, err := parseVolumeSource(hostPath)
// We should not find an error here coming
// from the old configuration, but who knows.
if err != nil {
return err
}
container.addBindMountPoint(id, source, destination, rw)
}
}
} else if len(container.MountPoints) > 0 {
// Volumes created with a Docker version >= 1.7. We verify integrity in case of data created
// with Docker 1.7 RC versions that put the information in
// DOCKER_ROOT/volumes/VOLUME_ID rather than DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
l, err := getVolumeDriver(volume.DefaultDriverName)
if err != nil {
return err
}
for _, m := range container.MountPoints {
if m.Driver != volume.DefaultDriverName {
continue
}
dataPath := l.(*local.Root).DataPath(m.Name)
volumePath := filepath.Dir(dataPath)
d, err := ioutil.ReadDir(volumePath)
if err != nil {
// If the volume directory doesn't exist yet it will be recreated,
// so we only return the error when there is a different issue.
if !os.IsNotExist(err) {
return err
}
// Do not check when the volume directory does not exist.
continue
}
if validVolumeLayout(d) {
continue
}
if err := os.Mkdir(dataPath, 0755); err != nil {
return err
}
// Move data inside the data directory
for _, f := range d {
oldp := filepath.Join(volumePath, f.Name())
newp := filepath.Join(dataPath, f.Name())
if err := os.Rename(oldp, newp); err != nil {
logrus.Errorf("Unable to move %s to %s\n", oldp, newp)
}
}
}
return container.ToDisk()
}
return nil
}
func createVolume(name, driverName string) (volume.Volume, error) {
vd, err := getVolumeDriver(driverName)
if err != nil {
return nil, err
}
return vd.Create(name)
}
func removeVolume(v volume.Volume) error {
vd, err := getVolumeDriver(v.DriverName())
if err != nil {
return nil
}
return vd.Remove(v)
}
func getVolumeDriver(name string) (volume.Driver, error) {
if name == "" {
name = volume.DefaultDriverName
}
return volumedrivers.Lookup(name)
}
func parseVolumeSource(spec string) (string, string, error) {
if !filepath.IsAbs(spec) {
return spec, "", nil
}
return "", spec, nil
}

View File

@ -3,15 +3,21 @@
package daemon package daemon
import ( import (
"fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
"github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/system"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume" "github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
"github.com/docker/docker/volume/local" "github.com/docker/docker/volume/local"
"github.com/opencontainers/runc/libcontainer/label"
) )
// copyOwnership copies the permissions and uid:gid of the source file // copyOwnership copies the permissions and uid:gid of the source file
@ -49,6 +55,48 @@ func (container *Container) setupMounts() ([]execdriver.Mount, error) {
return append(mounts, container.networkMounts()...), nil return append(mounts, container.networkMounts()...), nil
} }
func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
bind := &mountPoint{
RW: true,
}
arr := strings.Split(spec, ":")
switch len(arr) {
case 2:
bind.Destination = arr[1]
case 3:
bind.Destination = arr[1]
mode := arr[2]
isValid, isRw := volume.ValidateMountMode(mode)
if !isValid {
return nil, fmt.Errorf("invalid mode for volumes-from: %s", mode)
}
bind.RW = isRw
// Mode field is used by SELinux to decide whether to apply label
bind.Mode = mode
default:
return nil, fmt.Errorf("Invalid volume specification: %s", spec)
}
name, source, err := parseVolumeSource(arr[0])
if err != nil {
return nil, err
}
if len(source) == 0 {
bind.Driver = config.VolumeDriver
if len(bind.Driver) == 0 {
bind.Driver = volume.DefaultDriverName
}
} else {
bind.Source = filepath.Clean(source)
}
bind.Name = name
bind.Destination = filepath.Clean(bind.Destination)
return bind, nil
}
func sortMounts(m []execdriver.Mount) []execdriver.Mount { func sortMounts(m []execdriver.Mount) []execdriver.Mount {
sort.Sort(mounts(m)) sort.Sort(mounts(m))
return m return m
@ -118,3 +166,235 @@ func validVolumeLayout(files []os.FileInfo) bool {
return true return true
} }
// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7.
// It reads the container configuration and creates valid mount points for the old volumes.
func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
// Inspect old structures only when we're upgrading from old versions
// to versions >= 1.7 and the MountPoints has not been populated with volumes data.
if len(container.MountPoints) == 0 && len(container.Volumes) > 0 {
for destination, hostPath := range container.Volumes {
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
rw := container.VolumesRW != nil && container.VolumesRW[destination]
if strings.HasPrefix(hostPath, vfsPath) {
id := filepath.Base(hostPath)
if err := migrateVolume(id, hostPath); err != nil {
return err
}
container.addLocalMountPoint(id, destination, rw)
} else { // Bind mount
id, source, err := parseVolumeSource(hostPath)
// We should not find an error here coming
// from the old configuration, but who knows.
if err != nil {
return err
}
container.addBindMountPoint(id, source, destination, rw)
}
}
} else if len(container.MountPoints) > 0 {
// Volumes created with a Docker version >= 1.7. We verify integrity in case of data created
// with Docker 1.7 RC versions that put the information in
// DOCKER_ROOT/volumes/VOLUME_ID rather than DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
l, err := getVolumeDriver(volume.DefaultDriverName)
if err != nil {
return err
}
for _, m := range container.MountPoints {
if m.Driver != volume.DefaultDriverName {
continue
}
dataPath := l.(*local.Root).DataPath(m.Name)
volumePath := filepath.Dir(dataPath)
d, err := ioutil.ReadDir(volumePath)
if err != nil {
// If the volume directory doesn't exist yet it will be recreated,
// so we only return the error when there is a different issue.
if !os.IsNotExist(err) {
return err
}
// Do not check when the volume directory does not exist.
continue
}
if validVolumeLayout(d) {
continue
}
if err := os.Mkdir(dataPath, 0755); err != nil {
return err
}
// Move data inside the data directory
for _, f := range d {
oldp := filepath.Join(volumePath, f.Name())
newp := filepath.Join(dataPath, f.Name())
if err := os.Rename(oldp, newp); err != nil {
logrus.Errorf("Unable to move %s to %s\n", oldp, newp)
}
}
}
return container.ToDisk()
}
return nil
}
func parseVolumesFrom(spec string) (string, string, error) {
if len(spec) == 0 {
return "", "", fmt.Errorf("malformed volumes-from specification: %s", spec)
}
specParts := strings.SplitN(spec, ":", 2)
id := specParts[0]
mode := "rw"
if len(specParts) == 2 {
mode = specParts[1]
if isValid, _ := volume.ValidateMountMode(mode); !isValid {
return "", "", fmt.Errorf("invalid mode for volumes-from: %s", mode)
}
}
return id, mode, nil
}
// registerMountPoints initializes the container mount points with the configured volumes and bind mounts.
// It follows the next sequence to decide what to mount in each final destination:
//
// 1. Select the previously configured mount points for the containers, if any.
// 2. Select the volumes mounted from another containers. Overrides previously configured mount point destination.
// 3. Select the bind mounts set by the client. Overrides previously configured mount point destinations.
func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runconfig.HostConfig) error {
binds := map[string]bool{}
mountPoints := map[string]*mountPoint{}
// 1. Read already configured mount points.
for name, point := range container.MountPoints {
mountPoints[name] = point
}
// 2. Read volumes from other containers.
for _, v := range hostConfig.VolumesFrom {
containerID, mode, err := parseVolumesFrom(v)
if err != nil {
return err
}
c, err := daemon.Get(containerID)
if err != nil {
return err
}
for _, m := range c.MountPoints {
cp := &mountPoint{
Name: m.Name,
Source: m.Source,
RW: m.RW && volume.ReadWrite(mode),
Driver: m.Driver,
Destination: m.Destination,
}
if len(cp.Source) == 0 {
v, err := createVolume(cp.Name, cp.Driver)
if err != nil {
return err
}
cp.Volume = v
}
mountPoints[cp.Destination] = cp
}
}
// 3. Read bind mounts
for _, b := range hostConfig.Binds {
// #10618
bind, err := parseBindMount(b, container.MountLabel, container.Config)
if err != nil {
return err
}
if binds[bind.Destination] {
return fmt.Errorf("Duplicate bind mount %s", bind.Destination)
}
if len(bind.Name) > 0 && len(bind.Driver) > 0 {
// create the volume
v, err := createVolume(bind.Name, bind.Driver)
if err != nil {
return err
}
bind.Volume = v
bind.Source = v.Path()
// Since this is just a named volume and not a typical bind, set to shared mode `z`
if bind.Mode == "" {
bind.Mode = "z"
}
}
if err := label.Relabel(bind.Source, container.MountLabel, bind.Mode); err != nil {
return err
}
binds[bind.Destination] = true
mountPoints[bind.Destination] = bind
}
// Keep backwards compatible structures
bcVolumes := map[string]string{}
bcVolumesRW := map[string]bool{}
for _, m := range mountPoints {
if m.BackwardsCompatible() {
bcVolumes[m.Destination] = m.Path()
bcVolumesRW[m.Destination] = m.RW
}
}
container.Lock()
container.MountPoints = mountPoints
container.Volumes = bcVolumes
container.VolumesRW = bcVolumesRW
container.Unlock()
return nil
}
func createVolume(name, driverName string) (volume.Volume, error) {
vd, err := getVolumeDriver(driverName)
if err != nil {
return nil, err
}
return vd.Create(name)
}
func removeVolume(v volume.Volume) error {
vd, err := getVolumeDriver(v.DriverName())
if err != nil {
return nil
}
return vd.Remove(v)
}
func getVolumeDriver(name string) (volume.Driver, error) {
if name == "" {
name = volume.DefaultDriverName
}
return volumedrivers.Lookup(name)
}
func parseVolumeSource(spec string) (string, string, error) {
if !filepath.IsAbs(spec) {
return spec, "", nil
}
return "", spec, nil
}
// BackwardsCompatible decides whether this mount point can be
// used in old versions of Docker or not.
// Only bind mounts and local volumes can be used in old versions of Docker.
func (m *mountPoint) BackwardsCompatible() bool {
return len(m.Source) > 0 || m.Driver == volume.DefaultDriverName
}

View File

@ -3,9 +3,8 @@
package daemon package daemon
import ( import (
"os"
"github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/execdriver"
"github.com/docker/docker/runconfig"
) )
// Not supported on Windows // Not supported on Windows
@ -17,10 +16,13 @@ func (container *Container) setupMounts() ([]execdriver.Mount, error) {
return nil, nil return nil, nil
} }
func migrateVolume(id, vfs string) error { // verifyVolumesInfo ports volumes configured for the containers pre docker 1.7.
// As the Windows daemon was not supported before 1.7, this is a no-op
func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
return nil return nil
} }
func validVolumeLayout(files []os.FileInfo) bool { // TODO Windows: This can be further factored out. Called from daemon\daemon.go
return true func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runconfig.HostConfig) error {
return nil
} }

View File

@ -212,10 +212,8 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
} }
serverConfig := &apiserver.ServerConfig{ serverConfig := &apiserver.ServerConfig{
Logging: true, Logging: true,
EnableCors: cli.EnableCors, Version: dockerversion.VERSION,
CorsHeaders: cli.CorsHeaders,
Version: dockerversion.VERSION,
} }
serverConfig = setPlatformServerConfig(serverConfig, cli.Config) serverConfig = setPlatformServerConfig(serverConfig, cli.Config)

View File

@ -17,6 +17,9 @@ import (
func setPlatformServerConfig(serverConfig *apiserver.ServerConfig, daemonCfg *daemon.Config) *apiserver.ServerConfig { func setPlatformServerConfig(serverConfig *apiserver.ServerConfig, daemonCfg *daemon.Config) *apiserver.ServerConfig {
serverConfig.SocketGroup = daemonCfg.SocketGroup serverConfig.SocketGroup = daemonCfg.SocketGroup
serverConfig.EnableCors = daemonCfg.EnableCors
serverConfig.CorsHeaders = daemonCfg.CorsHeaders
return serverConfig return serverConfig
} }