Skip to content

17.03.2 cherry picks #33236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 17, 2017
121 changes: 76 additions & 45 deletions cli/command/system/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"strings"
"time"

"golang.org/x/net/context"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli"
Expand All @@ -17,6 +15,7 @@ import (
"github.com/docker/docker/utils/templates"
"github.com/docker/go-units"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)

type infoOptions struct {
Expand Down Expand Up @@ -66,11 +65,6 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
if info.DriverStatus != nil {
for _, pair := range info.DriverStatus {
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])

// print a warning if devicemapper is using a loopback file
if pair[0] == "Data loop file" {
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.")
}
}

}
Expand Down Expand Up @@ -228,43 +222,6 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress)
}

// Only output these warnings if the server does not support these features
if info.OSType != "windows" {
if !info.MemoryLimit {
fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
}
if !info.SwapLimit {
fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
}
if !info.KernelMemory {
fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
}
if !info.OomKillDisable {
fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
}
if !info.CPUCfsQuota {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
}
if !info.CPUCfsPeriod {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
}
if !info.CPUShares {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
}
if !info.CPUSet {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
}
if !info.IPv4Forwarding {
fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
}
if !info.BridgeNfIptables {
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
}
if !info.BridgeNfIP6tables {
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
}
}

if info.Labels != nil {
fmt.Fprintln(dockerCli.Out(), "Labels:")
for _, attribute := range info.Labels {
Expand Down Expand Up @@ -317,11 +274,85 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
}
}

fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n", info.LiveRestoreEnabled)
fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n\n", info.LiveRestoreEnabled)

// Only output these warnings if the server does not support these features
if info.OSType != "windows" {
printStorageDriverWarnings(dockerCli, info)

if !info.MemoryLimit {
fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
}
if !info.SwapLimit {
fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
}
if !info.KernelMemory {
fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support")
}
if !info.OomKillDisable {
fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
}
if !info.CPUCfsQuota {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
}
if !info.CPUCfsPeriod {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
}
if !info.CPUShares {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
}
if !info.CPUSet {
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
}
if !info.IPv4Forwarding {
fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
}
if !info.BridgeNfIptables {
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
}
if !info.BridgeNfIP6tables {
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
}
}

return nil
}

func printStorageDriverWarnings(dockerCli *command.DockerCli, info types.Info) {
if info.DriverStatus == nil {
return
}

for _, pair := range info.DriverStatus {
if pair[0] == "Data loop file" {
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)
}
if pair[0] == "Supports d_type" && pair[1] == "false" {
backingFs := getBackingFs(info)

msg := fmt.Sprintf("WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n", info.Driver, backingFs)
if backingFs == "xfs" {
msg += " Reformat the filesystem with ftype=1 to enable d_type support.\n"
}
msg += " Running without d_type support will not be supported in future releases."
fmt.Fprintln(dockerCli.Err(), msg)
}
}
}

func getBackingFs(info types.Info) string {
if info.DriverStatus == nil {
return ""
}

for _, pair := range info.DriverStatus {
if pair[0] == "Backing Filesystem" {
return pair[1]
}
}
return ""
}

func formatInfo(dockerCli *command.DockerCli, info types.Info, format string) error {
tmpl, err := templates.Parse(format)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions daemon/container_operations_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
}
}

label.Relabel(localMountPath, c.MountLabel, false)

// remount secrets ro
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "remount,ro,"+tmpfsOwnership); err != nil {
return errors.Wrap(err, "unable to remount secret dir as readonly")
Expand Down
4 changes: 0 additions & 4 deletions daemon/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/docker/docker/container"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
"github.com/opencontainers/runc/libcontainer/label"
)

var (
Expand Down Expand Up @@ -195,9 +194,6 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
return err
}

if err := label.Relabel(mp.Source, container.MountLabel, false); err != nil {
return err
}
mp.Volume = v
mp.Name = v.Name()
mp.Driver = v.DriverName()
Expand Down
2 changes: 1 addition & 1 deletion plugin/backend_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ func (pm *Manager) Remove(name string, config *types.PluginRmConfig) error {
func getMounts(root string) ([]string, error) {
infos, err := mount.GetMounts()
if err != nil {
return nil, errors.Wrap(err, "failed to read mount table while performing recursive unmount")
return nil, errors.Wrap(err, "failed to read mount table")
}

var mounts []string
Expand Down
10 changes: 9 additions & 1 deletion plugin/manager_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,17 @@ func (pm *Manager) upgradePlugin(p *v2.Plugin, configDigest digest.Digest, blobs

pdir := filepath.Join(pm.config.Root, p.PluginObj.ID)
orig := filepath.Join(pdir, "rootfs")

// Make sure nothing is mounted
// This could happen if the plugin was disabled with `-f` with active mounts.
// If there is anything in `orig` is still mounted, this should error out.
if err := recursiveUnmount(orig); err != nil {
return err
}

backup := orig + "-old"
if err := os.Rename(orig, backup); err != nil {
return err
return errors.Wrap(err, "error backing up plugin data before upgrade")
}

defer func() {
Expand Down
8 changes: 6 additions & 2 deletions volume/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,11 @@ func lookupVolume(driverName, volumeName string) (volume.Volume, error) {
if err != nil {
err = errors.Cause(err)
if _, ok := err.(net.Error); ok {
return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName())
if v != nil {
volumeName = v.Name()
driverName = v.DriverName()
}
return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
}

// At this point, the error could be anything from the driver, such as "no such volume"
Expand All @@ -542,7 +546,7 @@ func (s *VolumeStore) Remove(v volume.Volume) error {

vd, err := volumedrivers.GetDriver(v.DriverName())
if err != nil {
return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
}

logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
Expand Down
30 changes: 20 additions & 10 deletions volume/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,20 @@ type MountPoint struct {

// Setup sets up a mount point by either mounting the volume if it is
// configured, or creating the source directory if supplied.
func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (string, error) {
func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (path string, err error) {
defer func() {
if err == nil {
if label.RelabelNeeded(m.Mode) {
if err = label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil {
path = ""
err = errors.Wrapf(err, "error setting label on mount source '%s'", m.Source)
return
}
}
}
return
}()

if m.Volume != nil {
id := m.ID
if id == "" {
Expand Down Expand Up @@ -152,11 +165,6 @@ func (m *MountPoint) Setup(mountLabel string, rootUID, rootGID int) (string, err
}
}
}
if label.RelabelNeeded(m.Mode) {
if err := label.Relabel(m.Source, mountLabel, label.IsShared(m.Mode)); err != nil {
return "", errors.Wrapf(err, "error setting label on mount source '%s'", m.Source)
}
}
return m.Source, nil
}

Expand Down Expand Up @@ -303,10 +311,12 @@ func ParseMountSpec(cfg mounttypes.Mount, options ...func(*validateOpts)) (*Moun
}
case mounttypes.TypeBind:
mp.Source = clean(convertSlash(cfg.Source))
if cfg.BindOptions != nil {
if len(cfg.BindOptions.Propagation) > 0 {
mp.Propagation = cfg.BindOptions.Propagation
}
if cfg.BindOptions != nil && len(cfg.BindOptions.Propagation) > 0 {
mp.Propagation = cfg.BindOptions.Propagation
} else {
// If user did not specify a propagation mode, get
// default propagation mode.
mp.Propagation = DefaultPropagationMode
}
case mounttypes.TypeTmpfs:
// NOP
Expand Down
8 changes: 4 additions & 4 deletions volume/volume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,10 @@ func TestParseMountSpec(t *testing.T) {
defer os.RemoveAll(testDir)

cases := []c{
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true}},
{mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath}},
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, RW: true, Propagation: DefaultPropagationMode}},
{mount.Mount{Type: mount.TypeBind, Source: testDir + string(os.PathSeparator), Target: testDestinationPath, ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
{mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath + string(os.PathSeparator), ReadOnly: true}, MountPoint{Type: mount.TypeBind, Source: testDir, Destination: testDestinationPath, Propagation: DefaultPropagationMode}},
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: DefaultCopyMode}},
{mount.Mount{Type: mount.TypeVolume, Target: testDestinationPath + string(os.PathSeparator)}, MountPoint{Type: mount.TypeVolume, Destination: testDestinationPath, RW: true, CopyData: DefaultCopyMode}},
}
Expand Down