-
Notifications
You must be signed in to change notification settings - Fork 208
/
Copy pathapi.go
168 lines (142 loc) · 5.75 KB
/
api.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright 2018 Intel Corporation. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package deviceplugin provides API for reporting available devices to kubelet.
package deviceplugin
import (
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/topology"
"k8s.io/klog/v2"
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
cdispec "tags.cncf.io/container-device-interface/specs-go"
)
// DeviceInfo contains information about device maintained by Device Plugin.
type DeviceInfo struct {
mounts []pluginapi.Mount
envs map[string]string
annotations map[string]string
topology *pluginapi.TopologyInfo
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4009-add-cdi-devices-to-device-plugin-api
cdiSpec *cdispec.Spec
state string
nodes []pluginapi.DeviceSpec
}
// UseDefaultMethodError allows the plugin to request running the default
// logic even while implementing an optional interface. This is currently
// supported only with the Allocator interface.
type UseDefaultMethodError struct{}
func (e *UseDefaultMethodError) Error() string {
return "use default method"
}
func init() {
klog.InitFlags(nil)
}
// NewDeviceInfo makes DeviceInfo struct and adds topology information to it.
func NewDeviceInfo(state string, nodes []pluginapi.DeviceSpec, mounts []pluginapi.Mount, envs, annotations map[string]string, cdiSpec *cdispec.Spec) DeviceInfo {
deviceInfo := DeviceInfo{
state: state,
nodes: nodes,
mounts: mounts,
envs: envs,
annotations: annotations,
cdiSpec: cdiSpec,
}
devPaths := []string{}
for _, node := range nodes {
devPaths = append(devPaths, node.HostPath)
}
topologyInfo, err := topology.GetTopologyInfo(devPaths)
if err == nil {
deviceInfo.topology = topologyInfo
} else {
klog.Warningf("GetTopologyInfo: %v", err)
}
return deviceInfo
}
// NewDeviceInfoWithTopologyHints makes DeviceInfo struct with topology information provided to it.
func NewDeviceInfoWithTopologyHints(state string, nodes []pluginapi.DeviceSpec, mounts []pluginapi.Mount, envs map[string]string,
annotations map[string]string, topology *pluginapi.TopologyInfo, cdiSpec *cdispec.Spec) DeviceInfo {
return DeviceInfo{
state: state,
nodes: nodes,
mounts: mounts,
envs: envs,
annotations: annotations,
topology: topology,
cdiSpec: cdiSpec,
}
}
// DeviceTree contains a tree-like structure of device type -> device ID -> device info.
type DeviceTree map[string]map[string]DeviceInfo
// NewDeviceTree creates an instance of DeviceTree.
func NewDeviceTree() DeviceTree {
return make(map[string]map[string]DeviceInfo)
}
// AddDevice adds device info to DeviceTree.
func (tree DeviceTree) AddDevice(devType, id string, info DeviceInfo) {
if _, present := tree[devType]; !present {
tree[devType] = make(map[string]DeviceInfo)
}
if info.cdiSpec != nil {
devLength := len(info.cdiSpec.Devices)
if devLength == 0 {
klog.Warning("No CDI devices defined in spec, removing spec")
info.cdiSpec = nil
} else if devLength > 1 {
klog.Warning("Including more than one CDI device per spec is not supported, using first")
info.cdiSpec.Devices = info.cdiSpec.Devices[:1]
}
}
tree[devType][id] = info
}
// DeviceTypeCount returns number of device of given type.
func (tree DeviceTree) DeviceTypeCount(devType string) int {
return len(tree[devType])
}
// Notifier receives updates from Scanner, detects changes and sends the
// detected changes to a channel given by the creator of a Notifier object.
type Notifier interface {
// Notify notifies manager with a device tree constructed by device
// plugin during scanning process.
Notify(DeviceTree)
}
// Scanner serves as an interface between Manager and a device plugin.
type Scanner interface {
// Scan scans the host for devices and sends all found devices to
// a Notifier instance. It's called only once for every device plugin by
// Manager in a goroutine and operates in an infinite loop.
Scan(Notifier) error
}
// Allocator is an optional interface implemented by device plugins.
type Allocator interface {
// Allocate allows the plugin to replace the server Allocate(). Plugin can return
// UseDefaultAllocateMethod if the default server allocation is anyhow preferred
// for the particular allocation request.
Allocate(*pluginapi.AllocateRequest) (*pluginapi.AllocateResponse, error)
}
// PostAllocator is an optional interface implemented by device plugins.
type PostAllocator interface {
// PostAllocate modifies responses returned by Allocate() by e.g.
// adding annotations consumed by CRI hooks to the responses.
PostAllocate(*pluginapi.AllocateResponse) error
}
// PreferredAllocator is an optional interface implemented by device plugins.
type PreferredAllocator interface {
// GetPreferredAllocation defines the list of devices preferred for allocating next.
GetPreferredAllocation(*pluginapi.PreferredAllocationRequest) (*pluginapi.PreferredAllocationResponse, error)
}
// ContainerPreStarter is an optional interface implemented by device plugins.
type ContainerPreStarter interface {
// PreStartContainer defines device initialization function before container is started.
// It might include operations like card reset.
PreStartContainer(*pluginapi.PreStartContainerRequest) error
}