Merge pull request #33236 from cpuguy83/17.03.2_cherry_picks
17.03.2 cherry picks
This commit is contained in:
commit
8b9c66e80d
8 changed files with 118 additions and 67 deletions
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -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.")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 (
|
||||
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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"
|
||||
|
@ -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)
|
||||
|
|
|
@ -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 == "" {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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}},
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue