1// +build windows
2
3/*
4Copyright 2015 The Kubernetes Authors.
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17*/
18
19// containerManagerImpl implements container manager on Windows.
20// Only GetNodeAllocatableReservation() and GetCapacity() are implemented now.
21
22package cm
23
24import (
25	"fmt"
26
27	"k8s.io/klog/v2"
28	"k8s.io/mount-utils"
29
30	v1 "k8s.io/api/core/v1"
31	"k8s.io/apimachinery/pkg/api/resource"
32	utilfeature "k8s.io/apiserver/pkg/util/feature"
33	"k8s.io/client-go/tools/record"
34	internalapi "k8s.io/cri-api/pkg/apis"
35	podresourcesapi "k8s.io/kubelet/pkg/apis/podresources/v1"
36	kubefeatures "k8s.io/kubernetes/pkg/features"
37	"k8s.io/kubernetes/pkg/kubelet/cadvisor"
38	"k8s.io/kubernetes/pkg/kubelet/cm/admission"
39	"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager"
40	"k8s.io/kubernetes/pkg/kubelet/cm/devicemanager"
41	"k8s.io/kubernetes/pkg/kubelet/cm/memorymanager"
42	"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
43	"k8s.io/kubernetes/pkg/kubelet/config"
44	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
45	"k8s.io/kubernetes/pkg/kubelet/lifecycle"
46	"k8s.io/kubernetes/pkg/kubelet/pluginmanager/cache"
47	"k8s.io/kubernetes/pkg/kubelet/status"
48	schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework"
49)
50
51type containerManagerImpl struct {
52	// Capacity of this node.
53	capacity v1.ResourceList
54	// Interface for cadvisor.
55	cadvisorInterface cadvisor.Interface
56	// Config of this node.
57	nodeConfig NodeConfig
58	// Interface for exporting and allocating devices reported by device plugins.
59	deviceManager devicemanager.Manager
60	// Interface for Topology resource co-ordination
61	topologyManager topologymanager.Manager
62}
63
64type noopWindowsResourceAllocator struct{}
65
66func (ra *noopWindowsResourceAllocator) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {
67	return admission.GetPodAdmitResult(nil)
68}
69
70func (cm *containerManagerImpl) Start(node *v1.Node,
71	activePods ActivePodsFunc,
72	sourcesReady config.SourcesReady,
73	podStatusProvider status.PodStatusProvider,
74	runtimeService internalapi.RuntimeService) error {
75	klog.V(2).InfoS("Starting Windows container manager")
76
77	if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.LocalStorageCapacityIsolation) {
78		rootfs, err := cm.cadvisorInterface.RootFsInfo()
79		if err != nil {
80			return fmt.Errorf("failed to get rootfs info: %v", err)
81		}
82		for rName, rCap := range cadvisor.EphemeralStorageCapacityFromFsInfo(rootfs) {
83			cm.capacity[rName] = rCap
84		}
85	}
86
87	// Starts device manager.
88	if err := cm.deviceManager.Start(devicemanager.ActivePodsFunc(activePods), sourcesReady); err != nil {
89		return err
90	}
91
92	return nil
93}
94
95// NewContainerManager creates windows container manager.
96func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.Interface, nodeConfig NodeConfig, failSwapOn bool, devicePluginEnabled bool, recorder record.EventRecorder) (ContainerManager, error) {
97	// It is safe to invoke `MachineInfo` on cAdvisor before logically initializing cAdvisor here because
98	// machine info is computed and cached once as part of cAdvisor object creation.
99	// But `RootFsInfo` and `ImagesFsInfo` are not available at this moment so they will be called later during manager starts
100	machineInfo, err := cadvisorInterface.MachineInfo()
101	if err != nil {
102		return nil, err
103	}
104	capacity := cadvisor.CapacityFromMachineInfo(machineInfo)
105
106	cm := &containerManagerImpl{
107		capacity:          capacity,
108		nodeConfig:        nodeConfig,
109		cadvisorInterface: cadvisorInterface,
110	}
111
112	cm.topologyManager = topologymanager.NewFakeManager()
113
114	klog.InfoS("Creating device plugin manager", "devicePluginEnabled", devicePluginEnabled)
115	if devicePluginEnabled {
116		cm.deviceManager, err = devicemanager.NewManagerImpl(nil, cm.topologyManager)
117		cm.topologyManager.AddHintProvider(cm.deviceManager)
118	} else {
119		cm.deviceManager, err = devicemanager.NewManagerStub()
120	}
121	if err != nil {
122		return nil, err
123	}
124
125	return cm, nil
126}
127
128func (cm *containerManagerImpl) SystemCgroupsLimit() v1.ResourceList {
129	return v1.ResourceList{}
130}
131
132func (cm *containerManagerImpl) GetNodeConfig() NodeConfig {
133	return NodeConfig{}
134}
135
136func (cm *containerManagerImpl) GetMountedSubsystems() *CgroupSubsystems {
137	return &CgroupSubsystems{}
138}
139
140func (cm *containerManagerImpl) GetQOSContainersInfo() QOSContainersInfo {
141	return QOSContainersInfo{}
142}
143
144func (cm *containerManagerImpl) UpdateQOSCgroups() error {
145	return nil
146}
147
148func (cm *containerManagerImpl) Status() Status {
149	return Status{}
150}
151
152func (cm *containerManagerImpl) GetNodeAllocatableReservation() v1.ResourceList {
153	evictionReservation := hardEvictionReservation(cm.nodeConfig.HardEvictionThresholds, cm.capacity)
154	result := make(v1.ResourceList)
155	for k := range cm.capacity {
156		value := resource.NewQuantity(0, resource.DecimalSI)
157		if cm.nodeConfig.SystemReserved != nil {
158			value.Add(cm.nodeConfig.SystemReserved[k])
159		}
160		if cm.nodeConfig.KubeReserved != nil {
161			value.Add(cm.nodeConfig.KubeReserved[k])
162		}
163		if evictionReservation != nil {
164			value.Add(evictionReservation[k])
165		}
166		if !value.IsZero() {
167			result[k] = *value
168		}
169	}
170	return result
171}
172
173func (cm *containerManagerImpl) GetCapacity() v1.ResourceList {
174	return cm.capacity
175}
176
177func (cm *containerManagerImpl) GetPluginRegistrationHandler() cache.PluginHandler {
178	return cm.deviceManager.GetWatcherHandler()
179}
180
181func (cm *containerManagerImpl) GetDevicePluginResourceCapacity() (v1.ResourceList, v1.ResourceList, []string) {
182	return cm.deviceManager.GetCapacity()
183}
184
185func (cm *containerManagerImpl) NewPodContainerManager() PodContainerManager {
186	return &podContainerManagerStub{}
187}
188
189func (cm *containerManagerImpl) GetResources(pod *v1.Pod, container *v1.Container) (*kubecontainer.RunContainerOptions, error) {
190	opts := &kubecontainer.RunContainerOptions{}
191	// Allocate should already be called during predicateAdmitHandler.Admit(),
192	// just try to fetch device runtime information from cached state here
193	devOpts, err := cm.deviceManager.GetDeviceRunContainerOptions(pod, container)
194	if err != nil {
195		return nil, err
196	} else if devOpts == nil {
197		return opts, nil
198	}
199	opts.Devices = append(opts.Devices, devOpts.Devices...)
200	opts.Mounts = append(opts.Mounts, devOpts.Mounts...)
201	opts.Envs = append(opts.Envs, devOpts.Envs...)
202	opts.Annotations = append(opts.Annotations, devOpts.Annotations...)
203	return opts, nil
204}
205
206func (cm *containerManagerImpl) UpdatePluginResources(node *schedulerframework.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error {
207	return cm.deviceManager.UpdatePluginResources(node, attrs)
208}
209
210func (cm *containerManagerImpl) InternalContainerLifecycle() InternalContainerLifecycle {
211	return &internalContainerLifecycleImpl{cpumanager.NewFakeManager(), memorymanager.NewFakeManager(), topologymanager.NewFakeManager()}
212}
213
214func (cm *containerManagerImpl) GetPodCgroupRoot() string {
215	return ""
216}
217
218func (cm *containerManagerImpl) GetDevices(podUID, containerName string) []*podresourcesapi.ContainerDevices {
219	return containerDevicesFromResourceDeviceInstances(cm.deviceManager.GetDevices(podUID, containerName))
220}
221
222func (cm *containerManagerImpl) GetAllocatableDevices() []*podresourcesapi.ContainerDevices {
223	return nil
224}
225
226func (cm *containerManagerImpl) ShouldResetExtendedResourceCapacity() bool {
227	return cm.deviceManager.ShouldResetExtendedResourceCapacity()
228}
229
230func (cm *containerManagerImpl) GetAllocateResourcesPodAdmitHandler() lifecycle.PodAdmitHandler {
231	return &noopWindowsResourceAllocator{}
232}
233
234func (cm *containerManagerImpl) UpdateAllocatedDevices() {
235	return
236}
237
238func (cm *containerManagerImpl) GetCPUs(_, _ string) []int64 {
239	return nil
240}
241
242func (cm *containerManagerImpl) GetAllocatableCPUs() []int64 {
243	return nil
244}
245
246func (cm *containerManagerImpl) GetMemory(_, _ string) []*podresourcesapi.ContainerMemory {
247	return nil
248}
249
250func (cm *containerManagerImpl) GetAllocatableMemory() []*podresourcesapi.ContainerMemory {
251	return nil
252}
253
254func (cm *containerManagerImpl) GetNodeAllocatableAbsolute() v1.ResourceList {
255	return nil
256}
257