Browse code

Merge pull request #33236 from cpuguy83/17.03.2_cherry_picks

17.03.2 cherry picks

Sebastiaan van Stijn authored on 2017/05/17 18:56:44
Showing 8 changed files
... ...
@@ -6,8 +6,6 @@ import (
6 6
 	"strings"
7 7
 	"time"
8 8
 
9
-	"golang.org/x/net/context"
10
-
11 9
 	"github.com/docker/docker/api/types"
12 10
 	"github.com/docker/docker/api/types/swarm"
13 11
 	"github.com/docker/docker/cli"
... ...
@@ -17,6 +15,7 @@ import (
17 17
 	"github.com/docker/docker/utils/templates"
18 18
 	"github.com/docker/go-units"
19 19
 	"github.com/spf13/cobra"
20
+	"golang.org/x/net/context"
20 21
 )
21 22
 
22 23
 type infoOptions struct {
... ...
@@ -66,11 +65,6 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
66 66
 	if info.DriverStatus != nil {
67 67
 		for _, pair := range info.DriverStatus {
68 68
 			fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
69
-
70
-			// print a warning if devicemapper is using a loopback file
71
-			if pair[0] == "Data loop file" {
72
-				fmt.Fprintln(dockerCli.Err(), " WARNING: Usage of loopback devices is strongly discouraged for production use. Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.")
73
-			}
74 69
 		}
75 70
 
76 71
 	}
... ...
@@ -228,43 +222,6 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
228 228
 		fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress)
229 229
 	}
230 230
 
231
-	// Only output these warnings if the server does not support these features
232
-	if info.OSType != "windows" {
233
-		if !info.MemoryLimit {
234
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
235
-		}
236
-		if !info.SwapLimit {
237
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
238
-		}
239
-		if !info.KernelMemory {
240
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
241
-		}
242
-		if !info.OomKillDisable {
243
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
244
-		}
245
-		if !info.CPUCfsQuota {
246
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
247
-		}
248
-		if !info.CPUCfsPeriod {
249
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
250
-		}
251
-		if !info.CPUShares {
252
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
253
-		}
254
-		if !info.CPUSet {
255
-			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
256
-		}
257
-		if !info.IPv4Forwarding {
258
-			fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
259
-		}
260
-		if !info.BridgeNfIptables {
261
-			fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
262
-		}
263
-		if !info.BridgeNfIP6tables {
264
-			fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
265
-		}
266
-	}
267
-
268 231
 	if info.Labels != nil {
269 232
 		fmt.Fprintln(dockerCli.Out(), "Labels:")
270 233
 		for _, attribute := range info.Labels {
... ...
@@ -317,11 +274,85 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
317 317
 		}
318 318
 	}
319 319
 
320
-	fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n", info.LiveRestoreEnabled)
320
+	fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n\n", info.LiveRestoreEnabled)
321
+
322
+	// Only output these warnings if the server does not support these features
323
+	if info.OSType != "windows" {
324
+		printStorageDriverWarnings(dockerCli, info)
325
+
326
+		if !info.MemoryLimit {
327
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
328
+		}
329
+		if !info.SwapLimit {
330
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
331
+		}
332
+		if !info.KernelMemory {
333
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
334
+		}
335
+		if !info.OomKillDisable {
336
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
337
+		}
338
+		if !info.CPUCfsQuota {
339
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
340
+		}
341
+		if !info.CPUCfsPeriod {
342
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
343
+		}
344
+		if !info.CPUShares {
345
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
346
+		}
347
+		if !info.CPUSet {
348
+			fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
349
+		}
350
+		if !info.IPv4Forwarding {
351
+			fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
352
+		}
353
+		if !info.BridgeNfIptables {
354
+			fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
355
+		}
356
+		if !info.BridgeNfIP6tables {
357
+			fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
358
+		}
359
+	}
321 360
 
322 361
 	return nil
323 362
 }
324 363
 
364
+func printStorageDriverWarnings(dockerCli *command.DockerCli, info types.Info) {
365
+	if info.DriverStatus == nil {
366
+		return
367
+	}
368
+
369
+	for _, pair := range info.DriverStatus {
370
+		if pair[0] == "Data loop file" {
371
+			fmt.Fprintf(dockerCli.Err(), "WARNING: %s: usage of loopback devices is strongly discouraged for production use.\n         Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.\n", info.Driver)
372
+		}
373
+		if pair[0] == "Supports d_type" && pair[1] == "false" {
374
+			backingFs := getBackingFs(info)
375
+
376
+			msg := fmt.Sprintf("WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n", info.Driver, backingFs)
377
+			if backingFs == "xfs" {
378
+				msg += "         Reformat the filesystem with ftype=1 to enable d_type support.\n"
379
+			}
380
+			msg += "         Running without d_type support will not be supported in future releases."
381
+			fmt.Fprintln(dockerCli.Err(), msg)
382
+		}
383
+	}
384
+}
385
+
386
+func getBackingFs(info types.Info) string {
387
+	if info.DriverStatus == nil {
388
+		return ""
389
+	}
390
+
391
+	for _, pair := range info.DriverStatus {
392
+		if pair[0] == "Backing Filesystem" {
393
+			return pair[1]
394
+		}
395
+	}
396
+	return ""
397
+}
398
+
325 399
 func formatInfo(dockerCli *command.DockerCli, info types.Info, format string) error {
326 400
 	tmpl, err := templates.Parse(format)
327 401
 	if err != nil {
... ...
@@ -213,6 +213,8 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
213 213
 		}
214 214
 	}
215 215
 
216
+	label.Relabel(localMountPath, c.MountLabel, false)
217
+
216 218
 	// remount secrets ro
217 219
 	if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "remount,ro,"+tmpfsOwnership); err != nil {
218 220
 		return errors.Wrap(err, "unable to remount secret dir as readonly")
... ...
@@ -16,7 +16,6 @@ import (
16 16
 	"github.com/docker/docker/container"
17 17
 	"github.com/docker/docker/volume"
18 18
 	"github.com/docker/docker/volume/drivers"
19
-	"github.com/opencontainers/runc/libcontainer/label"
20 19
 )
21 20
 
22 21
 var (
... ...
@@ -195,9 +194,6 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
195 195
 				return err
196 196
 			}
197 197
 
198
-			if err := label.Relabel(mp.Source, container.MountLabel, false); err != nil {
199
-				return err
200
-			}
201 198
 			mp.Volume = v
202 199
 			mp.Name = v.Name()
203 200
 			mp.Driver = v.DriverName()
... ...
@@ -575,7 +575,7 @@ func (pm *Manager) Remove(name string, config *types.PluginRmConfig) error {
575 575
 func getMounts(root string) ([]string, error) {
576 576
 	infos, err := mount.GetMounts()
577 577
 	if err != nil {
578
-		return nil, errors.Wrap(err, "failed to read mount table while performing recursive unmount")
578
+		return nil, errors.Wrap(err, "failed to read mount table")
579 579
 	}
580 580
 
581 581
 	var mounts []string
... ...
@@ -171,9 +171,17 @@ func (pm *Manager) upgradePlugin(p *v2.Plugin, configDigest digest.Digest, blobs
171 171
 
172 172
 	pdir := filepath.Join(pm.config.Root, p.PluginObj.ID)
173 173
 	orig := filepath.Join(pdir, "rootfs")
174
+
175
+	// Make sure nothing is mounted
176
+	// This could happen if the plugin was disabled with `-f` with active mounts.
177
+	// If there is anything in `orig` is still mounted, this should error out.
178
+	if err := recursiveUnmount(orig); err != nil {
179
+		return err
180
+	}
181
+
174 182
 	backup := orig + "-old"
175 183
 	if err := os.Rename(orig, backup); err != nil {
176
-		return err
184
+		return errors.Wrap(err, "error backing up plugin data before upgrade")
177 185
 	}
178 186
 
179 187
 	defer func() {
... ...
@@ -519,7 +519,11 @@ func lookupVolume(driverName, volumeName string) (volume.Volume, error) {
519 519
 	if err != nil {
520 520
 		err = errors.Cause(err)
521 521
 		if _, ok := err.(net.Error); ok {
522
-			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName())
522
+			if v != nil {
523
+				volumeName = v.Name()
524
+				driverName = v.DriverName()
525
+			}
526
+			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
523 527
 		}
524 528
 
525 529
 		// At this point, the error could be anything from the driver, such as "no such volume"
... ...
@@ -542,7 +546,7 @@ func (s *VolumeStore) Remove(v volume.Volume) error {
542 542
 
543 543
 	vd, err := volumedrivers.GetDriver(v.DriverName())
544 544
 	if err != nil {
545
-		return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
545
+		return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
546 546
 	}
547 547
 
548 548
 	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
... ...
@@ -124,7 +124,20 @@ type MountPoint struct {
124 124
 
125 125
 // Setup sets up a mount point by either mounting the volume if it is
126 126
 // configured, or creating the source directory if supplied.
127
-func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (string, error) {
127
+func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string, err error) {
128
+	defer func() {
129
+		if err == nil {
130
+			if label.RelabelNeeded(m.Mode) {
131
+				if err = label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil {
132
+					path = ""
133
+					err = errors.Wrapf(err, "error setting label on mount source '%s'", m.Source)
134
+					return
135
+				}
136
+			}
137
+		}
138
+		return
139
+	}()
140
+
128 141
 	if m.Volume != nil {
129 142
 		id := m.ID
130 143
 		if id == "" {
... ...
@@ -152,11 +165,6 @@ func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (string, err
152 152
 			}
153 153
 		}
154 154
 	}
155
-	if label.RelabelNeeded(m.Mode) {
156
-		if err := label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil {
157
-			return "", errors.Wrapf(err, "error setting label on mount source '%s'", m.Source)
158
-		}
159
-	}
160 155
 	return m.Source, nil
161 156
 }
162 157
 
... ...
@@ -303,10 +311,12 @@ func ParseMountSpec(cfg mounttypes.Mount, options ...func(*validateOpts)) (*Moun
303 303
 		}
304 304
 	case mounttypes.TypeBind:
305 305
 		mp.Source = clean(convertSlash(cfg.Source))
306
-		if cfg.BindOptions != nil {
307
-			if len(cfg.BindOptions.Propagation) > 0 {
308
-				mp.Propagation = cfg.BindOptions.Propagation
309
-			}
306
+		if cfg.BindOptions != nil && len(cfg.BindOptions.Propagation) > 0 {
307
+			mp.Propagation = cfg.BindOptions.Propagation
308
+		} else {
309
+			// If user did not specify a propagation mode, get
310
+			// default propagation mode.
311
+			mp.Propagation = DefaultPropagationMode
310 312
 		}
311 313
 	case mounttypes.TypeTmpfs:
312 314
 		// NOP
... ...
@@ -229,10 +229,10 @@ func TestParseMountSpec(t *testing.T) {
229 229
 	defer os.RemoveAll(testDir)
230 230
 
231 231
 	cases := []c{
232
-		{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
233
-		{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true}},
234
-		{mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
235
-		{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
232
+		{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
233
+		{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true, Propagation: DefaultPropagationMode}},
234
+		{mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
235
+		{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
236 236
 		{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: DefaultCopyMode}},
237 237
 		{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath + string(os.PathSeparator)}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: DefaultCopyMode}},
238 238
 	}