github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/daemon/daemon_windows.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 "github.com/Microsoft/hcsshim" 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/container" 11 "github.com/docker/docker/image" 12 "github.com/docker/docker/pkg/idtools" 13 "github.com/docker/docker/pkg/parsers" 14 "github.com/docker/docker/pkg/sysinfo" 15 "github.com/docker/docker/pkg/system" 16 "github.com/docker/docker/runconfig" 17 "github.com/docker/engine-api/types" 18 pblkiodev "github.com/docker/engine-api/types/blkiodev" 19 containertypes "github.com/docker/engine-api/types/container" 20 "github.com/docker/libnetwork" 21 nwconfig "github.com/docker/libnetwork/config" 22 winlibnetwork "github.com/docker/libnetwork/drivers/windows" 23 "github.com/docker/libnetwork/netlabel" 24 "github.com/docker/libnetwork/options" 25 blkiodev "github.com/opencontainers/runc/libcontainer/configs" 26 ) 27 28 const ( 29 defaultNetworkSpace = "172.16.0.0/12" 30 platformSupported = true 31 windowsMinCPUShares = 1 32 windowsMaxCPUShares = 10000 33 ) 34 35 func getBlkioWeightDevices(config *containertypes.HostConfig) ([]blkiodev.WeightDevice, error) { 36 return nil, nil 37 } 38 39 func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error { 40 return nil 41 } 42 43 func getBlkioReadIOpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) { 44 return nil, nil 45 } 46 47 func getBlkioWriteIOpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) { 48 return nil, nil 49 } 50 51 func getBlkioReadBpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) { 52 return nil, nil 53 } 54 55 func getBlkioWriteBpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) { 56 return nil, nil 57 } 58 59 func setupInitLayer(initLayer string, rootUID, rootGID int) error { 60 return nil 61 } 62 63 func checkKernel() error { 64 return nil 65 } 66 67 func (daemon *Daemon) getCgroupDriver() string { 68 return "" 69 } 70 71 // adaptContainerSettings is called during container creation to modify any 72 // settings necessary in the HostConfig structure. 73 func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error { 74 if hostConfig == nil { 75 return nil 76 } 77 78 if hostConfig.CPUShares < 0 { 79 logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, windowsMinCPUShares) 80 hostConfig.CPUShares = windowsMinCPUShares 81 } else if hostConfig.CPUShares > windowsMaxCPUShares { 82 logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, windowsMaxCPUShares) 83 hostConfig.CPUShares = windowsMaxCPUShares 84 } 85 86 return nil 87 } 88 89 func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo) ([]string, error) { 90 warnings := []string{} 91 92 // cpu subsystem checks and adjustments 93 if resources.CPUPercent < 0 || resources.CPUPercent > 100 { 94 return warnings, fmt.Errorf("Range of CPU percent is from 1 to 100") 95 } 96 97 if resources.CPUPercent > 0 && resources.CPUShares > 0 { 98 return warnings, fmt.Errorf("Conflicting options: CPU Shares and CPU Percent cannot both be set") 99 } 100 101 // TODO Windows: Add more validation of resource settings not supported on Windows 102 103 if resources.BlkioWeight > 0 { 104 warnings = append(warnings, "Windows does not support Block I/O weight. Block I/O weight discarded.") 105 logrus.Warn("Windows does not support Block I/O weight. Block I/O weight discarded.") 106 resources.BlkioWeight = 0 107 } 108 if len(resources.BlkioWeightDevice) > 0 { 109 warnings = append(warnings, "Windows does not support Block I/O weight-device. Weight-device discarded.") 110 logrus.Warn("Windows does not support Block I/O weight-device. Weight-device discarded.") 111 resources.BlkioWeightDevice = []*pblkiodev.WeightDevice{} 112 } 113 if len(resources.BlkioDeviceReadBps) > 0 { 114 warnings = append(warnings, "Windows does not support Block read limit in bytes per second. Device read bps discarded.") 115 logrus.Warn("Windows does not support Block I/O read limit in bytes per second. Device read bps discarded.") 116 resources.BlkioDeviceReadBps = []*pblkiodev.ThrottleDevice{} 117 } 118 if len(resources.BlkioDeviceWriteBps) > 0 { 119 warnings = append(warnings, "Windows does not support Block write limit in bytes per second. Device write bps discarded.") 120 logrus.Warn("Windows does not support Block I/O write limit in bytes per second. Device write bps discarded.") 121 resources.BlkioDeviceWriteBps = []*pblkiodev.ThrottleDevice{} 122 } 123 if len(resources.BlkioDeviceReadIOps) > 0 { 124 warnings = append(warnings, "Windows does not support Block read limit in IO per second. Device read iops discarded.") 125 logrus.Warn("Windows does not support Block I/O read limit in IO per second. Device read iops discarded.") 126 resources.BlkioDeviceReadIOps = []*pblkiodev.ThrottleDevice{} 127 } 128 if len(resources.BlkioDeviceWriteIOps) > 0 { 129 warnings = append(warnings, "Windows does not support Block write limit in IO per second. Device write iops discarded.") 130 logrus.Warn("Windows does not support Block I/O write limit in IO per second. Device write iops discarded.") 131 resources.BlkioDeviceWriteIOps = []*pblkiodev.ThrottleDevice{} 132 } 133 return warnings, nil 134 } 135 136 // verifyPlatformContainerSettings performs platform-specific validation of the 137 // hostconfig and config structures. 138 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { 139 warnings := []string{} 140 141 w, err := verifyContainerResources(&hostConfig.Resources, nil) 142 warnings = append(warnings, w...) 143 if err != nil { 144 return warnings, err 145 } 146 147 return warnings, nil 148 } 149 150 // platformReload update configuration with platform specific options 151 func (daemon *Daemon) platformReload(config *Config, attributes *map[string]string) { 152 } 153 154 // verifyDaemonSettings performs validation of daemon config struct 155 func verifyDaemonSettings(config *Config) error { 156 return nil 157 } 158 159 // checkSystem validates platform-specific requirements 160 func checkSystem() error { 161 // Validate the OS version. Note that docker.exe must be manifested for this 162 // call to return the correct version. 163 osv := system.GetOSVersion() 164 if osv.MajorVersion < 10 { 165 return fmt.Errorf("This version of Windows does not support the docker daemon") 166 } 167 if osv.Build < 14300 { 168 return fmt.Errorf("The Windows daemon requires Windows Server 2016 Technical Preview 5 build 14300 or later") 169 } 170 return nil 171 } 172 173 // configureKernelSecuritySupport configures and validate security support for the kernel 174 func configureKernelSecuritySupport(config *Config, driverName string) error { 175 return nil 176 } 177 178 // configureMaxThreads sets the Go runtime max threads threshold 179 func configureMaxThreads(config *Config) error { 180 return nil 181 } 182 183 func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) { 184 netOptions, err := daemon.networkOptions(config, nil) 185 if err != nil { 186 return nil, err 187 } 188 controller, err := libnetwork.New(netOptions...) 189 if err != nil { 190 return nil, fmt.Errorf("error obtaining controller instance: %v", err) 191 } 192 193 hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "") 194 if err != nil { 195 return nil, err 196 } 197 198 // Remove networks not present in HNS 199 for _, v := range controller.Networks() { 200 options := v.Info().DriverOptions() 201 hnsid := options[winlibnetwork.HNSID] 202 found := false 203 204 for _, v := range hnsresponse { 205 if v.Id == hnsid { 206 found = true 207 break 208 } 209 } 210 211 if !found { 212 err = v.Delete() 213 if err != nil { 214 return nil, err 215 } 216 } 217 } 218 219 _, err = controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)) 220 if err != nil { 221 return nil, err 222 } 223 224 // discover and add HNS networks to windows 225 // network that exist are removed and added again 226 for _, v := range hnsresponse { 227 var n libnetwork.Network 228 s := func(current libnetwork.Network) bool { 229 options := current.Info().DriverOptions() 230 if options[winlibnetwork.HNSID] == v.Id { 231 n = current 232 return true 233 } 234 return false 235 } 236 237 controller.WalkNetworks(s) 238 if n != nil { 239 v.Name = n.Name() 240 n.Delete() 241 } 242 243 netOption := map[string]string{ 244 winlibnetwork.NetworkName: v.Name, 245 winlibnetwork.HNSID: v.Id, 246 } 247 248 v4Conf := []*libnetwork.IpamConf{} 249 for _, subnet := range v.Subnets { 250 ipamV4Conf := libnetwork.IpamConf{} 251 ipamV4Conf.PreferredPool = subnet.AddressPrefix 252 ipamV4Conf.Gateway = subnet.GatewayAddress 253 v4Conf = append(v4Conf, &ipamV4Conf) 254 } 255 256 name := v.Name 257 // There is only one nat network supported in windows. 258 // If it exists with a different name add it as the default name 259 if runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) { 260 name = runconfig.DefaultDaemonNetworkMode().NetworkName() 261 } 262 263 v6Conf := []*libnetwork.IpamConf{} 264 _, err := controller.NewNetwork(strings.ToLower(v.Type), name, "", 265 libnetwork.NetworkOptionGeneric(options.Generic{ 266 netlabel.GenericData: netOption, 267 }), 268 libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), 269 ) 270 271 if err != nil { 272 logrus.Errorf("Error occurred when creating network %v", err) 273 } 274 } 275 276 if !config.DisableBridge { 277 // Initialize default driver "bridge" 278 if err := initBridgeDriver(controller, config); err != nil { 279 return nil, err 280 } 281 } 282 283 return controller, nil 284 } 285 286 func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error { 287 if _, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil { 288 return nil 289 } 290 291 netOption := map[string]string{ 292 winlibnetwork.NetworkName: runconfig.DefaultDaemonNetworkMode().NetworkName(), 293 } 294 295 ipamV4Conf := libnetwork.IpamConf{} 296 if config.bridgeConfig.FixedCIDR == "" { 297 ipamV4Conf.PreferredPool = defaultNetworkSpace 298 } else { 299 ipamV4Conf.PreferredPool = config.bridgeConfig.FixedCIDR 300 } 301 302 v4Conf := []*libnetwork.IpamConf{&ipamV4Conf} 303 v6Conf := []*libnetwork.IpamConf{} 304 305 _, err := controller.NewNetwork(string(runconfig.DefaultDaemonNetworkMode()), runconfig.DefaultDaemonNetworkMode().NetworkName(), "", 306 libnetwork.NetworkOptionGeneric(options.Generic{ 307 netlabel.GenericData: netOption, 308 }), 309 libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil), 310 ) 311 312 if err != nil { 313 return fmt.Errorf("Error creating default network: %v", err) 314 } 315 return nil 316 } 317 318 // registerLinks sets up links between containers and writes the 319 // configuration out for persistence. As of Windows TP4, links are not supported. 320 func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { 321 return nil 322 } 323 324 func (daemon *Daemon) cleanupMountsByID(in string) error { 325 return nil 326 } 327 328 func (daemon *Daemon) cleanupMounts() error { 329 return nil 330 } 331 332 func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { 333 return nil, nil, nil 334 } 335 336 func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { 337 config.Root = rootDir 338 // Create the root directory if it doesn't exists 339 if err := system.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) { 340 return err 341 } 342 return nil 343 } 344 345 // runasHyperVContainer returns true if we are going to run as a Hyper-V container 346 func (daemon *Daemon) runAsHyperVContainer(container *container.Container) bool { 347 if container.HostConfig.Isolation.IsDefault() { 348 // Container is set to use the default, so take the default from the daemon configuration 349 return daemon.defaultIsolation.IsHyperV() 350 } 351 352 // Container is requesting an isolation mode. Honour it. 353 return container.HostConfig.Isolation.IsHyperV() 354 355 } 356 357 // conditionalMountOnStart is a platform specific helper function during the 358 // container start to call mount. 359 func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error { 360 // We do not mount if a Hyper-V container 361 if !daemon.runAsHyperVContainer(container) { 362 return daemon.Mount(container) 363 } 364 return nil 365 } 366 367 // conditionalUnmountOnCleanup is a platform specific helper function called 368 // during the cleanup of a container to unmount. 369 func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error { 370 // We do not unmount if a Hyper-V container 371 if !daemon.runAsHyperVContainer(container) { 372 return daemon.Unmount(container) 373 } 374 return nil 375 } 376 377 func driverOptions(config *Config) []nwconfig.Option { 378 return []nwconfig.Option{} 379 } 380 381 func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) { 382 return nil, nil 383 } 384 385 // setDefaultIsolation determine the default isolation mode for the 386 // daemon to run in. This is only applicable on Windows 387 func (daemon *Daemon) setDefaultIsolation() error { 388 daemon.defaultIsolation = containertypes.Isolation("process") 389 // On client SKUs, default to Hyper-V 390 if system.IsWindowsClient() { 391 daemon.defaultIsolation = containertypes.Isolation("hyperv") 392 } 393 for _, option := range daemon.configStore.ExecOptions { 394 key, val, err := parsers.ParseKeyValueOpt(option) 395 if err != nil { 396 return err 397 } 398 key = strings.ToLower(key) 399 switch key { 400 401 case "isolation": 402 if !containertypes.Isolation(val).IsValid() { 403 return fmt.Errorf("Invalid exec-opt value for 'isolation':'%s'", val) 404 } 405 if containertypes.Isolation(val).IsHyperV() { 406 daemon.defaultIsolation = containertypes.Isolation("hyperv") 407 } 408 if containertypes.Isolation(val).IsProcess() { 409 if system.IsWindowsClient() { 410 return fmt.Errorf("Windows client operating systems only support Hyper-V containers") 411 } 412 daemon.defaultIsolation = containertypes.Isolation("process") 413 } 414 default: 415 return fmt.Errorf("Unrecognised exec-opt '%s'\n", key) 416 } 417 } 418 419 logrus.Infof("Windows default isolation mode: %s", daemon.defaultIsolation) 420 return nil 421 } 422 423 func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { 424 var layers []string 425 for _, l := range rootfs.DiffIDs { 426 layers = append(layers, l.String()) 427 } 428 return types.RootFS{ 429 Type: rootfs.Type, 430 Layers: layers, 431 } 432 } 433 434 func setupDaemonProcess(config *Config) error { 435 return nil 436 }