2018-02-05 21:05:59 +00:00
|
|
|
package daemon // import "github.com/docker/docker/daemon"
|
2015-05-15 23:34:26 +00:00
|
|
|
|
|
|
|
import (
|
2017-09-22 13:52:41 +00:00
|
|
|
"context"
|
2015-05-15 23:34:26 +00:00
|
|
|
"fmt"
|
2019-08-13 07:10:19 +00:00
|
|
|
"math"
|
2017-02-02 19:22:12 +00:00
|
|
|
"path/filepath"
|
2019-08-13 07:10:19 +00:00
|
|
|
"runtime"
|
2015-11-18 22:20:54 +00:00
|
|
|
"strings"
|
2015-05-15 23:34:26 +00:00
|
|
|
|
2016-03-10 04:33:21 +00:00
|
|
|
"github.com/Microsoft/hcsshim"
|
2019-04-17 10:39:07 +00:00
|
|
|
"github.com/Microsoft/hcsshim/osversion"
|
2016-09-06 18:18:12 +00:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
2015-11-12 19:55:17 +00:00
|
|
|
"github.com/docker/docker/container"
|
2017-01-23 11:23:07 +00:00
|
|
|
"github.com/docker/docker/daemon/config"
|
2021-02-26 23:23:55 +00:00
|
|
|
"github.com/docker/docker/libcontainerd/local"
|
|
|
|
"github.com/docker/docker/libcontainerd/remote"
|
2021-05-28 00:15:56 +00:00
|
|
|
"github.com/docker/docker/libnetwork"
|
|
|
|
nwconfig "github.com/docker/docker/libnetwork/config"
|
|
|
|
"github.com/docker/docker/libnetwork/datastore"
|
|
|
|
winlibnetwork "github.com/docker/docker/libnetwork/drivers/windows"
|
|
|
|
"github.com/docker/docker/libnetwork/netlabel"
|
|
|
|
"github.com/docker/docker/libnetwork/options"
|
2017-08-04 00:22:00 +00:00
|
|
|
"github.com/docker/docker/pkg/containerfs"
|
2016-01-08 03:43:11 +00:00
|
|
|
"github.com/docker/docker/pkg/idtools"
|
2016-03-18 18:53:27 +00:00
|
|
|
"github.com/docker/docker/pkg/parsers"
|
2022-03-15 23:41:30 +00:00
|
|
|
"github.com/docker/docker/pkg/parsers/operatingsystem"
|
2016-09-07 23:08:51 +00:00
|
|
|
"github.com/docker/docker/pkg/platform"
|
2016-02-25 01:51:46 +00:00
|
|
|
"github.com/docker/docker/pkg/sysinfo"
|
2015-10-15 18:40:14 +00:00
|
|
|
"github.com/docker/docker/pkg/system"
|
2016-02-25 01:51:46 +00:00
|
|
|
"github.com/docker/docker/runconfig"
|
2017-09-21 22:09:41 +00:00
|
|
|
"github.com/pkg/errors"
|
2017-07-26 21:42:13 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2016-11-18 20:34:25 +00:00
|
|
|
"golang.org/x/sys/windows"
|
2017-09-21 22:09:41 +00:00
|
|
|
"golang.org/x/sys/windows/svc/mgr"
|
2015-05-15 23:34:26 +00:00
|
|
|
)
|
|
|
|
|
2015-08-07 16:33:29 +00:00
|
|
|
const (
|
2019-10-13 00:29:21 +00:00
|
|
|
isWindows = true
|
2016-11-01 20:02:46 +00:00
|
|
|
platformSupported = true
|
|
|
|
windowsMinCPUShares = 1
|
|
|
|
windowsMaxCPUShares = 10000
|
|
|
|
windowsMinCPUPercent = 1
|
|
|
|
windowsMaxCPUPercent = 100
|
2021-02-26 23:23:55 +00:00
|
|
|
|
|
|
|
windowsV1RuntimeName = "com.docker.hcsshim.v1"
|
|
|
|
windowsV2RuntimeName = "io.containerd.runhcs.v1"
|
2015-08-07 16:33:29 +00:00
|
|
|
)
|
2015-07-13 19:34:58 +00:00
|
|
|
|
2019-08-13 07:10:19 +00:00
|
|
|
// Windows containers are much larger than Linux containers and each of them
|
|
|
|
// have > 20 system processes which why we use much smaller parallelism value.
|
2018-12-04 16:44:45 +00:00
|
|
|
func adjustParallelLimit(n int, limit int) int {
|
2019-08-13 07:10:19 +00:00
|
|
|
return int(math.Max(1, math.Floor(float64(runtime.NumCPU())*.8)))
|
2018-12-04 16:44:45 +00:00
|
|
|
}
|
|
|
|
|
2017-02-02 19:22:12 +00:00
|
|
|
// Windows has no concept of an execution state directory. So use config.Root here.
|
|
|
|
func getPluginExecRoot(root string) string {
|
|
|
|
return filepath.Join(root, "plugins")
|
|
|
|
}
|
|
|
|
|
2017-01-09 01:22:05 +00:00
|
|
|
func (daemon *Daemon) parseSecurityOpt(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
2015-05-15 23:34:26 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-03-14 19:24:29 +00:00
|
|
|
func setupInitLayer(idMapping idtools.IdentityMapping) func(containerfs.ContainerFS) error {
|
2016-09-21 18:45:25 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-07-30 22:28:11 +00:00
|
|
|
// adaptContainerSettings is called during container creation to modify any
|
|
|
|
// settings necessary in the HostConfig structure.
|
2015-12-18 18:36:17 +00:00
|
|
|
func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error {
|
2015-12-02 02:53:52 +00:00
|
|
|
return nil
|
2015-07-13 07:17:43 +00:00
|
|
|
}
|
|
|
|
|
2018-12-18 22:41:52 +00:00
|
|
|
// verifyPlatformContainerResources performs platform-specific validation of the container's resource-configuration
|
|
|
|
func verifyPlatformContainerResources(resources *containertypes.Resources, isHyperv bool) (warnings []string, err error) {
|
2017-06-30 17:34:40 +00:00
|
|
|
fixMemorySwappiness(resources)
|
2016-11-01 20:02:46 +00:00
|
|
|
if !isHyperv {
|
|
|
|
// The processor resource controls are mutually exclusive on
|
|
|
|
// Windows Server Containers, the order of precedence is
|
|
|
|
// CPUCount first, then CPUShares, and CPUPercent last.
|
|
|
|
if resources.CPUCount > 0 {
|
|
|
|
if resources.CPUShares > 0 {
|
|
|
|
warnings = append(warnings, "Conflicting options: CPU count takes priority over CPU shares on Windows Server Containers. CPU shares discarded")
|
|
|
|
resources.CPUShares = 0
|
|
|
|
}
|
|
|
|
if resources.CPUPercent > 0 {
|
|
|
|
warnings = append(warnings, "Conflicting options: CPU count takes priority over CPU percent on Windows Server Containers. CPU percent discarded")
|
|
|
|
resources.CPUPercent = 0
|
|
|
|
}
|
|
|
|
} else if resources.CPUShares > 0 {
|
|
|
|
if resources.CPUPercent > 0 {
|
|
|
|
warnings = append(warnings, "Conflicting options: CPU shares takes priority over CPU percent on Windows Server Containers. CPU percent discarded")
|
|
|
|
resources.CPUPercent = 0
|
|
|
|
}
|
|
|
|
}
|
2016-03-05 01:24:09 +00:00
|
|
|
}
|
|
|
|
|
2016-11-09 23:18:54 +00:00
|
|
|
if resources.CPUShares < 0 || resources.CPUShares > windowsMaxCPUShares {
|
|
|
|
return warnings, fmt.Errorf("range of CPUShares is from %d to %d", windowsMinCPUShares, windowsMaxCPUShares)
|
|
|
|
}
|
|
|
|
if resources.CPUPercent < 0 || resources.CPUPercent > windowsMaxCPUPercent {
|
|
|
|
return warnings, fmt.Errorf("range of CPUPercent is from %d to %d", windowsMinCPUPercent, windowsMaxCPUPercent)
|
|
|
|
}
|
|
|
|
if resources.CPUCount < 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid CPUCount: CPUCount cannot be negative")
|
2016-11-01 17:12:29 +00:00
|
|
|
}
|
|
|
|
|
2016-11-09 23:18:54 +00:00
|
|
|
if resources.NanoCPUs > 0 && resources.CPUPercent > 0 {
|
|
|
|
return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Percent cannot both be set")
|
|
|
|
}
|
2016-11-01 17:12:29 +00:00
|
|
|
if resources.NanoCPUs > 0 && resources.CPUShares > 0 {
|
2016-11-09 23:18:54 +00:00
|
|
|
return warnings, fmt.Errorf("conflicting options: Nano CPUs and CPU Shares cannot both be set")
|
2016-11-01 17:12:29 +00:00
|
|
|
}
|
2016-11-15 23:48:46 +00:00
|
|
|
// The precision we could get is 0.01, because on Windows we have to convert to CPUPercent.
|
|
|
|
// We don't set the lower limit here and it is up to the underlying platform (e.g., Windows) to return an error.
|
2016-11-01 17:12:29 +00:00
|
|
|
if resources.NanoCPUs < 0 || resources.NanoCPUs > int64(sysinfo.NumCPU())*1e9 {
|
2016-11-15 23:48:46 +00:00
|
|
|
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())
|
2016-11-01 17:12:29 +00:00
|
|
|
}
|
|
|
|
|
2016-11-09 23:18:54 +00:00
|
|
|
if len(resources.BlkioDeviceReadBps) > 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceReadBps")
|
|
|
|
}
|
|
|
|
if len(resources.BlkioDeviceReadIOps) > 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceReadIOps")
|
|
|
|
}
|
|
|
|
if len(resources.BlkioDeviceWriteBps) > 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceWriteBps")
|
|
|
|
}
|
|
|
|
if len(resources.BlkioDeviceWriteIOps) > 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support BlkioDeviceWriteIOps")
|
|
|
|
}
|
2016-02-25 01:51:46 +00:00
|
|
|
if resources.BlkioWeight > 0 {
|
2016-11-09 23:18:54 +00:00
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support BlkioWeight")
|
2016-02-25 01:51:46 +00:00
|
|
|
}
|
|
|
|
if len(resources.BlkioWeightDevice) > 0 {
|
2016-11-09 23:18:54 +00:00
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support BlkioWeightDevice")
|
2016-02-25 01:51:46 +00:00
|
|
|
}
|
2016-11-09 23:18:54 +00:00
|
|
|
if resources.CgroupParent != "" {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support CgroupParent")
|
2016-02-25 01:51:46 +00:00
|
|
|
}
|
2016-11-09 23:18:54 +00:00
|
|
|
if resources.CPUPeriod != 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support CPUPeriod")
|
2016-02-25 01:51:46 +00:00
|
|
|
}
|
2016-11-09 23:18:54 +00:00
|
|
|
if resources.CpusetCpus != "" {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support CpusetCpus")
|
2016-02-25 01:51:46 +00:00
|
|
|
}
|
2016-11-09 23:18:54 +00:00
|
|
|
if resources.CpusetMems != "" {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support CpusetMems")
|
|
|
|
}
|
|
|
|
if resources.KernelMemory != 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support KernelMemory")
|
|
|
|
}
|
|
|
|
if resources.MemoryReservation != 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support MemoryReservation")
|
|
|
|
}
|
|
|
|
if resources.MemorySwap != 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support MemorySwap")
|
|
|
|
}
|
2017-06-30 17:34:40 +00:00
|
|
|
if resources.MemorySwappiness != nil {
|
2016-11-09 23:18:54 +00:00
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support MemorySwappiness")
|
|
|
|
}
|
|
|
|
if resources.OomKillDisable != nil && *resources.OomKillDisable {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support OomKillDisable")
|
|
|
|
}
|
2017-04-11 11:28:13 +00:00
|
|
|
if resources.PidsLimit != nil && *resources.PidsLimit != 0 {
|
2016-11-09 23:18:54 +00:00
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support PidsLimit")
|
|
|
|
}
|
|
|
|
if len(resources.Ulimits) != 0 {
|
|
|
|
return warnings, fmt.Errorf("invalid option: Windows does not support Ulimits")
|
2016-02-25 01:51:46 +00:00
|
|
|
}
|
2016-03-05 01:24:09 +00:00
|
|
|
return warnings, nil
|
|
|
|
}
|
|
|
|
|
2015-07-30 22:28:11 +00:00
|
|
|
// verifyPlatformContainerSettings performs platform-specific validation of the
|
|
|
|
// hostconfig and config structures.
|
2018-12-18 22:20:17 +00:00
|
|
|
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, update bool) (warnings []string, err error) {
|
2018-12-19 00:28:08 +00:00
|
|
|
if hostConfig == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2022-02-17 16:08:46 +00:00
|
|
|
return verifyPlatformContainerResources(&hostConfig.Resources, daemon.runAsHyperVContainer(hostConfig))
|
2015-05-15 23:34:26 +00:00
|
|
|
}
|
|
|
|
|
2016-01-23 02:15:09 +00:00
|
|
|
// verifyDaemonSettings performs validation of daemon config struct
|
2017-01-23 11:23:07 +00:00
|
|
|
func verifyDaemonSettings(config *config.Config) error {
|
2015-05-15 23:34:26 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-07-11 19:32:08 +00:00
|
|
|
// checkSystem validates platform-specific requirements
|
2015-05-15 23:34:26 +00:00
|
|
|
func checkSystem() error {
|
2019-09-11 13:16:27 +00:00
|
|
|
// Validate the OS version. Note that dockerd.exe must be manifested for this
|
2015-05-15 23:34:26 +00:00
|
|
|
// call to return the correct version.
|
2022-02-17 16:08:46 +00:00
|
|
|
if osversion.Get().MajorVersion < 10 || osversion.Build() < osversion.RS5 {
|
|
|
|
return fmt.Errorf("this version of Windows does not support the docker daemon (Windows build %d or higher is required)", osversion.RS5)
|
2015-11-11 22:47:02 +00:00
|
|
|
}
|
2016-11-18 20:34:25 +00:00
|
|
|
|
|
|
|
vmcompute := windows.NewLazySystemDLL("vmcompute.dll")
|
|
|
|
if vmcompute.Load() != nil {
|
2017-09-25 19:39:27 +00:00
|
|
|
return fmt.Errorf("failed to load vmcompute.dll, ensure that the Containers feature is installed")
|
2016-11-18 20:34:25 +00:00
|
|
|
}
|
2017-02-01 18:52:16 +00:00
|
|
|
|
2017-09-21 22:09:41 +00:00
|
|
|
// Ensure that the required Host Network Service and vmcompute services
|
|
|
|
// are running. Docker will fail in unexpected ways if this is not present.
|
|
|
|
var requiredServices = []string{"hns", "vmcompute"}
|
|
|
|
if err := ensureServicesInstalled(requiredServices); err != nil {
|
|
|
|
return errors.Wrap(err, "a required service is not installed, ensure the Containers feature is installed")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ensureServicesInstalled(services []string) error {
|
|
|
|
m, err := mgr.Connect()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer m.Disconnect()
|
|
|
|
for _, service := range services {
|
|
|
|
s, err := m.OpenService(service)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "failed to open service %s", service)
|
|
|
|
}
|
|
|
|
s.Close()
|
|
|
|
}
|
2017-03-27 21:32:18 +00:00
|
|
|
return nil
|
2015-05-15 23:34:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// configureKernelSecuritySupport configures and validate security support for the kernel
|
2017-08-24 18:48:16 +00:00
|
|
|
func configureKernelSecuritySupport(config *config.Config, driverName string) error {
|
2015-05-15 23:34:26 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-12-02 10:26:30 +00:00
|
|
|
// configureMaxThreads sets the Go runtime max threads threshold
|
2017-01-23 11:23:07 +00:00
|
|
|
func configureMaxThreads(config *config.Config) error {
|
2015-12-02 10:26:30 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-04-26 08:32:10 +00:00
|
|
|
func (daemon *Daemon) initNetworkController(activeSandboxes map[string]interface{}) error {
|
2022-04-23 21:12:55 +00:00
|
|
|
netOptions, err := daemon.networkOptions(nil, nil)
|
2016-03-10 04:33:21 +00:00
|
|
|
if err != nil {
|
2022-04-26 08:32:10 +00:00
|
|
|
return err
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
2022-04-26 08:32:10 +00:00
|
|
|
daemon.netController, err = libnetwork.New(netOptions...)
|
2016-03-10 04:33:21 +00:00
|
|
|
if err != nil {
|
2022-04-26 08:32:10 +00:00
|
|
|
return errors.Wrap(err, "error obtaining controller instance")
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "")
|
|
|
|
if err != nil {
|
2022-04-26 08:32:10 +00:00
|
|
|
return err
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove networks not present in HNS
|
2022-04-26 08:32:10 +00:00
|
|
|
for _, v := range daemon.netController.Networks() {
|
2022-04-23 21:12:55 +00:00
|
|
|
hnsid := v.Info().DriverOptions()[winlibnetwork.HNSID]
|
2016-03-10 04:33:21 +00:00
|
|
|
found := false
|
|
|
|
|
|
|
|
for _, v := range hnsresponse {
|
|
|
|
if v.Id == hnsid {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
2022-07-19 20:47:22 +00:00
|
|
|
// non-default nat networks should be re-created if missing from HNS
|
|
|
|
if v.Type() == "nat" && v.Name() != "nat" {
|
|
|
|
_, _, v4Conf, v6Conf := v.Info().IpamConfig()
|
|
|
|
netOption := map[string]string{}
|
|
|
|
for k, v := range v.Info().DriverOptions() {
|
|
|
|
if k != winlibnetwork.NetworkName && k != winlibnetwork.HNSID {
|
|
|
|
netOption[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
name := v.Name()
|
|
|
|
id := v.ID()
|
|
|
|
|
|
|
|
err = v.Delete()
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Error occurred when removing network %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := daemon.netController.NewNetwork("nat", name, id,
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2016-11-10 01:54:15 +00:00
|
|
|
// global networks should not be deleted by local HNS
|
|
|
|
if v.Info().Scope() != datastore.GlobalScope {
|
|
|
|
err = v.Delete()
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Error occurred when removing network %v", err)
|
|
|
|
}
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-26 08:32:10 +00:00
|
|
|
_, err = daemon.netController.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false))
|
2016-03-10 04:33:21 +00:00
|
|
|
if err != nil {
|
2022-04-26 08:32:10 +00:00
|
|
|
return err
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
|
2016-06-09 19:09:13 +00:00
|
|
|
defaultNetworkExists := false
|
|
|
|
|
2022-04-26 08:32:10 +00:00
|
|
|
if network, err := daemon.netController.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil {
|
2022-04-23 21:12:55 +00:00
|
|
|
hnsid := network.Info().DriverOptions()[winlibnetwork.HNSID]
|
2016-06-09 19:09:13 +00:00
|
|
|
for _, v := range hnsresponse {
|
2022-04-23 21:12:55 +00:00
|
|
|
if hnsid == v.Id {
|
2016-06-09 19:09:13 +00:00
|
|
|
defaultNetworkExists = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-10 04:33:21 +00:00
|
|
|
// discover and add HNS networks to windows
|
|
|
|
// network that exist are removed and added again
|
|
|
|
for _, v := range hnsresponse {
|
2018-09-06 09:54:23 +00:00
|
|
|
networkTypeNorm := strings.ToLower(v.Type)
|
|
|
|
if networkTypeNorm == "private" || networkTypeNorm == "internal" {
|
2017-05-05 16:03:22 +00:00
|
|
|
continue // workaround for HNS reporting unsupported networks
|
|
|
|
}
|
2016-03-10 04:33:21 +00:00
|
|
|
var n libnetwork.Network
|
|
|
|
s := func(current libnetwork.Network) bool {
|
2022-04-23 21:12:55 +00:00
|
|
|
hnsid := current.Info().DriverOptions()[winlibnetwork.HNSID]
|
|
|
|
if hnsid == v.Id {
|
2016-03-10 04:33:21 +00:00
|
|
|
n = current
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-04-26 08:32:10 +00:00
|
|
|
daemon.netController.WalkNetworks(s)
|
2017-11-21 20:00:26 +00:00
|
|
|
|
|
|
|
drvOptions := make(map[string]string)
|
2019-01-16 01:05:23 +00:00
|
|
|
nid := ""
|
2016-03-10 04:33:21 +00:00
|
|
|
if n != nil {
|
2019-01-16 01:05:23 +00:00
|
|
|
nid = n.ID()
|
|
|
|
|
2016-11-10 01:54:15 +00:00
|
|
|
// global networks should not be deleted by local HNS
|
|
|
|
if n.Info().Scope() == datastore.GlobalScope {
|
|
|
|
continue
|
|
|
|
}
|
2016-03-10 04:33:21 +00:00
|
|
|
v.Name = n.Name()
|
2016-06-09 19:09:13 +00:00
|
|
|
// This will not cause network delete from HNS as the network
|
|
|
|
// is not yet populated in the libnetwork windows driver
|
2017-11-21 20:00:26 +00:00
|
|
|
|
|
|
|
// restore option if it existed before
|
|
|
|
drvOptions = n.Info().DriverOptions()
|
2016-03-10 04:33:21 +00:00
|
|
|
n.Delete()
|
|
|
|
}
|
|
|
|
netOption := map[string]string{
|
|
|
|
winlibnetwork.NetworkName: v.Name,
|
|
|
|
winlibnetwork.HNSID: v.Id,
|
|
|
|
}
|
|
|
|
|
2017-11-21 20:00:26 +00:00
|
|
|
// add persisted driver options
|
|
|
|
for k, v := range drvOptions {
|
|
|
|
if k != winlibnetwork.NetworkName && k != winlibnetwork.HNSID {
|
|
|
|
netOption[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-10 04:33:21 +00:00
|
|
|
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
|
2016-06-09 19:09:13 +00:00
|
|
|
|
|
|
|
// If there is no nat network create one from the first NAT network
|
2017-01-13 05:09:57 +00:00
|
|
|
// encountered if it doesn't already exist
|
|
|
|
if !defaultNetworkExists &&
|
|
|
|
runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) &&
|
|
|
|
n == nil {
|
2016-03-10 04:33:21 +00:00
|
|
|
name = runconfig.DefaultDaemonNetworkMode().NetworkName()
|
2016-06-09 19:09:13 +00:00
|
|
|
defaultNetworkExists = true
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
v6Conf := []*libnetwork.IpamConf{}
|
2022-04-26 08:32:10 +00:00
|
|
|
_, err := daemon.netController.NewNetwork(strings.ToLower(v.Type), name, nid,
|
2016-03-10 04:33:21 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-26 08:32:10 +00:00
|
|
|
if !daemon.configStore.DisableBridge {
|
2016-03-10 04:33:21 +00:00
|
|
|
// Initialize default driver "bridge"
|
2022-04-26 08:32:10 +00:00
|
|
|
if err := initBridgeDriver(daemon.netController, daemon.configStore); err != nil {
|
|
|
|
return err
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-26 08:32:10 +00:00
|
|
|
return nil
|
2015-05-15 23:34:26 +00:00
|
|
|
}
|
|
|
|
|
2017-01-23 11:23:07 +00:00
|
|
|
func initBridgeDriver(controller libnetwork.NetworkController, config *config.Config) error {
|
2016-03-10 04:33:21 +00:00
|
|
|
if _, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil {
|
|
|
|
return nil
|
2015-07-13 19:34:58 +00:00
|
|
|
}
|
2016-03-10 04:33:21 +00:00
|
|
|
|
|
|
|
netOption := map[string]string{
|
|
|
|
winlibnetwork.NetworkName: runconfig.DefaultDaemonNetworkMode().NetworkName(),
|
|
|
|
}
|
|
|
|
|
2019-11-06 18:54:28 +00:00
|
|
|
var ipamOption libnetwork.NetworkOption
|
|
|
|
var subnetPrefix string
|
|
|
|
|
2017-01-23 11:23:07 +00:00
|
|
|
if config.BridgeConfig.FixedCIDR != "" {
|
|
|
|
subnetPrefix = config.BridgeConfig.FixedCIDR
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
|
|
|
|
2019-11-06 18:54:28 +00:00
|
|
|
if subnetPrefix != "" {
|
|
|
|
ipamV4Conf := libnetwork.IpamConf{PreferredPool: subnetPrefix}
|
|
|
|
v4Conf := []*libnetwork.IpamConf{&ipamV4Conf}
|
|
|
|
v6Conf := []*libnetwork.IpamConf{}
|
|
|
|
ipamOption = libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil)
|
|
|
|
}
|
2016-03-10 04:33:21 +00:00
|
|
|
|
2016-05-08 07:33:16 +00:00
|
|
|
_, err := controller.NewNetwork(string(runconfig.DefaultDaemonNetworkMode()), runconfig.DefaultDaemonNetworkMode().NetworkName(), "",
|
2016-03-10 04:33:21 +00:00
|
|
|
libnetwork.NetworkOptionGeneric(options.Generic{
|
|
|
|
netlabel.GenericData: netOption,
|
|
|
|
}),
|
2016-06-09 19:09:13 +00:00
|
|
|
ipamOption,
|
2016-03-10 04:33:21 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
2022-04-26 08:32:10 +00:00
|
|
|
return errors.Wrap(err, "error creating default network")
|
2016-03-10 04:33:21 +00:00
|
|
|
}
|
2016-06-09 19:09:13 +00:00
|
|
|
|
2016-03-10 04:33:21 +00:00
|
|
|
return nil
|
2015-05-15 23:34:26 +00:00
|
|
|
}
|
2015-06-23 17:13:42 +00:00
|
|
|
|
2015-07-30 21:01:53 +00:00
|
|
|
// registerLinks sets up links between containers and writes the
|
2015-11-16 05:32:31 +00:00
|
|
|
// configuration out for persistence. As of Windows TP4, links are not supported.
|
2015-12-18 18:36:17 +00:00
|
|
|
func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
2015-06-23 17:13:42 +00:00
|
|
|
return nil
|
|
|
|
}
|
2015-07-16 21:14:58 +00:00
|
|
|
|
2016-03-18 18:53:27 +00:00
|
|
|
func (daemon *Daemon) cleanupMountsByID(in string) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-08-03 22:05:34 +00:00
|
|
|
func (daemon *Daemon) cleanupMounts() error {
|
|
|
|
return nil
|
2020-09-19 16:45:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func recursiveUnmount(_ string) error {
|
|
|
|
return nil
|
2015-08-03 22:05:34 +00:00
|
|
|
}
|
2015-11-03 01:06:09 +00:00
|
|
|
|
2022-03-14 19:24:29 +00:00
|
|
|
func setupRemappedRoot(config *config.Config) (idtools.IdentityMapping, error) {
|
|
|
|
return idtools.IdentityMapping{}, nil
|
2016-01-08 03:43:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-16 06:20:33 +00:00
|
|
|
func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools.Identity) error {
|
2016-01-08 03:43:11 +00:00
|
|
|
config.Root = rootDir
|
|
|
|
// Create the root directory if it doesn't exists
|
Simplify/fix MkdirAll usage
This subtle bug keeps lurking in because error checking for `Mkdir()`
and `MkdirAll()` is slightly different wrt to `EEXIST`/`IsExist`:
- for `Mkdir()`, `IsExist` error should (usually) be ignored
(unless you want to make sure directory was not there before)
as it means "the destination directory was already there"
- for `MkdirAll()`, `IsExist` error should NEVER be ignored.
Mostly, this commit just removes ignoring the IsExist error, as it
should not be ignored.
Also, there are a couple of cases then IsExist is handled as
"directory already exist" which is wrong. As a result, some code
that never worked as intended is now removed.
NOTE that `idtools.MkdirAndChown()` behaves like `os.MkdirAll()`
rather than `os.Mkdir()` -- so its description is amended accordingly,
and its usage is handled as such (i.e. IsExist error is not ignored).
For more details, a quote from my runc commit 6f82d4b (July 2015):
TL;DR: check for IsExist(err) after a failed MkdirAll() is both
redundant and wrong -- so two reasons to remove it.
Quoting MkdirAll documentation:
> MkdirAll creates a directory named path, along with any necessary
> parents, and returns nil, or else returns an error. If path
> is already a directory, MkdirAll does nothing and returns nil.
This means two things:
1. If a directory to be created already exists, no error is
returned.
2. If the error returned is IsExist (EEXIST), it means there exists
a non-directory with the same name as MkdirAll need to use for
directory. Example: we want to MkdirAll("a/b"), but file "a"
(or "a/b") already exists, so MkdirAll fails.
The above is a theory, based on quoted documentation and my UNIX
knowledge.
3. In practice, though, current MkdirAll implementation [1] returns
ENOTDIR in most of cases described in #2, with the exception when
there is a race between MkdirAll and someone else creating the
last component of MkdirAll argument as a file. In this very case
MkdirAll() will indeed return EEXIST.
Because of #1, IsExist check after MkdirAll is not needed.
Because of #2 and #3, ignoring IsExist error is just plain wrong,
as directory we require is not created. It's cleaner to report
the error now.
Note this error is all over the tree, I guess due to copy-paste,
or trying to follow the same usage pattern as for Mkdir(),
or some not quite correct examples on the Internet.
[1] https://github.com/golang/go/blob/f9ed2f75/src/os/path.go
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2017-09-25 19:39:36 +00:00
|
|
|
if err := system.MkdirAllWithACL(config.Root, 0, system.SddlAdministratorsLocalSystem); err != nil {
|
2016-01-08 03:43:11 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-03-19 03:09:54 +00:00
|
|
|
// runasHyperVContainer returns true if we are going to run as a Hyper-V container
|
2016-11-01 20:02:46 +00:00
|
|
|
func (daemon *Daemon) runAsHyperVContainer(hostConfig *containertypes.HostConfig) bool {
|
|
|
|
if hostConfig.Isolation.IsDefault() {
|
2016-03-18 18:53:27 +00:00
|
|
|
// Container is set to use the default, so take the default from the daemon configuration
|
2016-03-19 03:09:54 +00:00
|
|
|
return daemon.defaultIsolation.IsHyperV()
|
2016-03-18 18:53:27 +00:00
|
|
|
}
|
|
|
|
|
2016-03-19 03:09:54 +00:00
|
|
|
// Container is requesting an isolation mode. Honour it.
|
2016-11-01 20:02:46 +00:00
|
|
|
return hostConfig.Isolation.IsHyperV()
|
2016-03-19 03:09:54 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// conditionalMountOnStart is a platform specific helper function during the
|
|
|
|
// container start to call mount.
|
|
|
|
func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
|
2021-03-18 20:01:46 +00:00
|
|
|
if daemon.runAsHyperVContainer(container.HostConfig) {
|
|
|
|
// We do not mount if a Hyper-V container as it needs to be mounted inside the
|
|
|
|
// utility VM, not the host.
|
2017-06-17 03:28:18 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-03-18 20:01:46 +00:00
|
|
|
return daemon.Mount(container)
|
2015-11-03 01:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// conditionalUnmountOnCleanup is a platform specific helper function called
|
|
|
|
// during the cleanup of a container to unmount.
|
2016-03-18 18:53:27 +00:00
|
|
|
func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container) error {
|
2021-07-27 10:12:11 +00:00
|
|
|
if daemon.runAsHyperVContainer(container.HostConfig) {
|
|
|
|
// We do not unmount if a Hyper-V container
|
2017-06-17 03:28:18 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-07-27 10:12:11 +00:00
|
|
|
return daemon.Unmount(container)
|
2015-11-18 22:20:54 +00:00
|
|
|
}
|
|
|
|
|
2021-07-27 10:12:11 +00:00
|
|
|
func driverOptions(_ *config.Config) nwconfig.Option {
|
|
|
|
return nil
|
2016-02-18 01:08:11 +00:00
|
|
|
}
|
2016-03-18 18:53:27 +00:00
|
|
|
|
|
|
|
func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
|
2016-09-07 23:08:51 +00:00
|
|
|
if !c.IsRunning() {
|
2017-07-19 14:20:13 +00:00
|
|
|
return nil, errNotRunning(c.ID)
|
2016-09-07 23:08:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Obtain the stats from HCS via libcontainerd
|
2017-09-22 13:52:41 +00:00
|
|
|
stats, err := daemon.containerd.Stats(context.Background(), c.ID)
|
2016-09-07 23:08:51 +00:00
|
|
|
if err != nil {
|
2017-07-07 07:33:45 +00:00
|
|
|
if strings.Contains(err.Error(), "container not found") {
|
2017-07-19 14:20:13 +00:00
|
|
|
return nil, containerNotFound(c.ID)
|
2017-07-07 07:33:45 +00:00
|
|
|
}
|
2016-09-07 23:08:51 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start with an empty structure
|
|
|
|
s := &types.StatsJSON{}
|
2017-09-22 13:52:41 +00:00
|
|
|
s.Stats.Read = stats.Read
|
|
|
|
s.Stats.NumProcs = platform.NumProcs()
|
2016-09-07 23:08:51 +00:00
|
|
|
|
2017-09-22 13:52:41 +00:00
|
|
|
if stats.HCSStats != nil {
|
|
|
|
hcss := stats.HCSStats
|
|
|
|
// Populate the CPU/processor statistics
|
|
|
|
s.CPUStats = types.CPUStats{
|
|
|
|
CPUUsage: types.CPUUsage{
|
|
|
|
TotalUsage: hcss.Processor.TotalRuntime100ns,
|
|
|
|
UsageInKernelmode: hcss.Processor.RuntimeKernel100ns,
|
2020-03-18 08:34:47 +00:00
|
|
|
UsageInUsermode: hcss.Processor.RuntimeUser100ns,
|
2017-09-22 13:52:41 +00:00
|
|
|
},
|
2016-09-07 23:08:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-22 13:52:41 +00:00
|
|
|
// Populate the memory statistics
|
|
|
|
s.MemoryStats = types.MemoryStats{
|
|
|
|
Commit: hcss.Memory.UsageCommitBytes,
|
|
|
|
CommitPeak: hcss.Memory.UsageCommitPeakBytes,
|
|
|
|
PrivateWorkingSet: hcss.Memory.UsagePrivateWorkingSetBytes,
|
|
|
|
}
|
2016-09-07 23:08:51 +00:00
|
|
|
|
2017-09-22 13:52:41 +00:00
|
|
|
// Populate the storage statistics
|
|
|
|
s.StorageStats = types.StorageStats{
|
|
|
|
ReadCountNormalized: hcss.Storage.ReadCountNormalized,
|
|
|
|
ReadSizeBytes: hcss.Storage.ReadSizeBytes,
|
|
|
|
WriteCountNormalized: hcss.Storage.WriteCountNormalized,
|
|
|
|
WriteSizeBytes: hcss.Storage.WriteSizeBytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Populate the network statistics
|
|
|
|
s.Networks = make(map[string]types.NetworkStats)
|
|
|
|
for _, nstats := range hcss.Network {
|
|
|
|
s.Networks[nstats.EndpointId] = types.NetworkStats{
|
|
|
|
RxBytes: nstats.BytesReceived,
|
|
|
|
RxPackets: nstats.PacketsReceived,
|
|
|
|
RxDropped: nstats.DroppedPacketsIncoming,
|
|
|
|
TxBytes: nstats.BytesSent,
|
|
|
|
TxPackets: nstats.PacketsSent,
|
|
|
|
TxDropped: nstats.DroppedPacketsOutgoing,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-07 23:08:51 +00:00
|
|
|
return s, nil
|
2016-03-18 18:53:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// setDefaultIsolation determine the default isolation mode for the
|
|
|
|
// daemon to run in. This is only applicable on Windows
|
|
|
|
func (daemon *Daemon) setDefaultIsolation() error {
|
2018-10-09 18:58:26 +00:00
|
|
|
// On client SKUs, default to Hyper-V. @engine maintainers. This
|
2019-09-25 17:51:18 +00:00
|
|
|
// should not be removed. Ping Microsoft folks is there are PRs to
|
2018-10-09 18:58:26 +00:00
|
|
|
// to change this.
|
2022-03-15 23:41:30 +00:00
|
|
|
if operatingsystem.IsWindowsClient() {
|
2022-02-17 17:25:38 +00:00
|
|
|
daemon.defaultIsolation = containertypes.IsolationHyperV
|
|
|
|
} else {
|
|
|
|
daemon.defaultIsolation = containertypes.IsolationProcess
|
2016-04-15 00:12:02 +00:00
|
|
|
}
|
2016-03-18 18:53:27 +00:00
|
|
|
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() {
|
2022-02-17 17:25:38 +00:00
|
|
|
daemon.defaultIsolation = containertypes.IsolationHyperV
|
2016-03-18 18:53:27 +00:00
|
|
|
}
|
2016-04-15 00:12:02 +00:00
|
|
|
if containertypes.Isolation(val).IsProcess() {
|
2022-02-17 17:25:38 +00:00
|
|
|
daemon.defaultIsolation = containertypes.IsolationProcess
|
2016-04-15 00:12:02 +00:00
|
|
|
}
|
2016-03-18 18:53:27 +00:00
|
|
|
default:
|
|
|
|
return fmt.Errorf("Unrecognised exec-opt '%s'\n", key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
logrus.Infof("Windows default isolation mode: %s", daemon.defaultIsolation)
|
|
|
|
return nil
|
|
|
|
}
|
2016-03-21 16:56:51 +00:00
|
|
|
|
2017-01-23 11:23:07 +00:00
|
|
|
func setupDaemonProcess(config *config.Config) error {
|
2016-07-11 22:26:23 +00:00
|
|
|
return nil
|
|
|
|
}
|
2016-09-06 13:49:10 +00:00
|
|
|
|
2016-09-02 13:20:54 +00:00
|
|
|
func (daemon *Daemon) setupSeccompProfile() error {
|
|
|
|
return nil
|
|
|
|
}
|
2017-06-01 00:11:42 +00:00
|
|
|
|
2017-09-22 13:52:41 +00:00
|
|
|
func (daemon *Daemon) loadRuntimes() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-02-17 16:57:51 +00:00
|
|
|
func setupResolvConf(config *config.Config) {}
|
2019-11-05 07:10:19 +00:00
|
|
|
|
2022-06-03 15:35:23 +00:00
|
|
|
func getSysInfo(daemon *Daemon) *sysinfo.SysInfo {
|
|
|
|
return sysinfo.New()
|
2020-03-10 12:09:25 +00:00
|
|
|
}
|
2021-02-26 23:23:55 +00:00
|
|
|
|
|
|
|
func (daemon *Daemon) initLibcontainerd(ctx context.Context) error {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
rt := daemon.configStore.GetDefaultRuntimeName()
|
|
|
|
if rt == "" {
|
|
|
|
if daemon.configStore.ContainerdAddr == "" {
|
|
|
|
rt = windowsV1RuntimeName
|
|
|
|
} else {
|
|
|
|
rt = windowsV2RuntimeName
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch rt {
|
|
|
|
case windowsV1RuntimeName:
|
|
|
|
daemon.containerd, err = local.NewClient(
|
|
|
|
ctx,
|
|
|
|
daemon.containerdCli,
|
|
|
|
filepath.Join(daemon.configStore.ExecRoot, "containerd"),
|
|
|
|
daemon.configStore.ContainerdNamespace,
|
|
|
|
daemon,
|
|
|
|
)
|
|
|
|
case windowsV2RuntimeName:
|
|
|
|
if daemon.configStore.ContainerdAddr == "" {
|
|
|
|
return fmt.Errorf("cannot use the specified runtime %q without containerd", rt)
|
|
|
|
}
|
|
|
|
daemon.containerd, err = remote.NewClient(
|
|
|
|
ctx,
|
|
|
|
daemon.containerdCli,
|
|
|
|
filepath.Join(daemon.configStore.ExecRoot, "containerd"),
|
|
|
|
daemon.configStore.ContainerdNamespace,
|
|
|
|
daemon,
|
|
|
|
)
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unknown windows runtime %s", rt)
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|