Browse code

graphdriver: prefer prior driver state

Before this, a storage driver would be defaulted to based on the
priority list, and only print a warning if there is state from other
drivers.

This meant a reordering of priority list would "break" users in an
upgrade of docker, such that there images in the prior driver's state
were now invisible.

With this change, prior state is scanned, and if present that driver is
preferred.

As such, we can reorder the priority list, and after an upgrade,
existing installs with prior drivers can have a contiguous experience,
while fresh installs may default to a driver in the new priority list.

Ref: https://github.com/docker/docker/pull/11962#issuecomment-88274858

Signed-off-by: Vincent Batts <vbatts@redhat.com>

Vincent Batts authored on 2015/04/02 03:12:15
Showing 1 changed files
... ...
@@ -146,10 +146,40 @@ func GetDriver(name, home string, options []string) (Driver, error) {
146 146
 func New(root string, options []string) (driver Driver, err error) {
147 147
 	for _, name := range []string{os.Getenv("DOCKER_DRIVER"), DefaultDriver} {
148 148
 		if name != "" {
149
+			logrus.Infof("[graphdriver] trying provided driver %q", name) // so the logs show specified driver
149 150
 			return GetDriver(name, root, options)
150 151
 		}
151 152
 	}
152 153
 
154
+	// Guess for prior driver
155
+	priorDrivers := scanPriorDrivers(root)
156
+	for _, name := range priority {
157
+		if name == "vfs" {
158
+			// don't use vfs even if there is state present.
159
+			continue
160
+		}
161
+		for _, prior := range priorDrivers {
162
+			// of the state found from prior drivers, check in order of our priority
163
+			// which we would prefer
164
+			if prior == name {
165
+				driver, err = GetDriver(name, root, options)
166
+				if err != nil {
167
+					// unlike below, we will return error here, because there is prior
168
+					// state, and now it is no longer supported/prereq/compatible, so
169
+					// something changed and needs attention. Otherwise the daemon's
170
+					// images would just "disappear".
171
+					logrus.Errorf("[graphdriver] prior storage driver %q failed: %s", name, err)
172
+					return nil, err
173
+				}
174
+				if err := checkPriorDriver(name, root); err != nil {
175
+					return nil, err
176
+				}
177
+				logrus.Infof("[graphdriver] using prior storage driver %q", name)
178
+				return driver, nil
179
+			}
180
+		}
181
+	}
182
+
153 183
 	// Check for priority drivers first
154 184
 	for _, name := range priority {
155 185
 		driver, err = GetDriver(name, root, options)
... ...
@@ -159,34 +189,47 @@ func New(root string, options []string) (driver Driver, err error) {
159 159
 			}
160 160
 			return nil, err
161 161
 		}
162
-		checkPriorDriver(name, root)
163 162
 		return driver, nil
164 163
 	}
165 164
 
166 165
 	// Check all registered drivers if no priority driver is found
167
-	for name, initFunc := range drivers {
166
+	for _, initFunc := range drivers {
168 167
 		if driver, err = initFunc(root, options); err != nil {
169 168
 			if err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS {
170 169
 				continue
171 170
 			}
172 171
 			return nil, err
173 172
 		}
174
-		checkPriorDriver(name, root)
175 173
 		return driver, nil
176 174
 	}
177 175
 	return nil, fmt.Errorf("No supported storage backend found")
178 176
 }
179 177
 
180
-func checkPriorDriver(name, root string) {
178
+// scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
179
+func scanPriorDrivers(root string) []string {
180
+	priorDrivers := []string{}
181
+	for driver := range drivers {
182
+		p := path.Join(root, driver)
183
+		if _, err := os.Stat(p); err == nil {
184
+			priorDrivers = append(priorDrivers, driver)
185
+		}
186
+	}
187
+	return priorDrivers
188
+}
189
+
190
+func checkPriorDriver(name, root string) error {
181 191
 	priorDrivers := []string{}
182
-	for prior := range drivers {
192
+	for _, prior := range scanPriorDrivers(root) {
183 193
 		if prior != name && prior != "vfs" {
184 194
 			if _, err := os.Stat(path.Join(root, prior)); err == nil {
185 195
 				priorDrivers = append(priorDrivers, prior)
186 196
 			}
187 197
 		}
188 198
 	}
199
+
189 200
 	if len(priorDrivers) > 0 {
190
-		logrus.Warnf("Graphdriver %s selected. Your graphdriver directory %s already contains data managed by other graphdrivers: %s", name, root, strings.Join(priorDrivers, ","))
201
+
202
+		return errors.New(fmt.Sprintf("%q contains other graphdrivers: %s; Please cleanup or explicitly choose storage driver (-s <DRIVER>)", root, strings.Join(priorDrivers, ",")))
191 203
 	}
204
+	return nil
192 205
 }