Browse code

Lazy initialize Volume on container Mount object

Currently on daemon start volumes are "created" which involves invoking
a volume driver if needed. If this process fails the mount is left in a
bad state in which there is no source or Volume set. This now becomes
an unrecoverable state in which that container can not be started. The
only way to fix is to restart the daemon and hopefully you don't get
another error on startup.

This change moves "createVolume" to be done at container start. If the
start fails it leaves it in the state in which you can try another
start. If the second start can contact the volume driver everything
will recover fine.

Signed-off-by: Darren Shepherd <darren@rancher.com>

Darren Shepherd authored on 2015/12/10 04:39:31
Showing 4 changed files
... ...
@@ -283,10 +283,6 @@ func (daemon *Daemon) Register(container *container.Container) error {
283 283
 		}
284 284
 	}
285 285
 
286
-	if err := daemon.prepareMountPoints(container); err != nil {
287
-		return err
288
-	}
289
-
290 286
 	return nil
291 287
 }
292 288
 
... ...
@@ -8,20 +8,6 @@ import (
8 8
 	volumestore "github.com/docker/docker/volume/store"
9 9
 )
10 10
 
11
-func (daemon *Daemon) prepareMountPoints(container *container.Container) error {
12
-	for _, config := range container.MountPoints {
13
-		if len(config.Driver) > 0 {
14
-			v, err := daemon.volumes.GetWithRef(config.Name, config.Driver, container.ID)
15
-			if err != nil {
16
-				return err
17
-			}
18
-
19
-			config.Volume = v
20
-		}
21
-	}
22
-	return nil
23
-}
24
-
25 11
 func (daemon *Daemon) removeMountPoints(container *container.Container, rm bool) error {
26 12
 	var rmErrors []string
27 13
 	for _, m := range container.MountPoints {
... ...
@@ -20,6 +20,14 @@ import (
20 20
 func (daemon *Daemon) setupMounts(container *container.Container) ([]execdriver.Mount, error) {
21 21
 	var mounts []execdriver.Mount
22 22
 	for _, m := range container.MountPoints {
23
+		// Lazy initialize m.Volume if needed.  This happens after a daemon restart
24
+		if len(m.Driver) > 0 && m.Volume == nil {
25
+			v, err := daemon.createVolume(m.Name, m.Driver, nil)
26
+			if err != nil {
27
+				return nil, err
28
+			}
29
+			m.Volume = v
30
+		}
23 31
 		path, err := m.Setup()
24 32
 		if err != nil {
25 33
 			return nil, err
... ...
@@ -18,6 +18,14 @@ import (
18 18
 func (daemon *Daemon) setupMounts(container *container.Container) ([]execdriver.Mount, error) {
19 19
 	var mnts []execdriver.Mount
20 20
 	for _, mount := range container.MountPoints { // type is volume.MountPoint
21
+		// Lazy initialize m.Volume if needed.  This happens after a daemon restart
22
+		if len(m.Driver) > 0 && m.Volume == nil {
23
+			v, err := daemon.createVolume(m.Name, m.Driver, nil)
24
+			if err != nil {
25
+				return nil, err
26
+			}
27
+			m.Volume = v
28
+		}
21 29
 		// If there is no source, take it from the volume path
22 30
 		s := mount.Source
23 31
 		if s == "" && mount.Volume != nil {