diff --git a/daemon/container.go b/daemon/container.go index 5f396dda57..3533628aa9 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -77,6 +77,20 @@ type CommonContainer struct { logCopier *logger.Copier } +// newBaseContainer creates a new container with its +// basic configuration. +func newBaseContainer(id, root string) *Container { + return &Container{ + CommonContainer: CommonContainer{ + ID: id, + State: NewState(), + execCommands: newExecStore(), + root: root, + MountPoints: make(map[string]*volume.MountPoint), + }, + } +} + func (container *Container) fromDisk() error { pth, err := container.jsonPath() if err != nil { diff --git a/daemon/container_unix.go b/daemon/container_unix.go index f4864b027a..338ec7ebca 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -58,9 +58,6 @@ type Container struct { ShmPath string MqueuePath string ResolvConfPath string - - 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 { diff --git a/daemon/daemon.go b/daemon/daemon.go index 90bd5cca91..b083a65871 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -242,10 +242,6 @@ func (daemon *Daemon) Register(container *Container) error { } } - if err := daemon.verifyVolumesInfo(container); err != nil { - return err - } - if err := daemon.prepareMountPoints(container); err != nil { return err } @@ -1332,6 +1328,12 @@ func (daemon *Daemon) getNetworkStats(c *Container) ([]*libcontainer.NetworkInte return list, nil } +// newBaseContainer creates a new container with its initial +// configuration based on the root storage from the daemon. +func (daemon *Daemon) newBaseContainer(id string) *Container { + return newBaseContainer(id, daemon.containerRoot(id)) +} + func convertLnNetworkStats(name string, stats *lntypes.InterfaceStatistics) *libcontainer.NetworkInterface { n := &libcontainer.NetworkInterface{Name: name} n.RxBytes = stats.RxBytes diff --git a/daemon/daemon_test.go b/daemon/daemon_test.go index 919327e795..80216ea083 100644 --- a/daemon/daemon_test.go +++ b/daemon/daemon_test.go @@ -1,18 +1,13 @@ package daemon import ( - "fmt" - "io/ioutil" "os" "path" - "path/filepath" "testing" "github.com/docker/docker/pkg/graphdb" - "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/truncindex" "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" volumedrivers "github.com/docker/docker/volume/drivers" "github.com/docker/docker/volume/local" "github.com/docker/docker/volume/store" @@ -124,384 +119,6 @@ func TestGet(t *testing.T) { os.Remove(daemonTestDbPath) } -func TestLoadWithVolume(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err := os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - hostVolumeID := stringid.GenerateNonCryptoID() - vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeID) - volumePath := filepath.Join(tmp, "volumes", hostVolumeID) - - if err := os.MkdirAll(vfsPath, 0755); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(volumePath, 0755); err != nil { - t.Fatal(err) - } - - content := filepath.Join(vfsPath, "helo") - if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}` - - cfg := fmt.Sprintf(config, vfsPath) - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":[],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonWithVolumeStore(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - if m.Name != hostVolumeID { - t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeID, m.Name) - } - - if m.Destination != "/vol1" { - t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination) - } - - if !m.RW { - t.Fatalf("Expected mount point to be RW but it was not\n") - } - - if m.Driver != volume.DefaultDriverName { - t.Fatalf("Expected mount driver local, was %s\n", m.Driver) - } - - newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo") - b, err := ioutil.ReadFile(newVolumeContent) - if err != nil { - t.Fatal(err) - } - if string(b) != "HELO" { - t.Fatalf("Expected HELO, was %s\n", string(b)) - } -} - -func TestLoadWithBindMount(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err = os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"Volumes":{"/vol1": "/vol1"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}` - - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonWithVolumeStore(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - if m.Name != "" { - t.Fatalf("Expected empty mount name, was %s\n", m.Name) - } - - if m.Source != "/vol1" { - t.Fatalf("Expected mount source /vol1, was %s\n", m.Source) - } - - if m.Destination != "/vol1" { - t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination) - } - - if !m.RW { - t.Fatalf("Expected mount point to be RW but it was not\n") - } -} - -func TestLoadWithVolume17RC(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err := os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - hostVolumeID := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101" - volumePath := filepath.Join(tmp, "volumes", hostVolumeID) - - if err := os.MkdirAll(volumePath, 0755); err != nil { - t.Fatal(err) - } - - content := filepath.Join(volumePath, "helo") - if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}` - - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":[],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonWithVolumeStore(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - if m.Name != hostVolumeID { - t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeID, m.Name) - } - - if m.Destination != "/vol1" { - t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination) - } - - if !m.RW { - t.Fatalf("Expected mount point to be RW but it was not\n") - } - - if m.Driver != volume.DefaultDriverName { - t.Fatalf("Expected mount driver local, was %s\n", m.Driver) - } - - newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo") - b, err := ioutil.ReadFile(newVolumeContent) - if err != nil { - t.Fatal(err) - } - if string(b) != "HELO" { - t.Fatalf("Expected HELO, was %s\n", string(b)) - } -} - -func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) { - tmp, err := ioutil.TempDir("", "docker-daemon-test-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" - containerPath := filepath.Join(tmp, containerID) - if err := os.MkdirAll(containerPath, 0755); err != nil { - t.Fatal(err) - } - - hostVolumeID := stringid.GenerateNonCryptoID() - vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeID) - volumePath := filepath.Join(tmp, "volumes", hostVolumeID) - - if err := os.MkdirAll(vfsPath, 0755); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(volumePath, 0755); err != nil { - t.Fatal(err) - } - - content := filepath.Join(vfsPath, "helo") - if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil { - t.Fatal(err) - } - - config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0, -"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, -"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top", -"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"", -"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true, -"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null, -"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95", -"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1", -"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}}, -"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf", -"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname", -"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts", -"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log", -"Name":"/ubuntu","Driver":"aufs","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, -"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}` - - cfg := fmt.Sprintf(config, vfsPath) - if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil { - t.Fatal(err) - } - - hostConfig := `{"Binds":[],"ContainerIDFile":"","Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"", -"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null, -"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0}, -"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}` - if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil { - t.Fatal(err) - } - - daemon, err := initDaemonWithVolumeStore(tmp) - if err != nil { - t.Fatal(err) - } - defer volumedrivers.Unregister(volume.DefaultDriverName) - - c, err := daemon.load(containerID) - if err != nil { - t.Fatal(err) - } - - err = daemon.verifyVolumesInfo(c) - if err != nil { - t.Fatal(err) - } - - if len(c.MountPoints) != 1 { - t.Fatalf("Expected 1 volume mounted, was 0\n") - } - - m := c.MountPoints["/vol1"] - _, err = daemon.VolumeCreate(m.Name, m.Driver, nil) - if err != nil { - t.Fatal(err) - } - - if err := daemon.VolumeRm(m.Name); err != nil { - t.Fatal(err) - } - - fi, err := os.Stat(vfsPath) - if err == nil || !os.IsNotExist(err) { - t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err) - } -} - func initDaemonWithVolumeStore(tmp string) (*Daemon, error) { daemon := &Daemon{ repository: tmp, diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 67e51d5d4a..a5a3806988 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -20,7 +20,6 @@ import ( "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/runconfig" - "github.com/docker/docker/volume" "github.com/docker/libnetwork" nwconfig "github.com/docker/libnetwork/config" "github.com/docker/libnetwork/drivers/bridge" @@ -602,20 +601,6 @@ func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig. 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]*volume.MountPoint), - }, - Volumes: make(map[string]string), - VolumesRW: make(map[string]bool), - } -} - // conditionalMountOnStart is a platform specific helper function during the // container start to call mount. func (daemon *Daemon) conditionalMountOnStart(container *Container) error { diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 6f94e81c70..219a5c3786 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -107,17 +107,6 @@ func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig. return nil } -func (daemon *Daemon) newBaseContainer(id string) *Container { - return &Container{ - CommonContainer: CommonContainer{ - ID: id, - State: NewState(), - execCommands: newExecStore(), - root: daemon.containerRoot(id), - }, - } -} - func (daemon *Daemon) cleanupMounts() error { return nil } diff --git a/daemon/volumes.go b/daemon/volumes.go index a589de66ae..981c3254a1 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -69,6 +69,7 @@ func (m mounts) parts(i int) int { // 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. +// 4. Cleanup old volumes that are about to be reasigned. func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runconfig.HostConfig) error { binds := map[string]bool{} mountPoints := map[string]*volume.MountPoint{} @@ -144,11 +145,17 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc mountPoints[bind.Destination] = bind } - bcVolumes, bcVolumesRW := configureBackCompatStructures(daemon, container, mountPoints) - container.Lock() + + // 4. Cleanup old volumes that are about to be reasigned. + for _, m := range mountPoints { + if m.BackwardsCompatible() { + if mp, exists := container.MountPoints[m.Destination]; exists && mp.Volume != nil { + daemon.volumes.Decrement(mp.Volume) + } + } + } container.MountPoints = mountPoints - setBackCompatStructures(container, bcVolumes, bcVolumesRW) container.Unlock() diff --git a/daemon/volumes_unix.go b/daemon/volumes_unix.go index a7ac991105..7bd0a9b1b0 100644 --- a/daemon/volumes_unix.go +++ b/daemon/volumes_unix.go @@ -5,11 +5,8 @@ package daemon import ( "io/ioutil" "os" - "path/filepath" "sort" - "strings" - "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/system" @@ -143,77 +140,6 @@ func validVolumeLayout(files []os.FileInfo) bool { 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 := volume.ParseVolumeSource(hostPath) - 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 := volumedrivers.Lookup(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.toDiskLocking() - } - - return nil -} - // setBindModeIfNull is platform specific processing to ensure the // shared mode is set to 'z' if it is null. This is called in the case // of processing a named volume and not a typical bind. @@ -223,30 +149,3 @@ func setBindModeIfNull(bind *volume.MountPoint) *volume.MountPoint { } return bind } - -// configureBackCompatStructures is platform specific processing for -// registering mount points to populate old structures. -func configureBackCompatStructures(daemon *Daemon, container *Container, mountPoints map[string]*volume.MountPoint) (map[string]string, map[string]bool) { - // 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 - - // This mountpoint is replacing an existing one, so the count needs to be decremented - if mp, exists := container.MountPoints[m.Destination]; exists && mp.Volume != nil { - daemon.volumes.Decrement(mp.Volume) - } - } - } - return bcVolumes, bcVolumesRW -} - -// setBackCompatStructures is a platform specific helper function to set -// backwards compatible structures in the container when registering volumes. -func setBackCompatStructures(container *Container, bcVolumes map[string]string, bcVolumesRW map[string]bool) { - container.Volumes = bcVolumes - container.VolumesRW = bcVolumesRW -} diff --git a/daemon/volumes_windows.go b/daemon/volumes_windows.go index 73ec171902..8cc0294482 100644 --- a/daemon/volumes_windows.go +++ b/daemon/volumes_windows.go @@ -36,26 +36,8 @@ func (daemon *Daemon) setupMounts(container *Container) ([]execdriver.Mount, err return mnts, nil } -// 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 -} - // setBindModeIfNull is platform specific processing which is a no-op on // Windows. func setBindModeIfNull(bind *volume.MountPoint) *volume.MountPoint { return bind } - -// configureBackCompatStructures is platform specific processing for -// registering mount points to populate old structures. This is a no-op on Windows. -func configureBackCompatStructures(*Daemon, *Container, map[string]*volume.MountPoint) (map[string]string, map[string]bool) { - return nil, nil -} - -// setBackCompatStructures is a platform specific helper function to set -// backwards compatible structures in the container when registering volumes. -// This is a no-op on Windows. -func setBackCompatStructures(*Container, map[string]string, map[string]bool) { -} diff --git a/volume/volume_windows.go b/volume/volume_windows.go index b6b3bbb0fe..ef7a25476a 100644 --- a/volume/volume_windows.go +++ b/volume/volume_windows.go @@ -80,6 +80,13 @@ const ( // ) +// BackwardsCompatible decides whether this mount point can be +// used in old versions of Docker or not. +// Windows volumes are never backwards compatible. +func (m *MountPoint) BackwardsCompatible() bool { + return false +} + // ParseMountSpec validates the configuration of mount information is valid. func ParseMountSpec(spec string, volumeDriver string) (*MountPoint, error) { var specExp = regexp.MustCompile(`^` + RXSource + RXDestination + RXMode + `$`)