github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/info_unix.go (about) 1 // +build !windows 2 3 package daemon // import "github.com/docker/docker/daemon" 4 5 import ( 6 "context" 7 "fmt" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 12 "github.com/docker/docker/api/types" 13 containertypes "github.com/docker/docker/api/types/container" 14 "github.com/docker/docker/dockerversion" 15 "github.com/docker/docker/pkg/sysinfo" 16 "github.com/pkg/errors" 17 "github.com/sirupsen/logrus" 18 ) 19 20 // fillPlatformInfo fills the platform related info. 21 func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) { 22 v.CgroupDriver = daemon.getCgroupDriver() 23 v.CgroupVersion = "1" 24 if sysInfo.CgroupUnified { 25 v.CgroupVersion = "2" 26 } 27 28 v.MemoryLimit = sysInfo.MemoryLimit 29 v.SwapLimit = sysInfo.SwapLimit 30 v.KernelMemory = sysInfo.KernelMemory 31 v.KernelMemoryTCP = sysInfo.KernelMemoryTCP 32 v.OomKillDisable = sysInfo.OomKillDisable 33 v.CPUCfsPeriod = sysInfo.CPUCfsPeriod 34 v.CPUCfsQuota = sysInfo.CPUCfsQuota 35 v.CPUShares = sysInfo.CPUShares 36 v.CPUSet = sysInfo.Cpuset 37 v.PidsLimit = sysInfo.PidsLimit 38 v.Runtimes = daemon.configStore.GetAllRuntimes() 39 v.DefaultRuntime = daemon.configStore.GetDefaultRuntimeName() 40 v.InitBinary = daemon.configStore.GetInitPath() 41 42 defaultRuntimeBinary := daemon.configStore.GetRuntime(v.DefaultRuntime).Path 43 if rv, err := exec.Command(defaultRuntimeBinary, "--version").Output(); err == nil { 44 if _, _, commit, err := parseRuntimeVersion(string(rv)); err != nil { 45 logrus.Warnf("failed to parse %s version: %v", defaultRuntimeBinary, err) 46 v.RuncCommit.ID = "N/A" 47 } else { 48 v.RuncCommit.ID = commit 49 } 50 } else { 51 logrus.Warnf("failed to retrieve %s version: %v", defaultRuntimeBinary, err) 52 v.RuncCommit.ID = "N/A" 53 } 54 55 // runc is now shipped as a separate package. Set "expected" to same value 56 // as "ID" to prevent clients from reporting a version-mismatch 57 v.RuncCommit.Expected = v.RuncCommit.ID 58 59 if rv, err := daemon.containerd.Version(context.Background()); err == nil { 60 v.ContainerdCommit.ID = rv.Revision 61 } else { 62 logrus.Warnf("failed to retrieve containerd version: %v", err) 63 v.ContainerdCommit.ID = "N/A" 64 } 65 66 // containerd is now shipped as a separate package. Set "expected" to same 67 // value as "ID" to prevent clients from reporting a version-mismatch 68 v.ContainerdCommit.Expected = v.ContainerdCommit.ID 69 70 // TODO is there still a need to check the expected version for tini? 71 // if not, we can change this, and just set "Expected" to v.InitCommit.ID 72 v.InitCommit.Expected = dockerversion.InitCommitID 73 74 defaultInitBinary := daemon.configStore.GetInitPath() 75 if rv, err := exec.Command(defaultInitBinary, "--version").Output(); err == nil { 76 if _, commit, err := parseInitVersion(string(rv)); err != nil { 77 logrus.Warnf("failed to parse %s version: %s", defaultInitBinary, err) 78 v.InitCommit.ID = "N/A" 79 } else { 80 v.InitCommit.ID = commit 81 if len(dockerversion.InitCommitID) > len(commit) { 82 v.InitCommit.Expected = dockerversion.InitCommitID[0:len(commit)] 83 } 84 } 85 } else { 86 logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err) 87 v.InitCommit.ID = "N/A" 88 } 89 90 if v.CgroupDriver == cgroupNoneDriver { 91 if v.CgroupVersion == "2" { 92 v.Warnings = append(v.Warnings, "WARNING: Running in rootless-mode without cgroup. To enable cgroup in rootless-mode, you need to set exec-opt \"native.cgroupdriver=systemd\".") 93 } else { 94 v.Warnings = append(v.Warnings, "WARNING: Running in rootless-mode without cgroup. To enable cgroup in rootless-mode, you need to boot the system in cgroup v2 mode and set exec-opt \"native.cgroupdriver=systemd\".") 95 } 96 } else { 97 if !v.MemoryLimit { 98 v.Warnings = append(v.Warnings, "WARNING: No memory limit support") 99 } 100 if !v.SwapLimit { 101 v.Warnings = append(v.Warnings, "WARNING: No swap limit support") 102 } 103 if !v.KernelMemory { 104 v.Warnings = append(v.Warnings, "WARNING: No kernel memory limit support") 105 } 106 if !v.KernelMemoryTCP { 107 v.Warnings = append(v.Warnings, "WARNING: No kernel memory TCP limit support") 108 } 109 if !v.OomKillDisable { 110 v.Warnings = append(v.Warnings, "WARNING: No oom kill disable support") 111 } 112 if !v.CPUCfsQuota { 113 v.Warnings = append(v.Warnings, "WARNING: No cpu cfs quota support") 114 } 115 if !v.CPUCfsPeriod { 116 v.Warnings = append(v.Warnings, "WARNING: No cpu cfs period support") 117 } 118 if !v.CPUShares { 119 v.Warnings = append(v.Warnings, "WARNING: No cpu shares support") 120 } 121 if !v.CPUSet { 122 v.Warnings = append(v.Warnings, "WARNING: No cpuset support") 123 } 124 if v.CgroupVersion == "2" { 125 v.Warnings = append(v.Warnings, "WARNING: Support for cgroup v2 is experimental") 126 } 127 } 128 if !v.IPv4Forwarding { 129 v.Warnings = append(v.Warnings, "WARNING: IPv4 forwarding is disabled") 130 } 131 if !v.BridgeNfIptables { 132 v.Warnings = append(v.Warnings, "WARNING: bridge-nf-call-iptables is disabled") 133 } 134 if !v.BridgeNfIP6tables { 135 v.Warnings = append(v.Warnings, "WARNING: bridge-nf-call-ip6tables is disabled") 136 } 137 } 138 139 func (daemon *Daemon) fillPlatformVersion(v *types.Version) { 140 if rv, err := daemon.containerd.Version(context.Background()); err == nil { 141 v.Components = append(v.Components, types.ComponentVersion{ 142 Name: "containerd", 143 Version: rv.Version, 144 Details: map[string]string{ 145 "GitCommit": rv.Revision, 146 }, 147 }) 148 } 149 150 defaultRuntime := daemon.configStore.GetDefaultRuntimeName() 151 defaultRuntimeBinary := daemon.configStore.GetRuntime(defaultRuntime).Path 152 if rv, err := exec.Command(defaultRuntimeBinary, "--version").Output(); err == nil { 153 if _, ver, commit, err := parseRuntimeVersion(string(rv)); err != nil { 154 logrus.Warnf("failed to parse %s version: %v", defaultRuntimeBinary, err) 155 } else { 156 v.Components = append(v.Components, types.ComponentVersion{ 157 Name: defaultRuntime, 158 Version: ver, 159 Details: map[string]string{ 160 "GitCommit": commit, 161 }, 162 }) 163 } 164 } else { 165 logrus.Warnf("failed to retrieve %s version: %v", defaultRuntimeBinary, err) 166 } 167 168 defaultInitBinary := daemon.configStore.GetInitPath() 169 if rv, err := exec.Command(defaultInitBinary, "--version").Output(); err == nil { 170 if ver, commit, err := parseInitVersion(string(rv)); err != nil { 171 logrus.Warnf("failed to parse %s version: %s", defaultInitBinary, err) 172 } else { 173 v.Components = append(v.Components, types.ComponentVersion{ 174 Name: filepath.Base(defaultInitBinary), 175 Version: ver, 176 Details: map[string]string{ 177 "GitCommit": commit, 178 }, 179 }) 180 } 181 } else { 182 logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err) 183 } 184 } 185 186 func fillDriverWarnings(v *types.Info) { 187 for _, pair := range v.DriverStatus { 188 if pair[0] == "Data loop file" { 189 msg := fmt.Sprintf("WARNING: %s: usage of loopback devices is "+ 190 "strongly discouraged for production use.\n "+ 191 "Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.", v.Driver) 192 193 v.Warnings = append(v.Warnings, msg) 194 continue 195 } 196 if pair[0] == "Supports d_type" && pair[1] == "false" { 197 backingFs := getBackingFs(v) 198 199 msg := fmt.Sprintf("WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n", v.Driver, backingFs) 200 if backingFs == "xfs" { 201 msg += " Reformat the filesystem with ftype=1 to enable d_type support.\n" 202 } 203 msg += " Running without d_type support will not be supported in future releases." 204 205 v.Warnings = append(v.Warnings, msg) 206 continue 207 } 208 } 209 } 210 211 func getBackingFs(v *types.Info) string { 212 for _, pair := range v.DriverStatus { 213 if pair[0] == "Backing Filesystem" { 214 return pair[1] 215 } 216 } 217 return "" 218 } 219 220 // parseInitVersion parses a Tini version string, and extracts the "version" 221 // and "git commit" from the output. 222 // 223 // Output example from `docker-init --version`: 224 // 225 // tini version 0.18.0 - git.fec3683 226 func parseInitVersion(v string) (version string, commit string, err error) { 227 parts := strings.Split(v, " - ") 228 229 if len(parts) >= 2 { 230 gitParts := strings.Split(strings.TrimSpace(parts[1]), ".") 231 if len(gitParts) == 2 && gitParts[0] == "git" { 232 commit = gitParts[1] 233 } 234 } 235 parts[0] = strings.TrimSpace(parts[0]) 236 if strings.HasPrefix(parts[0], "tini version ") { 237 version = strings.TrimPrefix(parts[0], "tini version ") 238 } 239 if version == "" && commit == "" { 240 err = errors.Errorf("unknown output format: %s", v) 241 } 242 return version, commit, err 243 } 244 245 // parseRuntimeVersion parses the output of `[runtime] --version` and extracts the 246 // "name", "version" and "git commit" from the output. 247 // 248 // Output example from `runc --version`: 249 // 250 // runc version 1.0.0-rc5+dev 251 // commit: 69663f0bd4b60df09991c08812a60108003fa340 252 // spec: 1.0.0 253 func parseRuntimeVersion(v string) (runtime string, version string, commit string, err error) { 254 lines := strings.Split(strings.TrimSpace(v), "\n") 255 for _, line := range lines { 256 if strings.Contains(line, "version") { 257 s := strings.Split(line, "version") 258 runtime = strings.TrimSpace(s[0]) 259 version = strings.TrimSpace(s[len(s)-1]) 260 continue 261 } 262 if strings.HasPrefix(line, "commit:") { 263 commit = strings.TrimSpace(strings.TrimPrefix(line, "commit:")) 264 continue 265 } 266 } 267 if version == "" && commit == "" { 268 err = errors.Errorf("unknown output format: %s", v) 269 } 270 return runtime, version, commit, err 271 } 272 273 func (daemon *Daemon) cgroupNamespacesEnabled(sysInfo *sysinfo.SysInfo) bool { 274 return sysInfo.CgroupNamespaces && containertypes.CgroupnsMode(daemon.configStore.CgroupNamespaceMode).IsPrivate() 275 } 276 277 // Rootless returns true if daemon is running in rootless mode 278 func (daemon *Daemon) Rootless() bool { 279 return daemon.configStore.Rootless 280 }