123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- package daemon
- import (
- "fmt"
- "os"
- "strings"
- "github.com/Microsoft/hcsshim"
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/container"
- "github.com/docker/docker/image"
- "github.com/docker/docker/pkg/idtools"
- "github.com/docker/docker/pkg/parsers"
- "github.com/docker/docker/pkg/sysinfo"
- "github.com/docker/docker/pkg/system"
- "github.com/docker/docker/runconfig"
- "github.com/docker/engine-api/types"
- pblkiodev "github.com/docker/engine-api/types/blkiodev"
- containertypes "github.com/docker/engine-api/types/container"
- "github.com/docker/libnetwork"
- nwconfig "github.com/docker/libnetwork/config"
- winlibnetwork "github.com/docker/libnetwork/drivers/windows"
- "github.com/docker/libnetwork/netlabel"
- "github.com/docker/libnetwork/options"
- blkiodev "github.com/opencontainers/runc/libcontainer/configs"
- )
- const (
- defaultNetworkSpace = "172.16.0.0/12"
- platformSupported = true
- windowsMinCPUShares = 1
- windowsMaxCPUShares = 10000
- )
- func getBlkioWeightDevices(config *containertypes.HostConfig) ([]blkiodev.WeightDevice, error) {
- return nil, nil
- }
- func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error {
- return nil
- }
- func getBlkioReadIOpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) {
- return nil, nil
- }
- func getBlkioWriteIOpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) {
- return nil, nil
- }
- func getBlkioReadBpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) {
- return nil, nil
- }
- func getBlkioWriteBpsDevices(config *containertypes.HostConfig) ([]blkiodev.ThrottleDevice, error) {
- return nil, nil
- }
- func setupInitLayer(initLayer string, rootUID, rootGID int) error {
- return nil
- }
- func checkKernel() error {
- return nil
- }
- func (daemon *Daemon) getCgroupDriver() string {
- return ""
- }
- // adaptContainerSettings is called during container creation to modify any
- // settings necessary in the HostConfig structure.
- func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error {
- if hostConfig == nil {
- return nil
- }
- if hostConfig.CPUShares < 0 {
- logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, windowsMinCPUShares)
- hostConfig.CPUShares = windowsMinCPUShares
- } else if hostConfig.CPUShares > windowsMaxCPUShares {
- logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, windowsMaxCPUShares)
- hostConfig.CPUShares = windowsMaxCPUShares
- }
- return nil
- }
- func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo) ([]string, error) {
- warnings := []string{}
- // cpu subsystem checks and adjustments
- if resources.CPUPercent < 0 || resources.CPUPercent > 100 {
- return warnings, fmt.Errorf("Range of CPU percent is from 1 to 100")
- }
- if resources.CPUPercent > 0 && resources.CPUShares > 0 {
- return warnings, fmt.Errorf("Conflicting options: CPU Shares and CPU Percent cannot both be set")
- }
- // TODO Windows: Add more validation of resource settings not supported on Windows
- if resources.BlkioWeight > 0 {
- warnings = append(warnings, "Windows does not support Block I/O weight. Block I/O weight discarded.")
- logrus.Warn("Windows does not support Block I/O weight. Block I/O weight discarded.")
- resources.BlkioWeight = 0
- }
- if len(resources.BlkioWeightDevice) > 0 {
- warnings = append(warnings, "Windows does not support Block I/O weight-device. Weight-device discarded.")
- logrus.Warn("Windows does not support Block I/O weight-device. Weight-device discarded.")
- resources.BlkioWeightDevice = []*pblkiodev.WeightDevice{}
- }
- if len(resources.BlkioDeviceReadBps) > 0 {
- warnings = append(warnings, "Windows does not support Block read limit in bytes per second. Device read bps discarded.")
- logrus.Warn("Windows does not support Block I/O read limit in bytes per second. Device read bps discarded.")
- resources.BlkioDeviceReadBps = []*pblkiodev.ThrottleDevice{}
- }
- if len(resources.BlkioDeviceWriteBps) > 0 {
- warnings = append(warnings, "Windows does not support Block write limit in bytes per second. Device write bps discarded.")
- logrus.Warn("Windows does not support Block I/O write limit in bytes per second. Device write bps discarded.")
- resources.BlkioDeviceWriteBps = []*pblkiodev.ThrottleDevice{}
- }
- if len(resources.BlkioDeviceReadIOps) > 0 {
- warnings = append(warnings, "Windows does not support Block read limit in IO per second. Device read iops discarded.")
- logrus.Warn("Windows does not support Block I/O read limit in IO per second. Device read iops discarded.")
- resources.BlkioDeviceReadIOps = []*pblkiodev.ThrottleDevice{}
- }
- if len(resources.BlkioDeviceWriteIOps) > 0 {
- warnings = append(warnings, "Windows does not support Block write limit in IO per second. Device write iops discarded.")
- logrus.Warn("Windows does not support Block I/O write limit in IO per second. Device write iops discarded.")
- resources.BlkioDeviceWriteIOps = []*pblkiodev.ThrottleDevice{}
- }
- return warnings, nil
- }
- // verifyPlatformContainerSettings performs platform-specific validation of the
- // hostconfig and config structures.
- func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
- warnings := []string{}
- w, err := verifyContainerResources(&hostConfig.Resources, nil)
- warnings = append(warnings, w...)
- if err != nil {
- return warnings, err
- }
- return warnings, nil
- }
- // platformReload update configuration with platform specific options
- func (daemon *Daemon) platformReload(config *Config, attributes *map[string]string) {
- }
- // verifyDaemonSettings performs validation of daemon config struct
- func verifyDaemonSettings(config *Config) error {
- return nil
- }
- // checkSystem validates platform-specific requirements
- func checkSystem() error {
- // Validate the OS version. Note that docker.exe must be manifested for this
- // call to return the correct version.
- osv := system.GetOSVersion()
- if osv.MajorVersion < 10 {
- return fmt.Errorf("This version of Windows does not support the docker daemon")
- }
- if osv.Build < 14300 {
- return fmt.Errorf("The Windows daemon requires Windows Server 2016 Technical Preview 5 build 14300 or later")
- }
- return nil
- }
- // configureKernelSecuritySupport configures and validate security support for the kernel
- func configureKernelSecuritySupport(config *Config, driverName string) error {
- return nil
- }
- // configureMaxThreads sets the Go runtime max threads threshold
- func configureMaxThreads(config *Config) error {
- return nil
- }
- func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
- netOptions, err := daemon.networkOptions(config, nil)
- if err != nil {
- return nil, err
- }
- controller, err := libnetwork.New(netOptions...)
- if err != nil {
- return nil, fmt.Errorf("error obtaining controller instance: %v", err)
- }
- hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "")
- if err != nil {
- return nil, err
- }
- // Remove networks not present in HNS
- for _, v := range controller.Networks() {
- options := v.Info().DriverOptions()
- hnsid := options[winlibnetwork.HNSID]
- found := false
- for _, v := range hnsresponse {
- if v.Id == hnsid {
- found = true
- break
- }
- }
- if !found {
- err = v.Delete()
- if err != nil {
- return nil, err
- }
- }
- }
- _, err = controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false))
- if err != nil {
- return nil, err
- }
- // discover and add HNS networks to windows
- // network that exist are removed and added again
- for _, v := range hnsresponse {
- var n libnetwork.Network
- s := func(current libnetwork.Network) bool {
- options := current.Info().DriverOptions()
- if options[winlibnetwork.HNSID] == v.Id {
- n = current
- return true
- }
- return false
- }
- controller.WalkNetworks(s)
- if n != nil {
- v.Name = n.Name()
- n.Delete()
- }
- netOption := map[string]string{
- winlibnetwork.NetworkName: v.Name,
- winlibnetwork.HNSID: v.Id,
- }
- v4Conf := []*libnetwork.IpamConf{}
- for _, subnet := range v.Subnets {
- ipamV4Conf := libnetwork.IpamConf{}
- ipamV4Conf.PreferredPool = subnet.AddressPrefix
- ipamV4Conf.Gateway = subnet.GatewayAddress
- v4Conf = append(v4Conf, &ipamV4Conf)
- }
- name := v.Name
- // There is only one nat network supported in windows.
- // If it exists with a different name add it as the default name
- if runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) {
- name = runconfig.DefaultDaemonNetworkMode().NetworkName()
- }
- v6Conf := []*libnetwork.IpamConf{}
- _, err := controller.NewNetwork(strings.ToLower(v.Type), name, "",
- libnetwork.NetworkOptionGeneric(options.Generic{
- netlabel.GenericData: netOption,
- }),
- libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
- )
- if err != nil {
- logrus.Errorf("Error occurred when creating network %v", err)
- }
- }
- if !config.DisableBridge {
- // Initialize default driver "bridge"
- if err := initBridgeDriver(controller, config); err != nil {
- return nil, err
- }
- }
- return controller, nil
- }
- func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
- if _, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil {
- return nil
- }
- netOption := map[string]string{
- winlibnetwork.NetworkName: runconfig.DefaultDaemonNetworkMode().NetworkName(),
- }
- ipamV4Conf := libnetwork.IpamConf{}
- if config.bridgeConfig.FixedCIDR == "" {
- ipamV4Conf.PreferredPool = defaultNetworkSpace
- } else {
- ipamV4Conf.PreferredPool = config.bridgeConfig.FixedCIDR
- }
- v4Conf := []*libnetwork.IpamConf{&ipamV4Conf}
- v6Conf := []*libnetwork.IpamConf{}
- _, err := controller.NewNetwork(string(runconfig.DefaultDaemonNetworkMode()), runconfig.DefaultDaemonNetworkMode().NetworkName(), "",
- libnetwork.NetworkOptionGeneric(options.Generic{
- netlabel.GenericData: netOption,
- }),
- libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
- )
- if err != nil {
- return fmt.Errorf("Error creating default network: %v", err)
- }
- return nil
- }
- // registerLinks sets up links between containers and writes the
- // configuration out for persistence. As of Windows TP4, links are not supported.
- func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
- return nil
- }
- func (daemon *Daemon) cleanupMountsByID(in string) error {
- return nil
- }
- func (daemon *Daemon) cleanupMounts() error {
- return nil
- }
- func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) {
- return nil, nil, nil
- }
- func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error {
- config.Root = rootDir
- // Create the root directory if it doesn't exists
- if err := system.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) {
- return err
- }
- return nil
- }
- // runasHyperVContainer returns true if we are going to run as a Hyper-V container
- func (daemon *Daemon) runAsHyperVContainer(container *container.Container) bool {
- if container.HostConfig.Isolation.IsDefault() {
- // Container is set to use the default, so take the default from the daemon configuration
- return daemon.defaultIsolation.IsHyperV()
- }
- // Container is requesting an isolation mode. Honour it.
- return container.HostConfig.Isolation.IsHyperV()
- }
- // conditionalMountOnStart is a platform specific helper function during the
- // container start to call mount.
- func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
- // We do not mount if a Hyper-V container
- if !daemon.runAsHyperVContainer(container) {
- return daemon.Mount(container)
- }
- return nil
- }
- // conditionalUnmountOnCleanup is a platform specific helper function called
- // during the cleanup of a container to unmount.
- func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error {
- // We do not unmount if a Hyper-V container
- if !daemon.runAsHyperVContainer(container) {
- return daemon.Unmount(container)
- }
- return nil
- }
- func driverOptions(config *Config) []nwconfig.Option {
- return []nwconfig.Option{}
- }
- func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
- return nil, nil
- }
- // setDefaultIsolation determine the default isolation mode for the
- // daemon to run in. This is only applicable on Windows
- func (daemon *Daemon) setDefaultIsolation() error {
- daemon.defaultIsolation = containertypes.Isolation("process")
- // On client SKUs, default to Hyper-V
- if system.IsWindowsClient() {
- daemon.defaultIsolation = containertypes.Isolation("hyperv")
- }
- for _, option := range daemon.configStore.ExecOptions {
- key, val, err := parsers.ParseKeyValueOpt(option)
- if err != nil {
- return err
- }
- key = strings.ToLower(key)
- switch key {
- case "isolation":
- if !containertypes.Isolation(val).IsValid() {
- return fmt.Errorf("Invalid exec-opt value for 'isolation':'%s'", val)
- }
- if containertypes.Isolation(val).IsHyperV() {
- daemon.defaultIsolation = containertypes.Isolation("hyperv")
- }
- if containertypes.Isolation(val).IsProcess() {
- if system.IsWindowsClient() {
- return fmt.Errorf("Windows client operating systems only support Hyper-V containers")
- }
- daemon.defaultIsolation = containertypes.Isolation("process")
- }
- default:
- return fmt.Errorf("Unrecognised exec-opt '%s'\n", key)
- }
- }
- logrus.Infof("Windows default isolation mode: %s", daemon.defaultIsolation)
- return nil
- }
- func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
- var layers []string
- for _, l := range rootfs.DiffIDs {
- layers = append(layers, l.String())
- }
- return types.RootFS{
- Type: rootfs.Type,
- Layers: layers,
- BaseLayer: rootfs.BaseLayer,
- }
- }
- func setupDaemonProcess(config *Config) error {
- return nil
- }
|