Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -129,12 +129,25 @@ func TestLoadWithVolume(t *testing.T) {
|
| 129 | 129 |
|
| 130 | 130 |
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e" |
| 131 | 131 |
containerPath := filepath.Join(tmp, containerId) |
| 132 |
- if err = os.MkdirAll(containerPath, 0755); err != nil {
|
|
| 132 |
+ if err := os.MkdirAll(containerPath, 0755); err != nil {
|
|
| 133 | 133 |
t.Fatal(err) |
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 | 136 |
hostVolumeId := stringid.GenerateRandomID() |
| 137 |
- volumePath := filepath.Join(tmp, "vfs", "dir", hostVolumeId) |
|
| 137 |
+ vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId) |
|
| 138 |
+ volumePath := filepath.Join(tmp, "volumes", hostVolumeId) |
|
| 139 |
+ |
|
| 140 |
+ if err := os.MkdirAll(vfsPath, 0755); err != nil {
|
|
| 141 |
+ t.Fatal(err) |
|
| 142 |
+ } |
|
| 143 |
+ if err := os.MkdirAll(volumePath, 0755); err != nil {
|
|
| 144 |
+ t.Fatal(err) |
|
| 145 |
+ } |
|
| 146 |
+ |
|
| 147 |
+ content := filepath.Join(vfsPath, "helo") |
|
| 148 |
+ if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
|
|
| 149 |
+ t.Fatal(err) |
|
| 150 |
+ } |
|
| 138 | 151 |
|
| 139 | 152 |
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
|
| 140 | 153 |
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"}, |
| ... | ... |
@@ -152,7 +165,7 @@ func TestLoadWithVolume(t *testing.T) {
|
| 152 | 152 |
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0, |
| 153 | 153 |
"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
|
| 154 | 154 |
|
| 155 |
- cfg := fmt.Sprintf(config, volumePath) |
|
| 155 |
+ cfg := fmt.Sprintf(config, vfsPath) |
|
| 156 | 156 |
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
|
| 157 | 157 |
t.Fatal(err) |
| 158 | 158 |
} |
| ... | ... |
@@ -200,6 +213,15 @@ func TestLoadWithVolume(t *testing.T) {
|
| 200 | 200 |
if m.Driver != volume.DefaultDriverName {
|
| 201 | 201 |
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
|
| 202 | 202 |
} |
| 203 |
+ |
|
| 204 |
+ newVolumeContent := filepath.Join(volumePath, "helo") |
|
| 205 |
+ b, err := ioutil.ReadFile(newVolumeContent) |
|
| 206 |
+ if err != nil {
|
|
| 207 |
+ t.Fatal(err) |
|
| 208 |
+ } |
|
| 209 |
+ if string(b) != "HELO" {
|
|
| 210 |
+ t.Fatalf("Expected HELO, was %s\n", string(b))
|
|
| 211 |
+ } |
|
| 203 | 212 |
} |
| 204 | 213 |
|
| 205 | 214 |
func TestLoadWithBindMount(t *testing.T) {
|
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"path/filepath" |
| 9 | 9 |
"strings" |
| 10 | 10 |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 11 | 12 |
"github.com/docker/docker/pkg/chrootarchive" |
| 12 | 13 |
"github.com/docker/docker/runconfig" |
| 13 | 14 |
"github.com/docker/docker/volume" |
| ... | ... |
@@ -272,6 +273,9 @@ func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
|
| 272 | 272 |
|
| 273 | 273 |
if strings.HasPrefix(hostPath, vfsPath) {
|
| 274 | 274 |
id := filepath.Base(hostPath) |
| 275 |
+ if err := daemon.migrateVolume(id, hostPath); err != nil {
|
|
| 276 |
+ return err |
|
| 277 |
+ } |
|
| 275 | 278 |
container.addLocalMountPoint(id, destination, rw) |
| 276 | 279 |
} else { // Bind mount
|
| 277 | 280 |
id, source, err := parseVolumeSource(hostPath) |
| ... | ... |
@@ -287,6 +291,37 @@ func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
|
| 287 | 287 |
return container.ToDisk() |
| 288 | 288 |
} |
| 289 | 289 |
|
| 290 |
+// migrateVolume moves the contents of a volume created pre Docker 1.7 |
|
| 291 |
+// to the location expected by the local driver. Steps: |
|
| 292 |
+// 1. Save old directory that includes old volume's config json file. |
|
| 293 |
+// 2. Move virtual directory with content to where the local driver expects it to be. |
|
| 294 |
+// 3. Remove the backup of the old volume config. |
|
| 295 |
+func (daemon *Daemon) migrateVolume(id, vfs string) error {
|
|
| 296 |
+ volumeInfo := filepath.Join(daemon.root, defaultVolumesPathName, id) |
|
| 297 |
+ backup := filepath.Join(daemon.root, defaultVolumesPathName, id+".back") |
|
| 298 |
+ |
|
| 299 |
+ var err error |
|
| 300 |
+ if err = os.Rename(volumeInfo, backup); err != nil {
|
|
| 301 |
+ return err |
|
| 302 |
+ } |
|
| 303 |
+ defer func() {
|
|
| 304 |
+ // Put old configuration back in place in case one of the next steps fails. |
|
| 305 |
+ if err != nil {
|
|
| 306 |
+ os.Rename(backup, volumeInfo) |
|
| 307 |
+ } |
|
| 308 |
+ }() |
|
| 309 |
+ |
|
| 310 |
+ if err = os.Rename(vfs, volumeInfo); err != nil {
|
|
| 311 |
+ return err |
|
| 312 |
+ } |
|
| 313 |
+ |
|
| 314 |
+ if err = os.RemoveAll(backup); err != nil {
|
|
| 315 |
+ logrus.Errorf("Unable to remove volume info backup directory %s: %v", backup, err)
|
|
| 316 |
+ } |
|
| 317 |
+ |
|
| 318 |
+ return nil |
|
| 319 |
+} |
|
| 320 |
+ |
|
| 290 | 321 |
func createVolume(name, driverName string) (volume.Volume, error) {
|
| 291 | 322 |
vd, err := getVolumeDriver(driverName) |
| 292 | 323 |
if err != nil {
|