github.com/ld86/docker@v1.7.1-rc3/daemon/daemon_test.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"github.com/docker/docker/pkg/graphdb"
    12  	"github.com/docker/docker/pkg/stringid"
    13  	"github.com/docker/docker/pkg/truncindex"
    14  	"github.com/docker/docker/volume"
    15  	"github.com/docker/docker/volume/drivers"
    16  	"github.com/docker/docker/volume/local"
    17  )
    18  
    19  //
    20  // https://github.com/docker/docker/issues/8069
    21  //
    22  
    23  func TestGet(t *testing.T) {
    24  	c1 := &Container{
    25  		CommonContainer: CommonContainer{
    26  			ID:   "5a4ff6a163ad4533d22d69a2b8960bf7fafdcba06e72d2febdba229008b0bf57",
    27  			Name: "tender_bardeen",
    28  		},
    29  	}
    30  
    31  	c2 := &Container{
    32  		CommonContainer: CommonContainer{
    33  			ID:   "3cdbd1aa394fd68559fd1441d6eff2ab7c1e6363582c82febfaa8045df3bd8de",
    34  			Name: "drunk_hawking",
    35  		},
    36  	}
    37  
    38  	c3 := &Container{
    39  		CommonContainer: CommonContainer{
    40  			ID:   "3cdbd1aa394fd68559fd1441d6eff2abfafdcba06e72d2febdba229008b0bf57",
    41  			Name: "3cdbd1aa",
    42  		},
    43  	}
    44  
    45  	c4 := &Container{
    46  		CommonContainer: CommonContainer{
    47  			ID:   "75fb0b800922abdbef2d27e60abcdfaf7fb0698b2a96d22d3354da361a6ff4a5",
    48  			Name: "5a4ff6a163ad4533d22d69a2b8960bf7fafdcba06e72d2febdba229008b0bf57",
    49  		},
    50  	}
    51  
    52  	c5 := &Container{
    53  		CommonContainer: CommonContainer{
    54  			ID:   "d22d69a2b8960bf7fafdcba06e72d2febdba960bf7fafdcba06e72d2f9008b060b",
    55  			Name: "d22d69a2b896",
    56  		},
    57  	}
    58  
    59  	store := &contStore{
    60  		s: map[string]*Container{
    61  			c1.ID: c1,
    62  			c2.ID: c2,
    63  			c3.ID: c3,
    64  			c4.ID: c4,
    65  			c5.ID: c5,
    66  		},
    67  	}
    68  
    69  	index := truncindex.NewTruncIndex([]string{})
    70  	index.Add(c1.ID)
    71  	index.Add(c2.ID)
    72  	index.Add(c3.ID)
    73  	index.Add(c4.ID)
    74  	index.Add(c5.ID)
    75  
    76  	daemonTestDbPath := path.Join(os.TempDir(), "daemon_test.db")
    77  	graph, err := graphdb.NewSqliteConn(daemonTestDbPath)
    78  	if err != nil {
    79  		t.Fatalf("Failed to create daemon test sqlite database at %s", daemonTestDbPath)
    80  	}
    81  	graph.Set(c1.Name, c1.ID)
    82  	graph.Set(c2.Name, c2.ID)
    83  	graph.Set(c3.Name, c3.ID)
    84  	graph.Set(c4.Name, c4.ID)
    85  	graph.Set(c5.Name, c5.ID)
    86  
    87  	daemon := &Daemon{
    88  		containers:     store,
    89  		idIndex:        index,
    90  		containerGraph: graph,
    91  	}
    92  
    93  	if container, _ := daemon.Get("3cdbd1aa394fd68559fd1441d6eff2ab7c1e6363582c82febfaa8045df3bd8de"); container != c2 {
    94  		t.Fatal("Should explicitly match full container IDs")
    95  	}
    96  
    97  	if container, _ := daemon.Get("75fb0b8009"); container != c4 {
    98  		t.Fatal("Should match a partial ID")
    99  	}
   100  
   101  	if container, _ := daemon.Get("drunk_hawking"); container != c2 {
   102  		t.Fatal("Should match a full name")
   103  	}
   104  
   105  	// c3.Name is a partial match for both c3.ID and c2.ID
   106  	if c, _ := daemon.Get("3cdbd1aa"); c != c3 {
   107  		t.Fatal("Should match a full name even though it collides with another container's ID")
   108  	}
   109  
   110  	if container, _ := daemon.Get("d22d69a2b896"); container != c5 {
   111  		t.Fatal("Should match a container where the provided prefix is an exact match to the it's name, and is also a prefix for it's ID")
   112  	}
   113  
   114  	if _, err := daemon.Get("3cdbd1"); err == nil {
   115  		t.Fatal("Should return an error when provided a prefix that partially matches multiple container ID's")
   116  	}
   117  
   118  	if _, err := daemon.Get("nothing"); err == nil {
   119  		t.Fatal("Should return an error when provided a prefix that is neither a name or a partial match to an ID")
   120  	}
   121  
   122  	os.Remove(daemonTestDbPath)
   123  }
   124  
   125  func TestLoadWithVolume(t *testing.T) {
   126  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	defer os.RemoveAll(tmp)
   131  
   132  	containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   133  	containerPath := filepath.Join(tmp, containerId)
   134  	if err := os.MkdirAll(containerPath, 0755); err != nil {
   135  		t.Fatal(err)
   136  	}
   137  
   138  	hostVolumeId := stringid.GenerateRandomID()
   139  	vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
   140  	volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
   141  
   142  	if err := os.MkdirAll(vfsPath, 0755); err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	if err := os.MkdirAll(volumePath, 0755); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	content := filepath.Join(vfsPath, "helo")
   150  	if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
   151  		t.Fatal(err)
   152  	}
   153  
   154  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   155  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   156  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   157  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   158  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   159  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   160  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   161  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   162  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
   163  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   164  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   165  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   166  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   167  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   168  "UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
   169  
   170  	cfg := fmt.Sprintf(config, vfsPath)
   171  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
   172  		t.Fatal(err)
   173  	}
   174  
   175  	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   176  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   177  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   178  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   179  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	daemon, err := initDaemonForVolumesTest(tmp)
   184  	if err != nil {
   185  		t.Fatal(err)
   186  	}
   187  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   188  
   189  	c, err := daemon.load(containerId)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  
   194  	err = daemon.verifyVolumesInfo(c)
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  
   199  	if len(c.MountPoints) != 1 {
   200  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   201  	}
   202  
   203  	m := c.MountPoints["/vol1"]
   204  	if m.Name != hostVolumeId {
   205  		t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
   206  	}
   207  
   208  	if m.Destination != "/vol1" {
   209  		t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
   210  	}
   211  
   212  	if !m.RW {
   213  		t.Fatalf("Expected mount point to be RW but it was not\n")
   214  	}
   215  
   216  	if m.Driver != volume.DefaultDriverName {
   217  		t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
   218  	}
   219  
   220  	newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
   221  	b, err := ioutil.ReadFile(newVolumeContent)
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  	if string(b) != "HELO" {
   226  		t.Fatalf("Expected HELO, was %s\n", string(b))
   227  	}
   228  }
   229  
   230  func TestLoadWithBindMount(t *testing.T) {
   231  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   232  	if err != nil {
   233  		t.Fatal(err)
   234  	}
   235  	defer os.RemoveAll(tmp)
   236  
   237  	containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   238  	containerPath := filepath.Join(tmp, containerId)
   239  	if err = os.MkdirAll(containerPath, 0755); err != nil {
   240  		t.Fatal(err)
   241  	}
   242  
   243  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   244  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   245  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   246  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   247  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   248  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   249  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   250  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   251  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
   252  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   253  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   254  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   255  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   256  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   257  "UpdateDns":false,"Volumes":{"/vol1": "/vol1"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
   258  
   259  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   264  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   265  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   266  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   267  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   268  		t.Fatal(err)
   269  	}
   270  
   271  	daemon, err := initDaemonForVolumesTest(tmp)
   272  	if err != nil {
   273  		t.Fatal(err)
   274  	}
   275  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   276  
   277  	c, err := daemon.load(containerId)
   278  	if err != nil {
   279  		t.Fatal(err)
   280  	}
   281  
   282  	err = daemon.verifyVolumesInfo(c)
   283  	if err != nil {
   284  		t.Fatal(err)
   285  	}
   286  
   287  	if len(c.MountPoints) != 1 {
   288  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   289  	}
   290  
   291  	m := c.MountPoints["/vol1"]
   292  	if m.Name != "" {
   293  		t.Fatalf("Expected empty mount name, was %s\n", m.Name)
   294  	}
   295  
   296  	if m.Source != "/vol1" {
   297  		t.Fatalf("Expected mount source /vol1, was %s\n", m.Source)
   298  	}
   299  
   300  	if m.Destination != "/vol1" {
   301  		t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
   302  	}
   303  
   304  	if !m.RW {
   305  		t.Fatalf("Expected mount point to be RW but it was not\n")
   306  	}
   307  }
   308  
   309  func TestLoadWithVolume17RC(t *testing.T) {
   310  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  	defer os.RemoveAll(tmp)
   315  
   316  	containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   317  	containerPath := filepath.Join(tmp, containerId)
   318  	if err := os.MkdirAll(containerPath, 0755); err != nil {
   319  		t.Fatal(err)
   320  	}
   321  
   322  	hostVolumeId := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101"
   323  	volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
   324  
   325  	if err := os.MkdirAll(volumePath, 0755); err != nil {
   326  		t.Fatal(err)
   327  	}
   328  
   329  	content := filepath.Join(volumePath, "helo")
   330  	if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
   331  		t.Fatal(err)
   332  	}
   333  
   334  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   335  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   336  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   337  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   338  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   339  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   340  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   341  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   342  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
   343  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   344  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   345  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   346  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   347  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   348  "UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}`
   349  
   350  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
   351  		t.Fatal(err)
   352  	}
   353  
   354  	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   355  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   356  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   357  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   358  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   359  		t.Fatal(err)
   360  	}
   361  
   362  	daemon, err := initDaemonForVolumesTest(tmp)
   363  	if err != nil {
   364  		t.Fatal(err)
   365  	}
   366  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   367  
   368  	c, err := daemon.load(containerId)
   369  	if err != nil {
   370  		t.Fatal(err)
   371  	}
   372  
   373  	err = daemon.verifyVolumesInfo(c)
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	if len(c.MountPoints) != 1 {
   379  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   380  	}
   381  
   382  	m := c.MountPoints["/vol1"]
   383  	if m.Name != hostVolumeId {
   384  		t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
   385  	}
   386  
   387  	if m.Destination != "/vol1" {
   388  		t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
   389  	}
   390  
   391  	if !m.RW {
   392  		t.Fatalf("Expected mount point to be RW but it was not\n")
   393  	}
   394  
   395  	if m.Driver != volume.DefaultDriverName {
   396  		t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
   397  	}
   398  
   399  	newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
   400  	b, err := ioutil.ReadFile(newVolumeContent)
   401  	if err != nil {
   402  		t.Fatal(err)
   403  	}
   404  	if string(b) != "HELO" {
   405  		t.Fatalf("Expected HELO, was %s\n", string(b))
   406  	}
   407  }
   408  
   409  func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
   410  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   411  	if err != nil {
   412  		t.Fatal(err)
   413  	}
   414  	defer os.RemoveAll(tmp)
   415  
   416  	containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   417  	containerPath := filepath.Join(tmp, containerId)
   418  	if err := os.MkdirAll(containerPath, 0755); err != nil {
   419  		t.Fatal(err)
   420  	}
   421  
   422  	hostVolumeId := stringid.GenerateRandomID()
   423  	vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
   424  	volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
   425  
   426  	if err := os.MkdirAll(vfsPath, 0755); err != nil {
   427  		t.Fatal(err)
   428  	}
   429  	if err := os.MkdirAll(volumePath, 0755); err != nil {
   430  		t.Fatal(err)
   431  	}
   432  
   433  	content := filepath.Join(vfsPath, "helo")
   434  	if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   439  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   440  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   441  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   442  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   443  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   444  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   445  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   446  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
   447  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   448  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   449  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   450  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   451  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   452  "UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
   453  
   454  	cfg := fmt.Sprintf(config, vfsPath)
   455  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
   456  		t.Fatal(err)
   457  	}
   458  
   459  	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   460  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   461  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   462  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   463  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   464  		t.Fatal(err)
   465  	}
   466  
   467  	daemon, err := initDaemonForVolumesTest(tmp)
   468  	if err != nil {
   469  		t.Fatal(err)
   470  	}
   471  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   472  
   473  	c, err := daemon.load(containerId)
   474  	if err != nil {
   475  		t.Fatal(err)
   476  	}
   477  
   478  	err = daemon.verifyVolumesInfo(c)
   479  	if err != nil {
   480  		t.Fatal(err)
   481  	}
   482  
   483  	if len(c.MountPoints) != 1 {
   484  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   485  	}
   486  
   487  	m := c.MountPoints["/vol1"]
   488  	v, err := createVolume(m.Name, m.Driver)
   489  	if err != nil {
   490  		t.Fatal(err)
   491  	}
   492  
   493  	if err := removeVolume(v); err != nil {
   494  		t.Fatal(err)
   495  	}
   496  
   497  	fi, err := os.Stat(vfsPath)
   498  	if err == nil || !os.IsNotExist(err) {
   499  		t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err)
   500  	}
   501  }
   502  
   503  func initDaemonForVolumesTest(tmp string) (*Daemon, error) {
   504  	daemon := &Daemon{
   505  		repository: tmp,
   506  		root:       tmp,
   507  	}
   508  
   509  	volumesDriver, err := local.New(tmp)
   510  	if err != nil {
   511  		return nil, err
   512  	}
   513  	volumedrivers.Register(volumesDriver, volumesDriver.Name())
   514  
   515  	return daemon, nil
   516  }