github.com/psychoss/docker@v1.9.0/daemon/daemon_unix.go (about) 1 // +build linux freebsd 2 3 package daemon 4 5 import ( 6 "fmt" 7 "net" 8 "os" 9 "path/filepath" 10 "strconv" 11 "strings" 12 "syscall" 13 14 "github.com/Sirupsen/logrus" 15 "github.com/docker/docker/autogen/dockerversion" 16 "github.com/docker/docker/daemon/graphdriver" 17 derr "github.com/docker/docker/errors" 18 "github.com/docker/docker/pkg/fileutils" 19 "github.com/docker/docker/pkg/idtools" 20 "github.com/docker/docker/pkg/parsers" 21 "github.com/docker/docker/pkg/parsers/kernel" 22 "github.com/docker/docker/pkg/sysinfo" 23 "github.com/docker/docker/runconfig" 24 "github.com/docker/docker/utils" 25 "github.com/docker/libnetwork" 26 nwconfig "github.com/docker/libnetwork/config" 27 "github.com/docker/libnetwork/drivers/bridge" 28 "github.com/docker/libnetwork/ipamutils" 29 "github.com/docker/libnetwork/netlabel" 30 "github.com/docker/libnetwork/options" 31 "github.com/docker/libnetwork/types" 32 "github.com/opencontainers/runc/libcontainer/label" 33 "github.com/vishvananda/netlink" 34 ) 35 36 const ( 37 // See https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269 38 linuxMinCPUShares = 2 39 linuxMaxCPUShares = 262144 40 platformSupported = true 41 ) 42 43 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error { 44 var ( 45 labelOpts []string 46 err error 47 ) 48 49 for _, opt := range config.SecurityOpt { 50 con := strings.SplitN(opt, ":", 2) 51 if len(con) == 1 { 52 return fmt.Errorf("Invalid --security-opt: %q", opt) 53 } 54 switch con[0] { 55 case "label": 56 labelOpts = append(labelOpts, con[1]) 57 case "apparmor": 58 container.AppArmorProfile = con[1] 59 default: 60 return fmt.Errorf("Invalid --security-opt: %q", opt) 61 } 62 } 63 64 container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts) 65 return err 66 } 67 68 func checkKernelVersion(k, major, minor int) bool { 69 if v, err := kernel.GetKernelVersion(); err != nil { 70 logrus.Warnf("%s", err) 71 } else { 72 if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 { 73 return false 74 } 75 } 76 return true 77 } 78 79 func checkKernel() error { 80 // Check for unsupported kernel versions 81 // FIXME: it would be cleaner to not test for specific versions, but rather 82 // test for specific functionalities. 83 // Unfortunately we can't test for the feature "does not cause a kernel panic" 84 // without actually causing a kernel panic, so we need this workaround until 85 // the circumstances of pre-3.10 crashes are clearer. 86 // For details see https://github.com/docker/docker/issues/407 87 if !checkKernelVersion(3, 10, 0) { 88 v, _ := kernel.GetKernelVersion() 89 if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" { 90 logrus.Warnf("Your Linux kernel version %s can be unstable running docker. Please upgrade your kernel to 3.10.0.", v.String()) 91 } 92 } 93 return nil 94 } 95 96 // adaptContainerSettings is called during container creation to modify any 97 // settings necessary in the HostConfig structure. 98 func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) { 99 if hostConfig == nil { 100 return 101 } 102 103 if adjustCPUShares && hostConfig.CPUShares > 0 { 104 // Handle unsupported CPUShares 105 if hostConfig.CPUShares < linuxMinCPUShares { 106 logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCPUShares) 107 hostConfig.CPUShares = linuxMinCPUShares 108 } else if hostConfig.CPUShares > linuxMaxCPUShares { 109 logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCPUShares) 110 hostConfig.CPUShares = linuxMaxCPUShares 111 } 112 } 113 if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 { 114 // By default, MemorySwap is set to twice the size of Memory. 115 hostConfig.MemorySwap = hostConfig.Memory * 2 116 } 117 } 118 119 // verifyPlatformContainerSettings performs platform-specific validation of the 120 // hostconfig and config structures. 121 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { 122 warnings := []string{} 123 sysInfo := sysinfo.New(true) 124 125 warnings, err := daemon.verifyExperimentalContainerSettings(hostConfig, config) 126 if err != nil { 127 return warnings, err 128 } 129 130 if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") { 131 return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name()) 132 } 133 134 // memory subsystem checks and adjustments 135 if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 { 136 return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB") 137 } 138 if hostConfig.Memory > 0 && !sysInfo.MemoryLimit { 139 warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") 140 logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.") 141 hostConfig.Memory = 0 142 hostConfig.MemorySwap = -1 143 } 144 if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit { 145 warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.") 146 logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.") 147 hostConfig.MemorySwap = -1 148 } 149 if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory { 150 return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") 151 } 152 if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 { 153 return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.") 154 } 155 if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness { 156 warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") 157 logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") 158 hostConfig.MemorySwappiness = nil 159 } 160 if hostConfig.MemorySwappiness != nil { 161 swappiness := *hostConfig.MemorySwappiness 162 if swappiness < -1 || swappiness > 100 { 163 return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness) 164 } 165 } 166 if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation { 167 warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.") 168 logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.") 169 hostConfig.MemoryReservation = 0 170 } 171 if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation { 172 return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.") 173 } 174 if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory { 175 warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.") 176 logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.") 177 hostConfig.KernelMemory = 0 178 } 179 if hostConfig.KernelMemory > 0 && !checkKernelVersion(4, 0, 0) { 180 warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") 181 logrus.Warnf("You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") 182 } 183 if hostConfig.CPUShares > 0 && !sysInfo.CPUShares { 184 warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.") 185 logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.") 186 hostConfig.CPUShares = 0 187 } 188 if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod { 189 warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.") 190 logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.") 191 hostConfig.CPUPeriod = 0 192 } 193 if hostConfig.CPUQuota > 0 && !sysInfo.CPUCfsQuota { 194 warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") 195 logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.") 196 hostConfig.CPUQuota = 0 197 } 198 if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset { 199 warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.") 200 logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.") 201 hostConfig.CpusetCpus = "" 202 hostConfig.CpusetMems = "" 203 } 204 cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(hostConfig.CpusetCpus) 205 if err != nil { 206 return warnings, derr.ErrorCodeInvalidCpusetCpus.WithArgs(hostConfig.CpusetCpus) 207 } 208 if !cpusAvailable { 209 return warnings, derr.ErrorCodeNotAvailableCpusetCpus.WithArgs(hostConfig.CpusetCpus, sysInfo.Cpus) 210 } 211 memsAvailable, err := sysInfo.IsCpusetMemsAvailable(hostConfig.CpusetMems) 212 if err != nil { 213 return warnings, derr.ErrorCodeInvalidCpusetMems.WithArgs(hostConfig.CpusetMems) 214 } 215 if !memsAvailable { 216 return warnings, derr.ErrorCodeNotAvailableCpusetMems.WithArgs(hostConfig.CpusetMems, sysInfo.Mems) 217 } 218 if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight { 219 warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.") 220 logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.") 221 hostConfig.BlkioWeight = 0 222 } 223 if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) { 224 return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") 225 } 226 if hostConfig.OomKillDisable && !sysInfo.OomKillDisable { 227 hostConfig.OomKillDisable = false 228 return warnings, fmt.Errorf("Your kernel does not support oom kill disable.") 229 } 230 231 if sysInfo.IPv4ForwardingDisabled { 232 warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.") 233 logrus.Warnf("IPv4 forwarding is disabled. Networking will not work") 234 } 235 return warnings, nil 236 } 237 238 // checkConfigOptions checks for mutually incompatible config options 239 func checkConfigOptions(config *Config) error { 240 // Check for mutually incompatible config options 241 if config.Bridge.Iface != "" && config.Bridge.IP != "" { 242 return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.") 243 } 244 if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication { 245 return fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.") 246 } 247 if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq { 248 config.Bridge.EnableIPMasq = false 249 } 250 return nil 251 } 252 253 // checkSystem validates platform-specific requirements 254 func checkSystem() error { 255 if os.Geteuid() != 0 { 256 return fmt.Errorf("The Docker daemon needs to be run as root") 257 } 258 return checkKernel() 259 } 260 261 // configureKernelSecuritySupport configures and validate security support for the kernel 262 func configureKernelSecuritySupport(config *Config, driverName string) error { 263 if config.EnableSelinuxSupport { 264 if selinuxEnabled() { 265 // As Docker on either btrfs or overlayFS and SELinux are incompatible at present, error on both being enabled 266 if driverName == "btrfs" || driverName == "overlay" { 267 return fmt.Errorf("SELinux is not supported with the %s graph driver", driverName) 268 } 269 logrus.Debug("SELinux enabled successfully") 270 } else { 271 logrus.Warn("Docker could not enable SELinux on the host system") 272 } 273 } else { 274 selinuxSetDisabled() 275 } 276 return nil 277 } 278 279 // MigrateIfDownlevel is a wrapper for AUFS migration for downlevel 280 func migrateIfDownlevel(driver graphdriver.Driver, root string) error { 281 return migrateIfAufs(driver, root) 282 } 283 284 func configureSysInit(config *Config, rootUID, rootGID int) (string, error) { 285 localCopy := filepath.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION)) 286 sysInitPath := utils.DockerInitPath(localCopy) 287 if sysInitPath == "" { 288 return "", fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/project/set-up-dev-env/ for official build instructions.") 289 } 290 291 if sysInitPath != localCopy { 292 // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). 293 if err := idtools.MkdirAs(filepath.Dir(localCopy), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { 294 return "", err 295 } 296 if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil { 297 return "", err 298 } 299 if err := os.Chmod(localCopy, 0700); err != nil { 300 return "", err 301 } 302 sysInitPath = localCopy 303 } 304 return sysInitPath, nil 305 } 306 307 func isBridgeNetworkDisabled(config *Config) bool { 308 return config.Bridge.Iface == disableNetworkBridge 309 } 310 311 func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) { 312 options := []nwconfig.Option{} 313 if dconfig == nil { 314 return options, nil 315 } 316 317 options = append(options, nwconfig.OptionDataDir(dconfig.Root)) 318 319 if strings.TrimSpace(dconfig.DefaultNetwork) != "" { 320 dn := strings.Split(dconfig.DefaultNetwork, ":") 321 if len(dn) < 2 { 322 return nil, fmt.Errorf("default network daemon config must be of the form NETWORKDRIVER:NETWORKNAME") 323 } 324 options = append(options, nwconfig.OptionDefaultDriver(dn[0])) 325 options = append(options, nwconfig.OptionDefaultNetwork(strings.Join(dn[1:], ":"))) 326 } else { 327 dd := runconfig.DefaultDaemonNetworkMode() 328 dn := runconfig.DefaultDaemonNetworkMode().NetworkName() 329 options = append(options, nwconfig.OptionDefaultDriver(string(dd))) 330 options = append(options, nwconfig.OptionDefaultNetwork(dn)) 331 } 332 333 if strings.TrimSpace(dconfig.ClusterStore) != "" { 334 kv := strings.Split(dconfig.ClusterStore, "://") 335 if len(kv) < 2 { 336 return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL") 337 } 338 options = append(options, nwconfig.OptionKVProvider(kv[0])) 339 options = append(options, nwconfig.OptionKVProviderURL(strings.Join(kv[1:], "://"))) 340 } 341 if len(dconfig.ClusterOpts) > 0 { 342 options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts)) 343 } 344 345 if daemon.discoveryWatcher != nil { 346 options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher)) 347 } 348 349 if dconfig.ClusterAdvertise != "" { 350 options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise)) 351 } 352 353 options = append(options, nwconfig.OptionLabels(dconfig.Labels)) 354 options = append(options, driverOptions(dconfig)...) 355 return options, nil 356 } 357 358 func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) { 359 netOptions, err := daemon.networkOptions(config) 360 if err != nil { 361 return nil, err 362 } 363 364 controller, err := libnetwork.New(netOptions...) 365 if err != nil { 366 return nil, fmt.Errorf("error obtaining controller instance: %v", err) 367 } 368 369 // Initialize default network on "null" 370 if _, err := controller.NewNetwork("null", "none", libnetwork.NetworkOptionPersist(false)); err != nil { 371 return nil, fmt.Errorf("Error creating default \"null\" network: %v", err) 372 } 373 374 // Initialize default network on "host" 375 if _, err := controller.NewNetwork("host", "host", libnetwork.NetworkOptionPersist(false)); err != nil { 376 return nil, fmt.Errorf("Error creating default \"host\" network: %v", err) 377 } 378 379 if !config.DisableBridge { 380 // Initialize default driver "bridge" 381 if err := initBridgeDriver(controller, config); err != nil { 382 return nil, err 383 } 384 } 385 386 return controller, nil 387 } 388 389 func driverOptions(config *Config) []nwconfig.Option { 390 bridgeConfig := options.Generic{ 391 "EnableIPForwarding": config.Bridge.EnableIPForward, 392 "EnableIPTables": config.Bridge.EnableIPTables, 393 "EnableUserlandProxy": config.Bridge.EnableUserlandProxy} 394 bridgeOption := options.Generic{netlabel.GenericData: bridgeConfig} 395 396 dOptions := []nwconfig.Option{} 397 dOptions = append(dOptions, nwconfig.OptionDriverConfig("bridge", bridgeOption)) 398 return dOptions 399 } 400 401 func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error { 402 if n, err := controller.NetworkByName("bridge"); err == nil { 403 if err = n.Delete(); err != nil { 404 return fmt.Errorf("could not delete the default bridge network: %v", err) 405 } 406 } 407 408 bridgeName := bridge.DefaultBridgeName 409 if config.Bridge.Iface != "" { 410 bridgeName = config.Bridge.Iface 411 } 412 netOption := map[string]string{ 413 bridge.BridgeName: bridgeName, 414 bridge.DefaultBridge: strconv.FormatBool(true), 415 netlabel.DriverMTU: strconv.Itoa(config.Mtu), 416 bridge.EnableIPMasquerade: strconv.FormatBool(config.Bridge.EnableIPMasq), 417 bridge.EnableICC: strconv.FormatBool(config.Bridge.InterContainerCommunication), 418 } 419 420 // --ip processing 421 if config.Bridge.DefaultIP != nil { 422 netOption[bridge.DefaultBindingIP] = config.Bridge.DefaultIP.String() 423 } 424 425 ipamV4Conf := libnetwork.IpamConf{} 426 427 ipamV4Conf.AuxAddresses = make(map[string]string) 428 429 if nw, _, err := ipamutils.ElectInterfaceAddresses(bridgeName); err == nil { 430 ipamV4Conf.PreferredPool = nw.String() 431 hip, _ := types.GetHostPartIP(nw.IP, nw.Mask) 432 if hip.IsGlobalUnicast() { 433 ipamV4Conf.Gateway = nw.IP.String() 434 } 435 } 436 437 if config.Bridge.IP != "" { 438 ipamV4Conf.PreferredPool = config.Bridge.IP 439 ip, _, err := net.ParseCIDR(config.Bridge.IP) 440 if err != nil { 441 return err 442 } 443 ipamV4Conf.Gateway = ip.String() 444 } else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" { 445 logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool) 446 } 447 448 if config.Bridge.FixedCIDR != "" { 449 _, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR) 450 if err != nil { 451 return err 452 } 453 454 ipamV4Conf.SubPool = fCIDR.String() 455 } 456 457 if config.Bridge.DefaultGatewayIPv4 != nil { 458 ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4.String() 459 } 460 461 var ipamV6Conf *libnetwork.IpamConf 462 if config.Bridge.FixedCIDRv6 != "" { 463 _, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6) 464 if err != nil { 465 return err 466 } 467 if ipamV6Conf == nil { 468 ipamV6Conf = &libnetwork.IpamConf{} 469 } 470 ipamV6Conf.PreferredPool = fCIDRv6.String() 471 } 472 473 if config.Bridge.DefaultGatewayIPv6 != nil { 474 if ipamV6Conf == nil { 475 ipamV6Conf = &libnetwork.IpamConf{} 476 } 477 ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6.String() 478 } 479 480 v4Conf := []*libnetwork.IpamConf{&ipamV4Conf} 481 v6Conf := []*libnetwork.IpamConf{} 482 if ipamV6Conf != nil { 483 v6Conf = append(v6Conf, ipamV6Conf) 484 } 485 // Initialize default network on "bridge" with the same name 486 _, err := controller.NewNetwork("bridge", "bridge", 487 libnetwork.NetworkOptionGeneric(options.Generic{ 488 netlabel.GenericData: netOption, 489 netlabel.EnableIPv6: config.Bridge.EnableIPv6, 490 }), 491 libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf)) 492 if err != nil { 493 return fmt.Errorf("Error creating default \"bridge\" network: %v", err) 494 } 495 return nil 496 } 497 498 // setupInitLayer populates a directory with mountpoints suitable 499 // for bind-mounting dockerinit into the container. The mountpoint is simply an 500 // empty file at /.dockerinit 501 // 502 // This extra layer is used by all containers as the top-most ro layer. It protects 503 // the container from unwanted side-effects on the rw layer. 504 func setupInitLayer(initLayer string, rootUID, rootGID int) error { 505 for pth, typ := range map[string]string{ 506 "/dev/pts": "dir", 507 "/dev/shm": "dir", 508 "/proc": "dir", 509 "/sys": "dir", 510 "/.dockerinit": "file", 511 "/.dockerenv": "file", 512 "/etc/resolv.conf": "file", 513 "/etc/hosts": "file", 514 "/etc/hostname": "file", 515 "/dev/console": "file", 516 "/etc/mtab": "/proc/mounts", 517 } { 518 parts := strings.Split(pth, "/") 519 prev := "/" 520 for _, p := range parts[1:] { 521 prev = filepath.Join(prev, p) 522 syscall.Unlink(filepath.Join(initLayer, prev)) 523 } 524 525 if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil { 526 if os.IsNotExist(err) { 527 if err := idtools.MkdirAllAs(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootUID, rootGID); err != nil { 528 return err 529 } 530 switch typ { 531 case "dir": 532 if err := idtools.MkdirAllAs(filepath.Join(initLayer, pth), 0755, rootUID, rootGID); err != nil { 533 return err 534 } 535 case "file": 536 f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755) 537 if err != nil { 538 return err 539 } 540 f.Close() 541 f.Chown(rootUID, rootGID) 542 default: 543 if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil { 544 return err 545 } 546 } 547 } else { 548 return err 549 } 550 } 551 } 552 553 // Layer is ready to use, if it wasn't before. 554 return nil 555 } 556 557 // registerLinks writes the links to a file. 558 func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig.HostConfig) error { 559 if hostConfig == nil || hostConfig.Links == nil { 560 return nil 561 } 562 563 for _, l := range hostConfig.Links { 564 name, alias, err := parsers.ParseLink(l) 565 if err != nil { 566 return err 567 } 568 child, err := daemon.Get(name) 569 if err != nil { 570 //An error from daemon.Get() means this name could not be found 571 return fmt.Errorf("Could not get container for %s", name) 572 } 573 for child.hostConfig.NetworkMode.IsContainer() { 574 parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2) 575 child, err = daemon.Get(parts[1]) 576 if err != nil { 577 return fmt.Errorf("Could not get container for %s", parts[1]) 578 } 579 } 580 if child.hostConfig.NetworkMode.IsHost() { 581 return runconfig.ErrConflictHostNetworkAndLinks 582 } 583 if err := daemon.registerLink(container, child, alias); err != nil { 584 return err 585 } 586 } 587 588 // After we load all the links into the daemon 589 // set them to nil on the hostconfig 590 hostConfig.Links = nil 591 if err := container.writeHostConfig(); err != nil { 592 return err 593 } 594 595 return nil 596 } 597 598 func (daemon *Daemon) newBaseContainer(id string) Container { 599 return Container{ 600 CommonContainer: CommonContainer{ 601 ID: id, 602 State: NewState(), 603 execCommands: newExecStore(), 604 root: daemon.containerRoot(id), 605 }, 606 MountPoints: make(map[string]*mountPoint), 607 Volumes: make(map[string]string), 608 VolumesRW: make(map[string]bool), 609 } 610 } 611 612 // getDefaultRouteMtu returns the MTU for the default route's interface. 613 func getDefaultRouteMtu() (int, error) { 614 routes, err := netlink.RouteList(nil, 0) 615 if err != nil { 616 return 0, err 617 } 618 for _, r := range routes { 619 // a nil Dst means that this is the default route. 620 if r.Dst == nil { 621 i, err := net.InterfaceByIndex(r.LinkIndex) 622 if err != nil { 623 continue 624 } 625 return i.MTU, nil 626 } 627 } 628 return 0, errNoDefaultRoute 629 }