Browse code

add d_type warning to docker info, and optimize output

The overlay(2) drivers were moved up in the list of storage drivers,
and are known to have problems if the backing filesystem does not
support d_type.

Commit 2e20e63da2a8a0ffbbb3f2146f87559e17f43046 added a warning,
which is logged in the daemon logs, however, many users do not
check those logs, and may overlook this warning.

This patch adds the same warning to the output of `docker info`
so that the warning is more easily found.

In addition, the output of warnings printed by `docker info` is
optimized, by;

- moving all warnings to the _end_ of the output, instead of
mixing them with the regular output
- wrapping the storage-driver warnings, so that they are more
easily readable

Example output with this patch applied
============================================

devicemapper using loopback devices:

...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

overlay2 on xfs without d_type support;

...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

WARNING: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior.
Reformat the filesystem with ftype=1 to enable d_type support.
Running without d_type support will not be supported in future releases.
WARNING: bridge-nf-call-iptables is disabled

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 19215597982232f65dcbc873e54e632b99cddecc)
Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Sebastiaan van Stijn authored on 2017/02/23 21:36:57
Showing 1 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 {