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  }