github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/daemon/daemon_solaris.go (about) 1 // +build solaris,cgo 2 3 package daemon 4 5 import ( 6 "fmt" 7 "net" 8 "strconv" 9 10 "github.com/Sirupsen/logrus" 11 "github.com/docker/docker/api/types" 12 containertypes "github.com/docker/docker/api/types/container" 13 "github.com/docker/docker/container" 14 "github.com/docker/docker/image" 15 "github.com/docker/docker/layer" 16 "github.com/docker/docker/pkg/idtools" 17 "github.com/docker/docker/pkg/parsers/kernel" 18 "github.com/docker/docker/pkg/sysinfo" 19 "github.com/docker/docker/reference" 20 "github.com/docker/libnetwork" 21 nwconfig "github.com/docker/libnetwork/config" 22 "github.com/docker/libnetwork/drivers/solaris/bridge" 23 "github.com/docker/libnetwork/netlabel" 24 "github.com/docker/libnetwork/netutils" 25 lntypes "github.com/docker/libnetwork/types" 26 "github.com/opencontainers/runc/libcontainer/label" 27 "github.com/opencontainers/runtime-spec/specs-go" 28 "github.com/pkg/errors" 29 ) 30 31 //#include <zone.h> 32 import "C" 33 34 const ( 35 defaultVirtualSwitch = "Virtual Switch" 36 platformSupported = true 37 solarisMinCPUShares = 1 38 solarisMaxCPUShares = 65535 39 ) 40 41 func getMemoryResources(config containertypes.Resources) specs.CappedMemory { 42 memory := specs.CappedMemory{} 43 44 if config.Memory > 0 { 45 memory.Physical = strconv.FormatInt(config.Memory, 10) 46 } 47 48 if config.MemorySwap != 0 { 49 memory.Swap = strconv.FormatInt(config.MemorySwap, 10) 50 } 51 52 return memory 53 } 54 55 func getCPUResources(config containertypes.Resources) specs.CappedCPU { 56 cpu := specs.CappedCPU{} 57 58 if config.CpusetCpus != "" { 59 cpu.Ncpus = config.CpusetCpus 60 } 61 62 return cpu 63 } 64 65 func (daemon *Daemon) cleanupMountsByID(id string) error { 66 return nil 67 } 68 69 func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error { 70 //Since config.SecurityOpt is specifically defined as a "List of string values to 71 //customize labels for MLs systems, such as SELinux" 72 //until we figure out how to map to Trusted Extensions 73 //this is being disabled for now on Solaris 74 var ( 75 labelOpts []string 76 err error 77 ) 78 79 if len(config.SecurityOpt) > 0 { 80 return errors.New("Security options are not supported on Solaris") 81 } 82 83 container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts) 84 return err 85 } 86 87 func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { 88 return nil, nil, nil 89 } 90 91 func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { 92 return nil 93 } 94 95 func (daemon *Daemon) getLayerInit() func(string) error { 96 return nil 97 } 98 99 // setupInitLayer populates a directory with mountpoints suitable 100 // for bind-mounting dockerinit into the container. The mountpoint is simply an 101 // empty file at /.dockerinit 102 // 103 // This extra layer is used by all containers as the top-most ro layer. It protects 104 // the container from unwanted side-effects on the rw layer. 105 func setupInitLayer(initLayer string, rootUID, rootGID int) error { 106 return nil 107 } 108 109 func checkKernel() error { 110 // solaris can rely upon checkSystem() below, we don't skew kernel versions 111 return nil 112 } 113 114 func (daemon *Daemon) getCgroupDriver() string { 115 return "" 116 } 117 118 func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error { 119 if hostConfig.CPUShares < 0 { 120 logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, solarisMinCPUShares) 121 hostConfig.CPUShares = solarisMinCPUShares 122 } else if hostConfig.CPUShares > solarisMaxCPUShares { 123 logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, solarisMaxCPUShares) 124 hostConfig.CPUShares = solarisMaxCPUShares 125 } 126 127 if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 { 128 // By default, MemorySwap is set to twice the size of Memory. 129 hostConfig.MemorySwap = hostConfig.Memory * 2 130 } 131 132 if hostConfig.ShmSize != 0 { 133 hostConfig.ShmSize = container.DefaultSHMSize 134 } 135 if hostConfig.OomKillDisable == nil { 136 defaultOomKillDisable := false 137 hostConfig.OomKillDisable = &defaultOomKillDisable 138 } 139 140 return nil 141 } 142 143 // UsingSystemd returns true if cli option includes native.cgroupdriver=systemd 144 func UsingSystemd(config *Config) bool { 145 return false 146 } 147 148 // verifyPlatformContainerSettings performs platform-specific validation of the 149 // hostconfig and config structures. 150 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { 151 warnings := []string{} 152 sysInfo := sysinfo.New(true) 153 // NOTE: We do not enforce a minimum value for swap limits for zones on Solaris and 154 // therefore we will not do that for Docker container either. 155 if hostConfig.Memory > 0 && !sysInfo.MemoryLimit { 156 warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") 157 logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.") 158 hostConfig.Memory = 0 159 hostConfig.MemorySwap = -1 160 } 161 if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit { 162 warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.") 163 logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.") 164 hostConfig.MemorySwap = -1 165 } 166 if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory { 167 return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") 168 } 169 // Solaris NOTE: We allow and encourage setting the swap without setting the memory limit. 170 171 if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness { 172 warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") 173 logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.") 174 hostConfig.MemorySwappiness = nil 175 } 176 if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation { 177 warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.") 178 logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.") 179 hostConfig.MemoryReservation = 0 180 } 181 if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation { 182 return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.") 183 } 184 if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory { 185 warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.") 186 logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.") 187 hostConfig.KernelMemory = 0 188 } 189 if hostConfig.CPUShares != 0 && !sysInfo.CPUShares { 190 warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.") 191 logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.") 192 hostConfig.CPUShares = 0 193 } 194 if hostConfig.CPUShares < 0 { 195 warnings = append(warnings, "Invalid CPUShares value. Must be positive. Discarding.") 196 logrus.Warnf("Invalid CPUShares value. Must be positive. Discarding.") 197 hostConfig.CPUQuota = 0 198 } 199 if hostConfig.CPUShares > 0 && !sysinfo.IsCPUSharesAvailable() { 200 warnings = append(warnings, "Global zone default scheduling class not FSS. Discarding shares.") 201 logrus.Warnf("Global zone default scheduling class not FSS. Discarding shares.") 202 hostConfig.CPUShares = 0 203 } 204 205 // Solaris NOTE: Linux does not do negative checking for CPUShares and Quota here. But it makes sense to. 206 if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod { 207 warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.") 208 logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.") 209 if hostConfig.CPUQuota > 0 { 210 warnings = append(warnings, "Quota will be applied on default period, not period specified.") 211 logrus.Warnf("Quota will be applied on default period, not period specified.") 212 } 213 hostConfig.CPUPeriod = 0 214 } 215 if hostConfig.CPUQuota != 0 && !sysInfo.CPUCfsQuota { 216 warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") 217 logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.") 218 hostConfig.CPUQuota = 0 219 } 220 if hostConfig.CPUQuota < 0 { 221 warnings = append(warnings, "Invalid CPUQuota value. Must be positive. Discarding.") 222 logrus.Warnf("Invalid CPUQuota value. Must be positive. Discarding.") 223 hostConfig.CPUQuota = 0 224 } 225 if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset { 226 warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.") 227 logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.") 228 hostConfig.CpusetCpus = "" 229 hostConfig.CpusetMems = "" 230 } 231 cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(hostConfig.CpusetCpus) 232 if err != nil { 233 return warnings, fmt.Errorf("Invalid value %s for cpuset cpus.", hostConfig.CpusetCpus) 234 } 235 if !cpusAvailable { 236 return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s.", hostConfig.CpusetCpus, sysInfo.Cpus) 237 } 238 memsAvailable, err := sysInfo.IsCpusetMemsAvailable(hostConfig.CpusetMems) 239 if err != nil { 240 return warnings, fmt.Errorf("Invalid value %s for cpuset mems.", hostConfig.CpusetMems) 241 } 242 if !memsAvailable { 243 return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s.", hostConfig.CpusetMems, sysInfo.Mems) 244 } 245 if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight { 246 warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.") 247 logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.") 248 hostConfig.BlkioWeight = 0 249 } 250 if hostConfig.OomKillDisable != nil && !sysInfo.OomKillDisable { 251 *hostConfig.OomKillDisable = false 252 // Don't warn; this is the default setting but only applicable to Linux 253 } 254 255 if sysInfo.IPv4ForwardingDisabled { 256 warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.") 257 logrus.Warnf("IPv4 forwarding is disabled. Networking will not work") 258 } 259 260 // Solaris NOTE: We do not allow setting Linux specific options, so check and warn for all of them. 261 262 if hostConfig.CapAdd != nil || hostConfig.CapDrop != nil { 263 warnings = append(warnings, "Adding or dropping kernel capabilities unsupported on Solaris.Discarding capabilities lists.") 264 logrus.Warnf("Adding or dropping kernel capabilities unsupported on Solaris.Discarding capabilities lists.") 265 hostConfig.CapAdd = nil 266 hostConfig.CapDrop = nil 267 } 268 269 if hostConfig.GroupAdd != nil { 270 warnings = append(warnings, "Additional groups unsupported on Solaris.Discarding groups lists.") 271 logrus.Warnf("Additional groups unsupported on Solaris.Discarding groups lists.") 272 hostConfig.GroupAdd = nil 273 } 274 275 if hostConfig.IpcMode != "" { 276 warnings = append(warnings, "IPC namespace assignment unsupported on Solaris.Discarding IPC setting.") 277 logrus.Warnf("IPC namespace assignment unsupported on Solaris.Discarding IPC setting.") 278 hostConfig.IpcMode = "" 279 } 280 281 if hostConfig.PidMode != "" { 282 warnings = append(warnings, "PID namespace setting unsupported on Solaris. Running container in host PID namespace.") 283 logrus.Warnf("PID namespace setting unsupported on Solaris. Running container in host PID namespace.") 284 hostConfig.PidMode = "" 285 } 286 287 if hostConfig.Privileged { 288 warnings = append(warnings, "Privileged mode unsupported on Solaris. Discarding privileged mode setting.") 289 logrus.Warnf("Privileged mode unsupported on Solaris. Discarding privileged mode setting.") 290 hostConfig.Privileged = false 291 } 292 293 if hostConfig.UTSMode != "" { 294 warnings = append(warnings, "UTS namespace assignment unsupported on Solaris.Discarding UTS setting.") 295 logrus.Warnf("UTS namespace assignment unsupported on Solaris.Discarding UTS setting.") 296 hostConfig.UTSMode = "" 297 } 298 299 if hostConfig.CgroupParent != "" { 300 warnings = append(warnings, "Specifying Cgroup parent unsupported on Solaris. Discarding cgroup parent setting.") 301 logrus.Warnf("Specifying Cgroup parent unsupported on Solaris. Discarding cgroup parent setting.") 302 hostConfig.CgroupParent = "" 303 } 304 305 if hostConfig.Ulimits != nil { 306 warnings = append(warnings, "Specifying ulimits unsupported on Solaris. Discarding ulimits setting.") 307 logrus.Warnf("Specifying ulimits unsupported on Solaris. Discarding ulimits setting.") 308 hostConfig.Ulimits = nil 309 } 310 311 return warnings, nil 312 } 313 314 // platformReload update configuration with platform specific options 315 func (daemon *Daemon) platformReload(config *Config) map[string]string { 316 return map[string]string{} 317 } 318 319 // verifyDaemonSettings performs validation of daemon config struct 320 func verifyDaemonSettings(config *Config) error { 321 322 if config.DefaultRuntime == "" { 323 config.DefaultRuntime = stockRuntimeName 324 } 325 if config.Runtimes == nil { 326 config.Runtimes = make(map[string]types.Runtime) 327 } 328 stockRuntimeOpts := []string{} 329 config.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary, Args: stockRuntimeOpts} 330 331 // checkSystem validates platform-specific requirements 332 return nil 333 } 334 335 func checkSystem() error { 336 // check OS version for compatibility, ensure running in global zone 337 var err error 338 var id C.zoneid_t 339 340 if id, err = C.getzoneid(); err != nil { 341 return fmt.Errorf("Exiting. Error getting zone id: %+v", err) 342 } 343 if int(id) != 0 { 344 return fmt.Errorf("Exiting because the Docker daemon is not running in the global zone") 345 } 346 347 v, err := kernel.GetKernelVersion() 348 if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 5, Major: 12, Minor: 0}) < 0 { 349 return fmt.Errorf("Your Solaris kernel version: %s doesn't support Docker. Please upgrade to 5.12.0", v.String()) 350 } 351 return err 352 } 353 354 // configureMaxThreads sets the Go runtime max threads threshold 355 // which is 90% of the kernel setting from /proc/sys/kernel/threads-max 356 func configureMaxThreads(config *Config) error { 357 return nil 358 } 359 360 // configureKernelSecuritySupport configures and validate security support for the kernel 361 func configureKernelSecuritySupport(config *Config, driverName string) error { 362 return nil 363 } 364 365 func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) { 366 netOptions, err := daemon.networkOptions(config, daemon.PluginStore, activeSandboxes) 367 if err != nil { 368 return nil, err 369 } 370 371 controller, err := libnetwork.New(netOptions...) 372 if err != nil { 373 return nil, fmt.Errorf("error obtaining controller instance: %v", err) 374 } 375 376 // Initialize default network on "null" 377 if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)); err != nil { 378 return nil, fmt.Errorf("Error creating default 'null' network: %v", err) 379 } 380 381 if !config.DisableBridge { 382 // Initialize default driver "bridge" 383 if err := initBridgeDriver(controller, config); err != nil { 384 return nil, err 385 } 386 } 387 388 return controller, nil 389 } 390 391 func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error { 392 if n, err := controller.NetworkByName("bridge"); err == nil { 393 if err = n.Delete(); err != nil { 394 return fmt.Errorf("could not delete the default bridge network: %v", err) 395 } 396 } 397 398 bridgeName := bridge.DefaultBridgeName 399 if config.bridgeConfig.Iface != "" { 400 bridgeName = config.bridgeConfig.Iface 401 } 402 netOption := map[string]string{ 403 bridge.BridgeName: bridgeName, 404 bridge.DefaultBridge: strconv.FormatBool(true), 405 netlabel.DriverMTU: strconv.Itoa(config.Mtu), 406 bridge.EnableICC: strconv.FormatBool(config.bridgeConfig.InterContainerCommunication), 407 } 408 409 // --ip processing 410 if config.bridgeConfig.DefaultIP != nil { 411 netOption[bridge.DefaultBindingIP] = config.bridgeConfig.DefaultIP.String() 412 } 413 414 var ipamV4Conf *libnetwork.IpamConf 415 416 ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)} 417 418 nwList, _, err := netutils.ElectInterfaceAddresses(bridgeName) 419 if err != nil { 420 return errors.Wrap(err, "list bridge addresses failed") 421 } 422 423 nw := nwList[0] 424 if len(nwList) > 1 && config.bridgeConfig.FixedCIDR != "" { 425 _, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR) 426 if err != nil { 427 return errors.Wrap(err, "parse CIDR failed") 428 } 429 // Iterate through in case there are multiple addresses for the bridge 430 for _, entry := range nwList { 431 if fCIDR.Contains(entry.IP) { 432 nw = entry 433 break 434 } 435 } 436 } 437 438 ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String() 439 hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask) 440 if hip.IsGlobalUnicast() { 441 ipamV4Conf.Gateway = nw.IP.String() 442 } 443 444 if config.bridgeConfig.IP != "" { 445 ipamV4Conf.PreferredPool = config.bridgeConfig.IP 446 ip, _, err := net.ParseCIDR(config.bridgeConfig.IP) 447 if err != nil { 448 return err 449 } 450 ipamV4Conf.Gateway = ip.String() 451 } else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" { 452 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) 453 } 454 455 if config.bridgeConfig.FixedCIDR != "" { 456 _, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR) 457 if err != nil { 458 return err 459 } 460 461 ipamV4Conf.SubPool = fCIDR.String() 462 } 463 464 if config.bridgeConfig.DefaultGatewayIPv4 != nil { 465 ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.bridgeConfig.DefaultGatewayIPv4.String() 466 } 467 468 v4Conf := []*libnetwork.IpamConf{ipamV4Conf} 469 v6Conf := []*libnetwork.IpamConf{} 470 471 // Initialize default network on "bridge" with the same name 472 _, err = controller.NewNetwork("bridge", "bridge", "", 473 libnetwork.NetworkOptionDriverOpts(netOption), 474 libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), 475 libnetwork.NetworkOptionDeferIPv6Alloc(false)) 476 if err != nil { 477 return fmt.Errorf("Error creating default 'bridge' network: %v", err) 478 } 479 return nil 480 } 481 482 // registerLinks sets up links between containers and writes the 483 // configuration out for persistence. 484 func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { 485 return nil 486 } 487 488 func (daemon *Daemon) cleanupMounts() error { 489 return nil 490 } 491 492 // conditionalMountOnStart is a platform specific helper function during the 493 // container start to call mount. 494 func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error { 495 return daemon.Mount(container) 496 } 497 498 // conditionalUnmountOnCleanup is a platform specific helper function called 499 // during the cleanup of a container to unmount. 500 func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error { 501 return daemon.Unmount(container) 502 } 503 504 func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) error { 505 // Solaris has no custom images to register 506 return nil 507 } 508 509 func driverOptions(config *Config) []nwconfig.Option { 510 return []nwconfig.Option{} 511 } 512 513 func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) { 514 return nil, nil 515 } 516 517 // setDefaultIsolation determine the default isolation mode for the 518 // daemon to run in. This is only applicable on Windows 519 func (daemon *Daemon) setDefaultIsolation() error { 520 return nil 521 } 522 523 func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { 524 return types.RootFS{} 525 } 526 527 func setupDaemonProcess(config *Config) error { 528 return nil 529 } 530 531 func (daemon *Daemon) setupSeccompProfile() error { 532 return nil 533 }