daemon_windows.go 23 KB

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