Merge pull request #35677 from fcrisciani/netdb-debug-tool
Netdb debug tool
diff --git a/api/swagger.yaml b/api/swagger.yaml
index b7ed3b8..7a5017f 100644
--- a/api/swagger.yaml
+++ b/api/swagger.yaml
@@ -254,6 +254,7 @@
properties:
Propagation:
description: "A propagation mode with the value `[r]private`, `[r]shared`, or `[r]slave`."
+ type: "string"
enum:
- "private"
- "rprivate"
@@ -823,9 +824,7 @@
type: "string"
Cmd:
description: "Command to run specified as a string or an array of strings."
- type:
- - "array"
- - "string"
+ type: "array"
items:
type: "string"
Healthcheck:
@@ -853,9 +852,7 @@
The entry point for the container as a string or an array of strings.
If the array consists of exactly one empty string (`[""]`) then the entry point is reset to system default (i.e., the entry point used by docker when there is no `ENTRYPOINT` instruction in the `Dockerfile`).
- type:
- - "array"
- - "string"
+ type: "array"
items:
type: "string"
NetworkDisabled:
diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go
index 11e763d..248b8bf 100644
--- a/daemon/graphdriver/aufs/aufs.go
+++ b/daemon/graphdriver/aufs/aufs.go
@@ -89,7 +89,16 @@
return nil, graphdriver.ErrNotSupported
}
- fsMagic, err := graphdriver.GetFSMagic(root)
+ // Perform feature detection on /var/lib/docker/aufs if it's an existing directory.
+ // This covers situations where /var/lib/docker/aufs is a mount, and on a different
+ // filesystem than /var/lib/docker.
+ // If the path does not exist, fall back to using /var/lib/docker for feature detection.
+ testdir := root
+ if _, err := os.Stat(testdir); os.IsNotExist(err) {
+ testdir = filepath.Dir(testdir)
+ }
+
+ fsMagic, err := graphdriver.GetFSMagic(testdir)
if err != nil {
return nil, err
}
diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go
index 0dabf71..57313c9 100644
--- a/daemon/graphdriver/btrfs/btrfs.go
+++ b/daemon/graphdriver/btrfs/btrfs.go
@@ -51,7 +51,16 @@
// An error is returned if BTRFS is not supported.
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
- fsMagic, err := graphdriver.GetFSMagic(home)
+ // Perform feature detection on /var/lib/docker/btrfs if it's an existing directory.
+ // This covers situations where /var/lib/docker/btrfs is a mount, and on a different
+ // filesystem than /var/lib/docker.
+ // If the path does not exist, fall back to using /var/lib/docker for feature detection.
+ testdir := home
+ if _, err := os.Stat(testdir); os.IsNotExist(err) {
+ testdir = filepath.Dir(testdir)
+ }
+
+ fsMagic, err := graphdriver.GetFSMagic(testdir)
if err != nil {
return nil, err
}
diff --git a/daemon/graphdriver/driver.go b/daemon/graphdriver/driver.go
index d08c6dc..ceb49b9 100644
--- a/daemon/graphdriver/driver.go
+++ b/daemon/graphdriver/driver.go
@@ -1,7 +1,6 @@
package graphdriver
import (
- "errors"
"fmt"
"io"
"os"
@@ -28,13 +27,6 @@
var (
// All registered drivers
drivers map[string]InitFunc
-
- // ErrNotSupported returned when driver is not supported.
- ErrNotSupported = errors.New("driver not supported")
- // ErrPrerequisites returned when driver does not meet prerequisites.
- ErrPrerequisites = errors.New("prerequisites for driver not satisfied (wrong filesystem?)")
- // ErrIncompatibleFS returned when file system is not supported.
- ErrIncompatibleFS = fmt.Errorf("backing file system is unsupported for this graph driver")
)
//CreateOpts contains optional arguments for Create() and CreateReadWrite()
@@ -248,7 +240,7 @@
for _, name := range list {
driver, err := getBuiltinDriver(name, config.Root, config.DriverOptions, config.UIDMaps, config.GIDMaps)
if err != nil {
- if isDriverNotSupported(err) {
+ if IsDriverNotSupported(err) {
continue
}
return nil, err
@@ -260,7 +252,7 @@
for name, initFunc := range drivers {
driver, err := initFunc(filepath.Join(config.Root, name), config.DriverOptions, config.UIDMaps, config.GIDMaps)
if err != nil {
- if isDriverNotSupported(err) {
+ if IsDriverNotSupported(err) {
continue
}
return nil, err
@@ -270,12 +262,6 @@
return nil, fmt.Errorf("No supported storage backend found")
}
-// isDriverNotSupported returns true if the error initializing
-// the graph driver is a non-supported error.
-func isDriverNotSupported(err error) bool {
- return err == ErrNotSupported || err == ErrPrerequisites || err == ErrIncompatibleFS
-}
-
// scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
func scanPriorDrivers(root string) map[string]bool {
driversMap := make(map[string]bool)
@@ -291,6 +277,18 @@
return driversMap
}
+// IsInitialized checks if the driver's home-directory exists and is non-empty.
+func IsInitialized(driverHome string) bool {
+ _, err := os.Stat(driverHome)
+ if os.IsNotExist(err) {
+ return false
+ }
+ if err != nil {
+ logrus.Warnf("graphdriver.IsInitialized: stat failed: %v", err)
+ }
+ return !isEmptyDir(driverHome)
+}
+
// isEmptyDir checks if a directory is empty. It is used to check if prior
// storage-driver directories exist. If an error occurs, it also assumes the
// directory is not empty (which preserves the behavior _before_ this check
diff --git a/daemon/graphdriver/driver_linux.go b/daemon/graphdriver/driver_linux.go
index aa3cfc9..f59862d 100644
--- a/daemon/graphdriver/driver_linux.go
+++ b/daemon/graphdriver/driver_linux.go
@@ -3,8 +3,6 @@
package graphdriver
import (
- "path/filepath"
-
"github.com/docker/docker/pkg/mount"
"golang.org/x/sys/unix"
)
@@ -82,7 +80,7 @@
// GetFSMagic returns the filesystem id given the path.
func GetFSMagic(rootpath string) (FsMagic, error) {
var buf unix.Statfs_t
- if err := unix.Statfs(filepath.Dir(rootpath), &buf); err != nil {
+ if err := unix.Statfs(rootpath, &buf); err != nil {
return 0, err
}
return FsMagic(buf.Type), nil
diff --git a/daemon/graphdriver/errors.go b/daemon/graphdriver/errors.go
new file mode 100644
index 0000000..dd52ee4
--- /dev/null
+++ b/daemon/graphdriver/errors.go
@@ -0,0 +1,36 @@
+package graphdriver
+
+const (
+ // ErrNotSupported returned when driver is not supported.
+ ErrNotSupported NotSupportedError = "driver not supported"
+ // ErrPrerequisites returned when driver does not meet prerequisites.
+ ErrPrerequisites NotSupportedError = "prerequisites for driver not satisfied (wrong filesystem?)"
+ // ErrIncompatibleFS returned when file system is not supported.
+ ErrIncompatibleFS NotSupportedError = "backing file system is unsupported for this graph driver"
+)
+
+// ErrUnSupported signals that the graph-driver is not supported on the current configuration
+type ErrUnSupported interface {
+ NotSupported()
+}
+
+// NotSupportedError signals that the graph-driver is not supported on the current configuration
+type NotSupportedError string
+
+func (e NotSupportedError) Error() string {
+ return string(e)
+}
+
+// NotSupported signals that a graph-driver is not supported.
+func (e NotSupportedError) NotSupported() {}
+
+// IsDriverNotSupported returns true if the error initializing
+// the graph driver is a non-supported error.
+func IsDriverNotSupported(err error) bool {
+ switch err.(type) {
+ case ErrUnSupported:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/daemon/graphdriver/graphtest/graphtest_unix.go b/daemon/graphdriver/graphtest/graphtest_unix.go
index c25d482..da9443e 100644
--- a/daemon/graphdriver/graphtest/graphtest_unix.go
+++ b/daemon/graphdriver/graphtest/graphtest_unix.go
@@ -42,7 +42,7 @@
d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root})
if err != nil {
t.Logf("graphdriver: %v\n", err)
- if err == graphdriver.ErrNotSupported || err == graphdriver.ErrPrerequisites || err == graphdriver.ErrIncompatibleFS {
+ if graphdriver.IsDriverNotSupported(err) {
t.Skipf("Driver %s not supported", name)
}
t.Fatal(err)
diff --git a/daemon/graphdriver/overlay/overlay.go b/daemon/graphdriver/overlay/overlay.go
index 647a86d..bcb21d8 100644
--- a/daemon/graphdriver/overlay/overlay.go
+++ b/daemon/graphdriver/overlay/overlay.go
@@ -10,6 +10,7 @@
"os"
"os/exec"
"path"
+ "path/filepath"
"strconv"
"github.com/docker/docker/daemon/graphdriver"
@@ -119,7 +120,16 @@
return nil, graphdriver.ErrNotSupported
}
- fsMagic, err := graphdriver.GetFSMagic(home)
+ // Perform feature detection on /var/lib/docker/overlay if it's an existing directory.
+ // This covers situations where /var/lib/docker/overlay is a mount, and on a different
+ // filesystem than /var/lib/docker.
+ // If the path does not exist, fall back to using /var/lib/docker for feature detection.
+ testdir := home
+ if _, err := os.Stat(testdir); os.IsNotExist(err) {
+ testdir = filepath.Dir(testdir)
+ }
+
+ fsMagic, err := graphdriver.GetFSMagic(testdir)
if err != nil {
return nil, err
}
@@ -128,11 +138,23 @@
}
switch fsMagic {
- case graphdriver.FsMagicAufs, graphdriver.FsMagicBtrfs, graphdriver.FsMagicOverlay, graphdriver.FsMagicZfs, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs:
+ case graphdriver.FsMagicAufs, graphdriver.FsMagicBtrfs, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs, graphdriver.FsMagicOverlay, graphdriver.FsMagicZfs:
logrus.Errorf("'overlay' is not supported over %s", backingFs)
return nil, graphdriver.ErrIncompatibleFS
}
+ supportsDType, err := fsutils.SupportsDType(testdir)
+ if err != nil {
+ return nil, err
+ }
+ if !supportsDType {
+ if !graphdriver.IsInitialized(home) {
+ return nil, overlayutils.ErrDTypeNotSupported("overlay", backingFs)
+ }
+ // allow running without d_type only for existing setups (#27443)
+ logrus.Warn(overlayutils.ErrDTypeNotSupported("overlay", backingFs))
+ }
+
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
return nil, err
@@ -146,15 +168,6 @@
return nil, err
}
- supportsDType, err := fsutils.SupportsDType(home)
- if err != nil {
- return nil, err
- }
- if !supportsDType {
- // not a fatal error until v17.12 (#27443)
- logrus.Warn(overlayutils.ErrDTypeNotSupported("overlay", backingFs))
- }
-
d := &Driver{
home: home,
uidMaps: uidMaps,
diff --git a/daemon/graphdriver/overlay2/overlay.go b/daemon/graphdriver/overlay2/overlay.go
index e660d80..f1731ea 100644
--- a/daemon/graphdriver/overlay2/overlay.go
+++ b/daemon/graphdriver/overlay2/overlay.go
@@ -136,7 +136,16 @@
return nil, err
}
- fsMagic, err := graphdriver.GetFSMagic(home)
+ // Perform feature detection on /var/lib/docker/overlay2 if it's an existing directory.
+ // This covers situations where /var/lib/docker/overlay2 is a mount, and on a different
+ // filesystem than /var/lib/docker.
+ // If the path does not exist, fall back to using /var/lib/docker for feature detection.
+ testdir := home
+ if _, err := os.Stat(testdir); os.IsNotExist(err) {
+ testdir = filepath.Dir(testdir)
+ }
+
+ fsMagic, err := graphdriver.GetFSMagic(testdir)
if err != nil {
return nil, err
}
@@ -144,9 +153,8 @@
backingFs = fsName
}
- // check if they are running over btrfs, aufs, zfs, overlay, or ecryptfs
switch fsMagic {
- case graphdriver.FsMagicAufs, graphdriver.FsMagicZfs, graphdriver.FsMagicOverlay, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs:
+ case graphdriver.FsMagicAufs, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs, graphdriver.FsMagicOverlay, graphdriver.FsMagicZfs:
logrus.Errorf("'overlay2' is not supported over %s", backingFs)
return nil, graphdriver.ErrIncompatibleFS
case graphdriver.FsMagicBtrfs:
@@ -165,12 +173,23 @@
if opts.overrideKernelCheck {
logrus.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update")
} else {
- if err := supportsMultipleLowerDir(filepath.Dir(home)); err != nil {
+ if err := supportsMultipleLowerDir(testdir); err != nil {
logrus.Debugf("Multiple lower dirs not supported: %v", err)
return nil, graphdriver.ErrNotSupported
}
}
}
+ supportsDType, err := fsutils.SupportsDType(testdir)
+ if err != nil {
+ return nil, err
+ }
+ if !supportsDType {
+ if !graphdriver.IsInitialized(home) {
+ return nil, overlayutils.ErrDTypeNotSupported("overlay2", backingFs)
+ }
+ // allow running without d_type only for existing setups (#27443)
+ logrus.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs))
+ }
rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
if err != nil {
@@ -185,15 +204,6 @@
return nil, err
}
- supportsDType, err := fsutils.SupportsDType(home)
- if err != nil {
- return nil, err
- }
- if !supportsDType {
- // not a fatal error until v17.12 (#27443)
- logrus.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs))
- }
-
d := &Driver{
home: home,
uidMaps: uidMaps,
diff --git a/daemon/graphdriver/overlayutils/overlayutils.go b/daemon/graphdriver/overlayutils/overlayutils.go
index 7491c34..9f71c60 100644
--- a/daemon/graphdriver/overlayutils/overlayutils.go
+++ b/daemon/graphdriver/overlayutils/overlayutils.go
@@ -3,8 +3,9 @@
package overlayutils
import (
- "errors"
"fmt"
+
+ "github.com/docker/docker/daemon/graphdriver"
)
// ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type.
@@ -13,6 +14,7 @@
if backingFs == "xfs" {
msg += " Reformat the filesystem with ftype=1 to enable d_type support."
}
- msg += " Running without d_type support will no longer be supported in Docker 17.12."
- return errors.New(msg)
+ msg += " Backing filesystems without d_type support are not supported."
+
+ return graphdriver.NotSupportedError(msg)
}