github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/daemon/daemon_windows.go (about) 1 package daemon 2 3 import ( 4 "context" 5 "fmt" 6 "path/filepath" 7 "strings" 8 9 "github.com/Microsoft/hcsshim" 10 "github.com/docker/docker/api/types" 11 containertypes "github.com/docker/docker/api/types/container" 12 "github.com/docker/docker/container" 13 "github.com/docker/docker/daemon/config" 14 "github.com/docker/docker/image" 15 "github.com/docker/docker/pkg/containerfs" 16 "github.com/docker/docker/pkg/fileutils" 17 "github.com/docker/docker/pkg/idtools" 18 "github.com/docker/docker/pkg/parsers" 19 "github.com/docker/docker/pkg/platform" 20 "github.com/docker/docker/pkg/sysinfo" 21 "github.com/docker/docker/pkg/system" 22 "github.com/docker/docker/runconfig" 23 "github.com/docker/libnetwork" 24 nwconfig "github.com/docker/libnetwork/config" 25 "github.com/docker/libnetwork/datastore" 26 winlibnetwork "github.com/docker/libnetwork/drivers/windows" 27 "github.com/docker/libnetwork/netlabel" 28 "github.com/docker/libnetwork/options" 29 blkiodev "github.com/opencontainers/runc/libcontainer/configs" 30 "github.com/pkg/errors" 31 "github.com/sirupsen/logrus" 32 "golang.org/x/sys/windows" 33 "golang.org/x/sys/windows/svc/mgr" 34 ) 35 36 const ( 37 defaultNetworkSpace = "172.16.0.0/12" 38 platformSupported = true 39 windowsMinCPUShares = 1 40 windowsMaxCPUShares = 10000 41 windowsMinCPUPercent = 1 42 windowsMaxCPUPercent = 100 43 ) 44 45 // Windows has no concept of an execution state directory. So use config.Root here. 46 func getPluginExecRoot(root string) string { 47 return filepath.Join(root, "plugins") 48 } 49 50 func getBlkioWeightDevices(config *containertypes.HostConfig) ([]blkiodev.WeightDevice, error) { 51 return nil, nil 52 } 53 54 func (daemon *Daemon) parseSecurityOpt(container *container.Container, hostConfig *containertypes.HostConfig) error { 55 return parseSecurityOpt(container, hostConfig) 56 } 57 58 func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error { 59 return nil 60 } 61 62 func (daemon *Daemon) getLayerInit() func(containerfs.ContainerFS) error { 63 return nil 64 } 65 66 func checkKernel() error { 67 return nil 68 } 69 70 func (daemon *Daemon) getCgroupDriver() string { 71 return "" 72 } 73 74 // adaptContainerSettings is called during container creation to modify any 75 // settings necessary in the HostConfig structure. 76 func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error { 77 if hostConfig == nil { 78 return nil 79 } 80 81 return nil 82 } 83 84 func verifyContainerResources(resources *containertypes.Resources, isHyperv bool) ([]string, error) { 85 warnings := []string{} 86 fixMemorySwappiness(resources) 87 if !isHyperv { 88 // The processor resource controls are mutually exclusive on 89 // Windows Server Containers, the order of precedence is 90 // CPUCount first, then CPUShares, and CPUPercent last. 91 if resources.CPUCount > 0 { 92 if resources.CPUShares > 0 { 93 warnings = append(warnings, "Conflicting options: CPU count takes priority over CPU shares on Windows Server Containers. CPU shares discarded") 94 logrus.Warn("Conflicting options: CPU count takes priority over CPU shares on Windows Server Containers. CPU shares discarded") 95 resources.CPUShares = 0 96 } 97 if resources.CPUPercent > 0 { 98 warnings = append(warnings, "Conflicting options: CPU count takes priority over CPU percent on Windows Server Containers. CPU percent discarded") 99 logrus.Warn("Conflicting options: CPU count takes priority over CPU percent on Windows Server Containers. CPU percent discarded") 100 resources.CPUPercent = 0 101 } 102 } else if resources.CPUShares > 0 { 103 if resources.CPUPercent > 0 { 104 warnings = append(warnings, "Conflicting options: CPU shares takes priority over CPU percent on Windows Server Containers. CPU percent discarded") 105 logrus.Warn("Conflicting options: CPU shares takes priority over CPU percent on Windows Server Containers. CPU percent discarded") 106 resources.CPUPercent = 0 107 } 108 } 109 } 110 111 if resources.CPUShares < 0 || resources.CPUShares > windowsMaxCPUShares { 112 return warnings, fmt.Errorf("range of CPUShares is from %d to %d", windowsMinCPUShares, windowsMaxCPUShares) 113 } 114 if resources.CPUPercent < 0 || resources.CPUPercent > windowsMaxCPUPercent { 115 return warnings, fmt.Errorf("range of CPUPercent is from %d to %d", windowsMinCPUPercent, windowsMaxCPUPercent) 116 } 117 if resources.CPUCount < 0 { 118 return warnings, fmt.Errorf("invalid CPUCount: CPUCount cannot be negative") 119 } 120 121 if resources.NanoCPUs > 0 && resources.CPUPercent > 0 { 122 return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Percent cannot both be set") 123 } 124 if resources.NanoCPUs > 0 && resources.CPUShares > 0 { 125 return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Shares cannot both be set") 126 } 127 // The precision we could get is 0.01, because on Windows we have to convert to CPUPercent. 128 // We don't set the lower limit here and it is up to the underlying platform (e.g., Windows) to return an error. 129 if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 { 130 return warnings, fmt.Errorf("range of CPUs is from 0.01 to %d.00, as there are only %d CPUs available", sysinfo.NumCPU(), sysinfo.NumCPU()) 131 } 132 133 osv := system.GetOSVersion() 134 if resources.NanoCPUs > 0 && isHyperv && osv.Build < 16175 { 135 leftoverNanoCPUs := resources.NanoCPUs % 1e9 136 if leftoverNanoCPUs != 0 && resources.NanoCPUs > 1e9 { 137 resources.NanoCPUs = ((resources.NanoCPUs + 1e9/2) / 1e9) * 1e9 138 warningString := fmt.Sprintf("Your current OS version does not support Hyper-V containers with NanoCPUs greater than 1000000000 but not divisible by 1000000000. NanoCPUs rounded to %d", resources.NanoCPUs) 139 warnings = append(warnings, warningString) 140 logrus.Warn(warningString) 141 } 142 } 143 144 if len(resources.BlkioDeviceReadBps) > 0 { 145 return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceReadBps") 146 } 147 if len(resources.BlkioDeviceReadIOps) > 0 { 148 return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceReadIOps") 149 } 150 if len(resources.BlkioDeviceWriteBps) > 0 { 151 return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceWriteBps") 152 } 153 if len(resources.BlkioDeviceWriteIOps) > 0 { 154 return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceWriteIOps") 155 } 156 if resources.BlkioWeight > 0 { 157 return warnings, fmt.Errorf("invalid option: Windows does not support BlkioWeight") 158 } 159 if len(resources.BlkioWeightDevice) > 0 { 160 return warnings, fmt.Errorf("invalid option: Windows does not support BlkioWeightDevice") 161 } 162 if resources.CgroupParent != "" { 163 return warnings, fmt.Errorf("invalid option: Windows does not support CgroupParent") 164 } 165 if resources.CPUPeriod != 0 { 166 return warnings, fmt.Errorf("invalid option: Windows does not support CPUPeriod") 167 } 168 if resources.CpusetCpus != "" { 169 return warnings, fmt.Errorf("invalid option: Windows does not support CpusetCpus") 170 } 171 if resources.CpusetMems != "" { 172 return warnings, fmt.Errorf("invalid option: Windows does not support CpusetMems") 173 } 174 if resources.KernelMemory != 0 { 175 return warnings, fmt.Errorf("invalid option: Windows does not support KernelMemory") 176 } 177 if resources.MemoryReservation != 0 { 178 return warnings, fmt.Errorf("invalid option: Windows does not support MemoryReservation") 179 } 180 if resources.MemorySwap != 0 { 181 return warnings, fmt.Errorf("invalid option: Windows does not support MemorySwap") 182 } 183 if resources.MemorySwappiness != nil { 184 return warnings, fmt.Errorf("invalid option: Windows does not support MemorySwappiness") 185 } 186 if resources.OomKillDisable != nil && *resources.OomKillDisable { 187 return warnings, fmt.Errorf("invalid option: Windows does not support OomKillDisable") 188 } 189 if resources.PidsLimit != 0 { 190 return warnings, fmt.Errorf("invalid option: Windows does not support PidsLimit") 191 } 192 if len(resources.Ulimits) != 0 { 193 return warnings, fmt.Errorf("invalid option: Windows does not support Ulimits") 194 } 195 return warnings, nil 196 } 197 198 // verifyPlatformContainerSettings performs platform-specific validation of the 199 // hostconfig and config structures. 200 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { 201 warnings := []string{} 202 203 hyperv := daemon.runAsHyperVContainer(hostConfig) 204 if !hyperv && system.IsWindowsClient() && !system.IsIoTCore() { 205 // @engine maintainers. This block should not be removed. It partially enforces licensing 206 // restrictions on Windows. Ping @jhowardmsft if there are concerns or PRs to change this. 207 return warnings, fmt.Errorf("Windows client operating systems only support Hyper-V containers") 208 } 209 210 w, err := verifyContainerResources(&hostConfig.Resources, hyperv) 211 warnings = append(warnings, w...) 212 return warnings, err 213 } 214 215 // reloadPlatform updates configuration with platform specific options 216 // and updates the passed attributes 217 func (daemon *Daemon) reloadPlatform(config *config.Config, attributes map[string]string) error { 218 return nil 219 } 220 221 // verifyDaemonSettings performs validation of daemon config struct 222 func verifyDaemonSettings(config *config.Config) error { 223 return nil 224 } 225 226 // checkSystem validates platform-specific requirements 227 func checkSystem() error { 228 // Validate the OS version. Note that docker.exe must be manifested for this 229 // call to return the correct version. 230 osv := system.GetOSVersion() 231 if osv.MajorVersion < 10 { 232 return fmt.Errorf("This version of Windows does not support the docker daemon") 233 } 234 if osv.Build < 14393 { 235 return fmt.Errorf("The docker daemon requires build 14393 or later of Windows Server 2016 or Windows 10") 236 } 237 238 vmcompute := windows.NewLazySystemDLL("vmcompute.dll") 239 if vmcompute.Load() != nil { 240 return fmt.Errorf("failed to load vmcompute.dll, ensure that the Containers feature is installed") 241 } 242 243 // Ensure that the required Host Network Service and vmcompute services 244 // are running. Docker will fail in unexpected ways if this is not present. 245 var requiredServices = []string{"hns", "vmcompute"} 246 if err := ensureServicesInstalled(requiredServices); err != nil { 247 return errors.Wrap(err, "a required service is not installed, ensure the Containers feature is installed") 248 } 249 250 return nil 251 } 252 253 func ensureServicesInstalled(services []string) error { 254 m, err := mgr.Connect() 255 if err != nil { 256 return err 257 } 258 defer m.Disconnect() 259 for _, service := range services { 260 s, err := m.OpenService(service) 261 if err != nil { 262 return errors.Wrapf(err, "failed to open service %s", service) 263 } 264 s.Close() 265 } 266 return nil 267 } 268 269 // configureKernelSecuritySupport configures and validate security support for the kernel 270 func configureKernelSecuritySupport(config *config.Config, driverNames []string) error { 271 return nil 272 } 273 274 // configureMaxThreads sets the Go runtime max threads threshold 275 func configureMaxThreads(config *config.Config) error { 276 return nil 277 } 278 279 func (daemon *Daemon) initNetworkController(config *config.Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) { 280 netOptions, err := daemon.networkOptions(config, nil, nil) 281 if err != nil { 282 return nil, err 283 } 284 controller, err := libnetwork.New(netOptions...) 285 if err != nil { 286 return nil, fmt.Errorf("error obtaining controller instance: %v", err) 287 } 288 289 hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "") 290 if err != nil { 291 return nil, err 292 } 293 294 // Remove networks not present in HNS 295 for _, v := range controller.Networks() { 296 options := v.Info().DriverOptions() 297 hnsid := options[winlibnetwork.HNSID] 298 found := false 299 300 for _, v := range hnsresponse { 301 if v.Id == hnsid { 302 found = true 303 break 304 } 305 } 306 307 if !found { 308 // global networks should not be deleted by local HNS 309 if v.Info().Scope() != datastore.GlobalScope { 310 err = v.Delete() 311 if err != nil { 312 logrus.Errorf("Error occurred when removing network %v", err) 313 } 314 } 315 } 316 } 317 318 _, err = controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)) 319 if err != nil { 320 return nil, err 321 } 322 323 defaultNetworkExists := false 324 325 if network, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil { 326 options := network.Info().DriverOptions() 327 for _, v := range hnsresponse { 328 if options[winlibnetwork.HNSID] == v.Id { 329 defaultNetworkExists = true 330 break 331 } 332 } 333 } 334 335 // discover and add HNS networks to windows 336 // network that exist are removed and added again 337 for _, v := range hnsresponse { 338 if strings.ToLower(v.Type) == "private" { 339 continue // workaround for HNS reporting unsupported networks 340 } 341 var n libnetwork.Network 342 s := func(current libnetwork.Network) bool { 343 options := current.Info().DriverOptions() 344 if options[winlibnetwork.HNSID] == v.Id { 345 n = current 346 return true 347 } 348 return false 349 } 350 351 controller.WalkNetworks(s) 352 353 drvOptions := make(map[string]string) 354 355 if n != nil { 356 // global networks should not be deleted by local HNS 357 if n.Info().Scope() == datastore.GlobalScope { 358 continue 359 } 360 v.Name = n.Name() 361 // This will not cause network delete from HNS as the network 362 // is not yet populated in the libnetwork windows driver 363 364 // restore option if it existed before 365 drvOptions = n.Info().DriverOptions() 366 n.Delete() 367 } 368 netOption := map[string]string{ 369 winlibnetwork.NetworkName: v.Name, 370 winlibnetwork.HNSID: v.Id, 371 } 372 373 // add persisted driver options 374 for k, v := range drvOptions { 375 if k != winlibnetwork.NetworkName && k != winlibnetwork.HNSID { 376 netOption[k] = v 377 } 378 } 379 380 v4Conf := []*libnetwork.IpamConf{} 381 for _, subnet := range v.Subnets { 382 ipamV4Conf := libnetwork.IpamConf{} 383 ipamV4Conf.PreferredPool = subnet.AddressPrefix 384 ipamV4Conf.Gateway = subnet.GatewayAddress 385 v4Conf = append(v4Conf, &ipamV4Conf) 386 } 387 388 name := v.Name 389 390 // If there is no nat network create one from the first NAT network 391 // encountered if it doesn't already exist 392 if !defaultNetworkExists && 393 runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) && 394 n == nil { 395 name = runconfig.DefaultDaemonNetworkMode().NetworkName() 396 defaultNetworkExists = true 397 } 398 399 v6Conf := []*libnetwork.IpamConf{} 400 _, err := controller.NewNetwork(strings.ToLower(v.Type), name, "", 401 libnetwork.NetworkOptionGeneric(options.Generic{ 402 netlabel.GenericData: netOption, 403 }), 404 libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), 405 ) 406 407 if err != nil { 408 logrus.Errorf("Error occurred when creating network %v", err) 409 } 410 } 411 412 if !config.DisableBridge { 413 // Initialize default driver "bridge" 414 if err := initBridgeDriver(controller, config); err != nil { 415 return nil, err 416 } 417 } 418 419 return controller, nil 420 } 421 422 func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error { 423 if _, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil { 424 return nil 425 } 426 427 netOption := map[string]string{ 428 winlibnetwork.NetworkName: runconfig.DefaultDaemonNetworkMode().NetworkName(), 429 } 430 431 var ipamOption libnetwork.NetworkOption 432 var subnetPrefix string 433 434 if config.BridgeConfig.FixedCIDR != "" { 435 subnetPrefix = config.BridgeConfig.FixedCIDR 436 } else { 437 // TP5 doesn't support properly detecting subnet 438 osv := system.GetOSVersion() 439 if osv.Build < 14360 { 440 subnetPrefix = defaultNetworkSpace 441 } 442 } 443 444 if subnetPrefix != "" { 445 ipamV4Conf := libnetwork.IpamConf{} 446 ipamV4Conf.PreferredPool = subnetPrefix 447 v4Conf := []*libnetwork.IpamConf{&ipamV4Conf} 448 v6Conf := []*libnetwork.IpamConf{} 449 ipamOption = libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil) 450 } 451 452 _, err := controller.NewNetwork(string(runconfig.DefaultDaemonNetworkMode()), runconfig.DefaultDaemonNetworkMode().NetworkName(), "", 453 libnetwork.NetworkOptionGeneric(options.Generic{ 454 netlabel.GenericData: netOption, 455 }), 456 ipamOption, 457 ) 458 459 if err != nil { 460 return fmt.Errorf("Error creating default network: %v", err) 461 } 462 463 return nil 464 } 465 466 // registerLinks sets up links between containers and writes the 467 // configuration out for persistence. As of Windows TP4, links are not supported. 468 func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { 469 return nil 470 } 471 472 func (daemon *Daemon) cleanupMountsByID(in string) error { 473 return nil 474 } 475 476 func (daemon *Daemon) cleanupMounts() error { 477 return nil 478 } 479 480 func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) { 481 return &idtools.IDMappings{}, nil 482 } 483 484 func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error { 485 config.Root = rootDir 486 // Create the root directory if it doesn't exists 487 if err := system.MkdirAllWithACL(config.Root, 0, system.SddlAdministratorsLocalSystem); err != nil { 488 return err 489 } 490 return nil 491 } 492 493 // runasHyperVContainer returns true if we are going to run as a Hyper-V container 494 func (daemon *Daemon) runAsHyperVContainer(hostConfig *containertypes.HostConfig) bool { 495 if hostConfig.Isolation.IsDefault() { 496 // Container is set to use the default, so take the default from the daemon configuration 497 return daemon.defaultIsolation.IsHyperV() 498 } 499 500 // Container is requesting an isolation mode. Honour it. 501 return hostConfig.Isolation.IsHyperV() 502 503 } 504 505 // conditionalMountOnStart is a platform specific helper function during the 506 // container start to call mount. 507 func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error { 508 // Bail out now for Linux containers. We cannot mount the containers filesystem on the 509 // host as it is a non-Windows filesystem. 510 if system.LCOWSupported() && container.OS != "windows" { 511 return nil 512 } 513 514 // We do not mount if a Hyper-V container as it needs to be mounted inside the 515 // utility VM, not the host. 516 if !daemon.runAsHyperVContainer(container.HostConfig) { 517 return daemon.Mount(container) 518 } 519 return nil 520 } 521 522 // conditionalUnmountOnCleanup is a platform specific helper function called 523 // during the cleanup of a container to unmount. 524 func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error { 525 // Bail out now for Linux containers 526 if system.LCOWSupported() && container.OS != "windows" { 527 return nil 528 } 529 530 // We do not unmount if a Hyper-V container 531 if !daemon.runAsHyperVContainer(container.HostConfig) { 532 return daemon.Unmount(container) 533 } 534 return nil 535 } 536 537 func driverOptions(config *config.Config) []nwconfig.Option { 538 return []nwconfig.Option{} 539 } 540 541 func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) { 542 if !c.IsRunning() { 543 return nil, errNotRunning(c.ID) 544 } 545 546 // Obtain the stats from HCS via libcontainerd 547 stats, err := daemon.containerd.Stats(context.Background(), c.ID) 548 if err != nil { 549 if strings.Contains(err.Error(), "container not found") { 550 return nil, containerNotFound(c.ID) 551 } 552 return nil, err 553 } 554 555 // Start with an empty structure 556 s := &types.StatsJSON{} 557 s.Stats.Read = stats.Read 558 s.Stats.NumProcs = platform.NumProcs() 559 560 if stats.HCSStats != nil { 561 hcss := stats.HCSStats 562 // Populate the CPU/processor statistics 563 s.CPUStats = types.CPUStats{ 564 CPUUsage: types.CPUUsage{ 565 TotalUsage: hcss.Processor.TotalRuntime100ns, 566 UsageInKernelmode: hcss.Processor.RuntimeKernel100ns, 567 UsageInUsermode: hcss.Processor.RuntimeKernel100ns, 568 }, 569 } 570 571 // Populate the memory statistics 572 s.MemoryStats = types.MemoryStats{ 573 Commit: hcss.Memory.UsageCommitBytes, 574 CommitPeak: hcss.Memory.UsageCommitPeakBytes, 575 PrivateWorkingSet: hcss.Memory.UsagePrivateWorkingSetBytes, 576 } 577 578 // Populate the storage statistics 579 s.StorageStats = types.StorageStats{ 580 ReadCountNormalized: hcss.Storage.ReadCountNormalized, 581 ReadSizeBytes: hcss.Storage.ReadSizeBytes, 582 WriteCountNormalized: hcss.Storage.WriteCountNormalized, 583 WriteSizeBytes: hcss.Storage.WriteSizeBytes, 584 } 585 586 // Populate the network statistics 587 s.Networks = make(map[string]types.NetworkStats) 588 for _, nstats := range hcss.Network { 589 s.Networks[nstats.EndpointId] = types.NetworkStats{ 590 RxBytes: nstats.BytesReceived, 591 RxPackets: nstats.PacketsReceived, 592 RxDropped: nstats.DroppedPacketsIncoming, 593 TxBytes: nstats.BytesSent, 594 TxPackets: nstats.PacketsSent, 595 TxDropped: nstats.DroppedPacketsOutgoing, 596 } 597 } 598 } 599 return s, nil 600 } 601 602 // setDefaultIsolation determine the default isolation mode for the 603 // daemon to run in. This is only applicable on Windows 604 func (daemon *Daemon) setDefaultIsolation() error { 605 daemon.defaultIsolation = containertypes.Isolation("process") 606 // On client SKUs, default to Hyper-V. Note that IoT reports as a client SKU 607 // but it should not be treated as such. 608 if system.IsWindowsClient() && !system.IsIoTCore() { 609 daemon.defaultIsolation = containertypes.Isolation("hyperv") 610 } 611 for _, option := range daemon.configStore.ExecOptions { 612 key, val, err := parsers.ParseKeyValueOpt(option) 613 if err != nil { 614 return err 615 } 616 key = strings.ToLower(key) 617 switch key { 618 619 case "isolation": 620 if !containertypes.Isolation(val).IsValid() { 621 return fmt.Errorf("Invalid exec-opt value for 'isolation':'%s'", val) 622 } 623 if containertypes.Isolation(val).IsHyperV() { 624 daemon.defaultIsolation = containertypes.Isolation("hyperv") 625 } 626 if containertypes.Isolation(val).IsProcess() { 627 if system.IsWindowsClient() && !system.IsIoTCore() { 628 // @engine maintainers. This block should not be removed. It partially enforces licensing 629 // restrictions on Windows. Ping @jhowardmsft if there are concerns or PRs to change this. 630 return fmt.Errorf("Windows client operating systems only support Hyper-V containers") 631 } 632 daemon.defaultIsolation = containertypes.Isolation("process") 633 } 634 default: 635 return fmt.Errorf("Unrecognised exec-opt '%s'\n", key) 636 } 637 } 638 639 logrus.Infof("Windows default isolation mode: %s", daemon.defaultIsolation) 640 return nil 641 } 642 643 func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { 644 var layers []string 645 for _, l := range rootfs.DiffIDs { 646 layers = append(layers, l.String()) 647 } 648 return types.RootFS{ 649 Type: rootfs.Type, 650 Layers: layers, 651 } 652 } 653 654 func setupDaemonProcess(config *config.Config) error { 655 return nil 656 } 657 658 // verifyVolumesInfo is a no-op on windows. 659 // This is called during daemon initialization to migrate volumes from pre-1.7. 660 // volumes were not supported on windows pre-1.7 661 func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error { 662 return nil 663 } 664 665 func (daemon *Daemon) setupSeccompProfile() error { 666 return nil 667 } 668 669 func getRealPath(path string) (string, error) { 670 if system.IsIoTCore() { 671 // Due to https://github.com/golang/go/issues/20506, path expansion 672 // does not work correctly on the default IoT Core configuration. 673 // TODO @darrenstahlmsft remove this once golang/go/20506 is fixed 674 return path, nil 675 } 676 return fileutils.ReadSymlinkedDirectory(path) 677 } 678 679 func (daemon *Daemon) loadRuntimes() error { 680 return nil 681 } 682 683 func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error { 684 return nil 685 }