gpustack-runtime 0.1.40.post1__py3-none-any.whl → 0.1.41.post1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gpustack_runtime/__init__.py +1 -1
- gpustack_runtime/__main__.py +5 -3
- gpustack_runtime/_version.py +2 -2
- gpustack_runtime/_version_appendix.py +1 -1
- gpustack_runtime/cmds/__init__.py +5 -3
- gpustack_runtime/cmds/__types__.py +1 -1
- gpustack_runtime/cmds/deployer.py +140 -18
- gpustack_runtime/cmds/detector.py +1 -1
- gpustack_runtime/cmds/images.py +1 -1
- gpustack_runtime/deployer/__init__.py +28 -2
- gpustack_runtime/deployer/__patches__.py +1 -1
- gpustack_runtime/deployer/__types__.py +2 -1
- gpustack_runtime/deployer/__utils__.py +2 -2
- gpustack_runtime/deployer/cdi/__init__.py +86 -5
- gpustack_runtime/deployer/cdi/__types__.py +92 -29
- gpustack_runtime/deployer/cdi/__utils__.py +180 -0
- gpustack_runtime/deployer/cdi/amd.py +146 -0
- gpustack_runtime/deployer/cdi/ascend.py +164 -0
- gpustack_runtime/deployer/cdi/hygon.py +147 -0
- gpustack_runtime/deployer/cdi/iluvatar.py +136 -0
- gpustack_runtime/deployer/cdi/metax.py +148 -0
- gpustack_runtime/deployer/cdi/thead.py +57 -23
- gpustack_runtime/deployer/docker.py +9 -8
- gpustack_runtime/deployer/k8s/deviceplugin/__init__.py +325 -0
- gpustack_runtime/deployer/k8s/deviceplugin/__types__.py +131 -0
- gpustack_runtime/deployer/k8s/deviceplugin/plugin.py +590 -0
- gpustack_runtime/deployer/k8s/types/kubelet/deviceplugin/v1beta1/__init__.py +3 -0
- gpustack_runtime/deployer/k8s/types/kubelet/deviceplugin/v1beta1/api.proto +212 -0
- gpustack_runtime/deployer/k8s/types/kubelet/deviceplugin/v1beta1/api_pb2.py +86 -0
- gpustack_runtime/deployer/k8s/types/kubelet/deviceplugin/v1beta1/api_pb2.pyi +168 -0
- gpustack_runtime/deployer/k8s/types/kubelet/deviceplugin/v1beta1/api_pb2_grpc.py +358 -0
- gpustack_runtime/deployer/k8s/types/kubelet/deviceplugin/v1beta1/constants.py +34 -0
- gpustack_runtime/deployer/kuberentes.py +50 -4
- gpustack_runtime/deployer/podman.py +9 -8
- gpustack_runtime/detector/__init__.py +42 -5
- gpustack_runtime/detector/__types__.py +8 -24
- gpustack_runtime/detector/__utils__.py +46 -39
- gpustack_runtime/detector/amd.py +55 -66
- gpustack_runtime/detector/ascend.py +29 -41
- gpustack_runtime/detector/cambricon.py +3 -3
- gpustack_runtime/detector/hygon.py +21 -49
- gpustack_runtime/detector/iluvatar.py +44 -60
- gpustack_runtime/detector/metax.py +54 -37
- gpustack_runtime/detector/mthreads.py +74 -36
- gpustack_runtime/detector/nvidia.py +130 -93
- gpustack_runtime/detector/pyacl/__init__.py +1 -1
- gpustack_runtime/detector/pyamdgpu/__init__.py +1 -1
- gpustack_runtime/detector/pyamdsmi/__init__.py +1 -1
- gpustack_runtime/detector/pycuda/__init__.py +1 -1
- gpustack_runtime/detector/pydcmi/__init__.py +1 -1
- gpustack_runtime/detector/pyhsa/__init__.py +1 -1
- gpustack_runtime/detector/pymxsml/__init__.py +1553 -1
- gpustack_runtime/detector/pyrocmcore/__init__.py +1 -1
- gpustack_runtime/detector/pyrocmsmi/__init__.py +1 -1
- gpustack_runtime/detector/thead.py +41 -60
- gpustack_runtime/envs.py +106 -12
- gpustack_runtime/logging.py +6 -2
- {gpustack_runtime-0.1.40.post1.dist-info → gpustack_runtime-0.1.41.post1.dist-info}/METADATA +6 -1
- gpustack_runtime-0.1.41.post1.dist-info/RECORD +67 -0
- gpustack_runtime/detector/pymxsml/mxsml.py +0 -1580
- gpustack_runtime/detector/pymxsml/mxsml_extension.py +0 -816
- gpustack_runtime/detector/pymxsml/mxsml_mcm.py +0 -476
- gpustack_runtime-0.1.40.post1.dist-info/RECORD +0 -55
- {gpustack_runtime-0.1.40.post1.dist-info → gpustack_runtime-0.1.41.post1.dist-info}/WHEEL +0 -0
- {gpustack_runtime-0.1.40.post1.dist-info → gpustack_runtime-0.1.41.post1.dist-info}/entry_points.txt +0 -0
- {gpustack_runtime-0.1.40.post1.dist-info → gpustack_runtime-0.1.41.post1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
|
|
5
|
+
from gpustack_runtime.deployer.k8s.types.kubelet.deviceplugin.v1beta1 import api_pb2 as gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RegistrationStub(object):
|
|
9
|
+
"""Registration is the service advertised by the Kubelet
|
|
10
|
+
Only when Kubelet answers with a success code to a Register Request
|
|
11
|
+
may Device Plugins start their service
|
|
12
|
+
Registration may fail when device plugin version is not supported by
|
|
13
|
+
Kubelet or the registered resourceName is already taken by another
|
|
14
|
+
active device plugin. Device plugin is expected to terminate upon registration failure
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, channel):
|
|
18
|
+
"""Constructor.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
channel: A grpc.Channel.
|
|
22
|
+
"""
|
|
23
|
+
self.Register = channel.unary_unary(
|
|
24
|
+
'/v1beta1.Registration/Register',
|
|
25
|
+
request_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.RegisterRequest.SerializeToString,
|
|
26
|
+
response_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.FromString,
|
|
27
|
+
_registered_method=True)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RegistrationServicer(object):
|
|
31
|
+
"""Registration is the service advertised by the Kubelet
|
|
32
|
+
Only when Kubelet answers with a success code to a Register Request
|
|
33
|
+
may Device Plugins start their service
|
|
34
|
+
Registration may fail when device plugin version is not supported by
|
|
35
|
+
Kubelet or the registered resourceName is already taken by another
|
|
36
|
+
active device plugin. Device plugin is expected to terminate upon registration failure
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def Register(self, request, context):
|
|
40
|
+
"""Missing associated documentation comment in .proto file."""
|
|
41
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
42
|
+
context.set_details('Method not implemented!')
|
|
43
|
+
raise NotImplementedError('Method not implemented!')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def add_RegistrationServicer_to_server(servicer, server):
|
|
47
|
+
rpc_method_handlers = {
|
|
48
|
+
'Register': grpc.unary_unary_rpc_method_handler(
|
|
49
|
+
servicer.Register,
|
|
50
|
+
request_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.RegisterRequest.FromString,
|
|
51
|
+
response_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.SerializeToString,
|
|
52
|
+
),
|
|
53
|
+
}
|
|
54
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
|
55
|
+
'v1beta1.Registration', rpc_method_handlers)
|
|
56
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
|
57
|
+
server.add_registered_method_handlers('v1beta1.Registration', rpc_method_handlers)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# This class is part of an EXPERIMENTAL API.
|
|
61
|
+
class Registration(object):
|
|
62
|
+
"""Registration is the service advertised by the Kubelet
|
|
63
|
+
Only when Kubelet answers with a success code to a Register Request
|
|
64
|
+
may Device Plugins start their service
|
|
65
|
+
Registration may fail when device plugin version is not supported by
|
|
66
|
+
Kubelet or the registered resourceName is already taken by another
|
|
67
|
+
active device plugin. Device plugin is expected to terminate upon registration failure
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def Register(request,
|
|
72
|
+
target,
|
|
73
|
+
options=(),
|
|
74
|
+
channel_credentials=None,
|
|
75
|
+
call_credentials=None,
|
|
76
|
+
insecure=False,
|
|
77
|
+
compression=None,
|
|
78
|
+
wait_for_ready=None,
|
|
79
|
+
timeout=None,
|
|
80
|
+
metadata=None):
|
|
81
|
+
return grpc.experimental.unary_unary(
|
|
82
|
+
request,
|
|
83
|
+
target,
|
|
84
|
+
'/v1beta1.Registration/Register',
|
|
85
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.RegisterRequest.SerializeToString,
|
|
86
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.FromString,
|
|
87
|
+
options,
|
|
88
|
+
channel_credentials,
|
|
89
|
+
insecure,
|
|
90
|
+
call_credentials,
|
|
91
|
+
compression,
|
|
92
|
+
wait_for_ready,
|
|
93
|
+
timeout,
|
|
94
|
+
metadata,
|
|
95
|
+
_registered_method=True)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class DevicePluginStub(object):
|
|
99
|
+
"""DevicePlugin is the service advertised by Device Plugins
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, channel):
|
|
103
|
+
"""Constructor.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
channel: A grpc.Channel.
|
|
107
|
+
"""
|
|
108
|
+
self.GetDevicePluginOptions = channel.unary_unary(
|
|
109
|
+
'/v1beta1.DevicePlugin/GetDevicePluginOptions',
|
|
110
|
+
request_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.SerializeToString,
|
|
111
|
+
response_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.DevicePluginOptions.FromString,
|
|
112
|
+
_registered_method=True)
|
|
113
|
+
self.ListAndWatch = channel.unary_stream(
|
|
114
|
+
'/v1beta1.DevicePlugin/ListAndWatch',
|
|
115
|
+
request_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.SerializeToString,
|
|
116
|
+
response_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.ListAndWatchResponse.FromString,
|
|
117
|
+
_registered_method=True)
|
|
118
|
+
self.GetPreferredAllocation = channel.unary_unary(
|
|
119
|
+
'/v1beta1.DevicePlugin/GetPreferredAllocation',
|
|
120
|
+
request_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreferredAllocationRequest.SerializeToString,
|
|
121
|
+
response_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreferredAllocationResponse.FromString,
|
|
122
|
+
_registered_method=True)
|
|
123
|
+
self.Allocate = channel.unary_unary(
|
|
124
|
+
'/v1beta1.DevicePlugin/Allocate',
|
|
125
|
+
request_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.AllocateRequest.SerializeToString,
|
|
126
|
+
response_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.AllocateResponse.FromString,
|
|
127
|
+
_registered_method=True)
|
|
128
|
+
self.PreStartContainer = channel.unary_unary(
|
|
129
|
+
'/v1beta1.DevicePlugin/PreStartContainer',
|
|
130
|
+
request_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreStartContainerRequest.SerializeToString,
|
|
131
|
+
response_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreStartContainerResponse.FromString,
|
|
132
|
+
_registered_method=True)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class DevicePluginServicer(object):
|
|
136
|
+
"""DevicePlugin is the service advertised by Device Plugins
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def GetDevicePluginOptions(self, request, context):
|
|
140
|
+
"""GetDevicePluginOptions returns options to be communicated with Device
|
|
141
|
+
Manager
|
|
142
|
+
"""
|
|
143
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
144
|
+
context.set_details('Method not implemented!')
|
|
145
|
+
raise NotImplementedError('Method not implemented!')
|
|
146
|
+
|
|
147
|
+
def ListAndWatch(self, request, context):
|
|
148
|
+
"""ListAndWatch returns a stream of List of Devices
|
|
149
|
+
Whenever a Device state change or a Device disappears, ListAndWatch
|
|
150
|
+
returns the new list
|
|
151
|
+
"""
|
|
152
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
153
|
+
context.set_details('Method not implemented!')
|
|
154
|
+
raise NotImplementedError('Method not implemented!')
|
|
155
|
+
|
|
156
|
+
def GetPreferredAllocation(self, request, context):
|
|
157
|
+
"""GetPreferredAllocation returns a preferred set of devices to allocate
|
|
158
|
+
from a list of available ones. The resulting preferred allocation is not
|
|
159
|
+
guaranteed to be the allocation ultimately performed by the
|
|
160
|
+
devicemanager. It is only designed to help the devicemanager make a more
|
|
161
|
+
informed allocation decision when possible.
|
|
162
|
+
"""
|
|
163
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
164
|
+
context.set_details('Method not implemented!')
|
|
165
|
+
raise NotImplementedError('Method not implemented!')
|
|
166
|
+
|
|
167
|
+
def Allocate(self, request, context):
|
|
168
|
+
"""Allocate is called during container creation so that the Device
|
|
169
|
+
Plugin can run device specific operations and instruct Kubelet
|
|
170
|
+
of the steps to make the Device available in the container
|
|
171
|
+
"""
|
|
172
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
173
|
+
context.set_details('Method not implemented!')
|
|
174
|
+
raise NotImplementedError('Method not implemented!')
|
|
175
|
+
|
|
176
|
+
def PreStartContainer(self, request, context):
|
|
177
|
+
"""PreStartContainer is called, if indicated by Device Plugin during registeration phase,
|
|
178
|
+
before each container start. Device plugin can run device specific operations
|
|
179
|
+
such as resetting the device before making devices available to the container
|
|
180
|
+
"""
|
|
181
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
182
|
+
context.set_details('Method not implemented!')
|
|
183
|
+
raise NotImplementedError('Method not implemented!')
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def add_DevicePluginServicer_to_server(servicer, server):
|
|
187
|
+
rpc_method_handlers = {
|
|
188
|
+
'GetDevicePluginOptions': grpc.unary_unary_rpc_method_handler(
|
|
189
|
+
servicer.GetDevicePluginOptions,
|
|
190
|
+
request_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.FromString,
|
|
191
|
+
response_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.DevicePluginOptions.SerializeToString,
|
|
192
|
+
),
|
|
193
|
+
'ListAndWatch': grpc.unary_stream_rpc_method_handler(
|
|
194
|
+
servicer.ListAndWatch,
|
|
195
|
+
request_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.FromString,
|
|
196
|
+
response_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.ListAndWatchResponse.SerializeToString,
|
|
197
|
+
),
|
|
198
|
+
'GetPreferredAllocation': grpc.unary_unary_rpc_method_handler(
|
|
199
|
+
servicer.GetPreferredAllocation,
|
|
200
|
+
request_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreferredAllocationRequest.FromString,
|
|
201
|
+
response_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreferredAllocationResponse.SerializeToString,
|
|
202
|
+
),
|
|
203
|
+
'Allocate': grpc.unary_unary_rpc_method_handler(
|
|
204
|
+
servicer.Allocate,
|
|
205
|
+
request_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.AllocateRequest.FromString,
|
|
206
|
+
response_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.AllocateResponse.SerializeToString,
|
|
207
|
+
),
|
|
208
|
+
'PreStartContainer': grpc.unary_unary_rpc_method_handler(
|
|
209
|
+
servicer.PreStartContainer,
|
|
210
|
+
request_deserializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreStartContainerRequest.FromString,
|
|
211
|
+
response_serializer=gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreStartContainerResponse.SerializeToString,
|
|
212
|
+
),
|
|
213
|
+
}
|
|
214
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
|
215
|
+
'v1beta1.DevicePlugin', rpc_method_handlers)
|
|
216
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
|
217
|
+
server.add_registered_method_handlers('v1beta1.DevicePlugin', rpc_method_handlers)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
# This class is part of an EXPERIMENTAL API.
|
|
221
|
+
class DevicePlugin(object):
|
|
222
|
+
"""DevicePlugin is the service advertised by Device Plugins
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
@staticmethod
|
|
226
|
+
def GetDevicePluginOptions(request,
|
|
227
|
+
target,
|
|
228
|
+
options=(),
|
|
229
|
+
channel_credentials=None,
|
|
230
|
+
call_credentials=None,
|
|
231
|
+
insecure=False,
|
|
232
|
+
compression=None,
|
|
233
|
+
wait_for_ready=None,
|
|
234
|
+
timeout=None,
|
|
235
|
+
metadata=None):
|
|
236
|
+
return grpc.experimental.unary_unary(
|
|
237
|
+
request,
|
|
238
|
+
target,
|
|
239
|
+
'/v1beta1.DevicePlugin/GetDevicePluginOptions',
|
|
240
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.SerializeToString,
|
|
241
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.DevicePluginOptions.FromString,
|
|
242
|
+
options,
|
|
243
|
+
channel_credentials,
|
|
244
|
+
insecure,
|
|
245
|
+
call_credentials,
|
|
246
|
+
compression,
|
|
247
|
+
wait_for_ready,
|
|
248
|
+
timeout,
|
|
249
|
+
metadata,
|
|
250
|
+
_registered_method=True)
|
|
251
|
+
|
|
252
|
+
@staticmethod
|
|
253
|
+
def ListAndWatch(request,
|
|
254
|
+
target,
|
|
255
|
+
options=(),
|
|
256
|
+
channel_credentials=None,
|
|
257
|
+
call_credentials=None,
|
|
258
|
+
insecure=False,
|
|
259
|
+
compression=None,
|
|
260
|
+
wait_for_ready=None,
|
|
261
|
+
timeout=None,
|
|
262
|
+
metadata=None):
|
|
263
|
+
return grpc.experimental.unary_stream(
|
|
264
|
+
request,
|
|
265
|
+
target,
|
|
266
|
+
'/v1beta1.DevicePlugin/ListAndWatch',
|
|
267
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.Empty.SerializeToString,
|
|
268
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.ListAndWatchResponse.FromString,
|
|
269
|
+
options,
|
|
270
|
+
channel_credentials,
|
|
271
|
+
insecure,
|
|
272
|
+
call_credentials,
|
|
273
|
+
compression,
|
|
274
|
+
wait_for_ready,
|
|
275
|
+
timeout,
|
|
276
|
+
metadata,
|
|
277
|
+
_registered_method=True)
|
|
278
|
+
|
|
279
|
+
@staticmethod
|
|
280
|
+
def GetPreferredAllocation(request,
|
|
281
|
+
target,
|
|
282
|
+
options=(),
|
|
283
|
+
channel_credentials=None,
|
|
284
|
+
call_credentials=None,
|
|
285
|
+
insecure=False,
|
|
286
|
+
compression=None,
|
|
287
|
+
wait_for_ready=None,
|
|
288
|
+
timeout=None,
|
|
289
|
+
metadata=None):
|
|
290
|
+
return grpc.experimental.unary_unary(
|
|
291
|
+
request,
|
|
292
|
+
target,
|
|
293
|
+
'/v1beta1.DevicePlugin/GetPreferredAllocation',
|
|
294
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreferredAllocationRequest.SerializeToString,
|
|
295
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreferredAllocationResponse.FromString,
|
|
296
|
+
options,
|
|
297
|
+
channel_credentials,
|
|
298
|
+
insecure,
|
|
299
|
+
call_credentials,
|
|
300
|
+
compression,
|
|
301
|
+
wait_for_ready,
|
|
302
|
+
timeout,
|
|
303
|
+
metadata,
|
|
304
|
+
_registered_method=True)
|
|
305
|
+
|
|
306
|
+
@staticmethod
|
|
307
|
+
def Allocate(request,
|
|
308
|
+
target,
|
|
309
|
+
options=(),
|
|
310
|
+
channel_credentials=None,
|
|
311
|
+
call_credentials=None,
|
|
312
|
+
insecure=False,
|
|
313
|
+
compression=None,
|
|
314
|
+
wait_for_ready=None,
|
|
315
|
+
timeout=None,
|
|
316
|
+
metadata=None):
|
|
317
|
+
return grpc.experimental.unary_unary(
|
|
318
|
+
request,
|
|
319
|
+
target,
|
|
320
|
+
'/v1beta1.DevicePlugin/Allocate',
|
|
321
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.AllocateRequest.SerializeToString,
|
|
322
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.AllocateResponse.FromString,
|
|
323
|
+
options,
|
|
324
|
+
channel_credentials,
|
|
325
|
+
insecure,
|
|
326
|
+
call_credentials,
|
|
327
|
+
compression,
|
|
328
|
+
wait_for_ready,
|
|
329
|
+
timeout,
|
|
330
|
+
metadata,
|
|
331
|
+
_registered_method=True)
|
|
332
|
+
|
|
333
|
+
@staticmethod
|
|
334
|
+
def PreStartContainer(request,
|
|
335
|
+
target,
|
|
336
|
+
options=(),
|
|
337
|
+
channel_credentials=None,
|
|
338
|
+
call_credentials=None,
|
|
339
|
+
insecure=False,
|
|
340
|
+
compression=None,
|
|
341
|
+
wait_for_ready=None,
|
|
342
|
+
timeout=None,
|
|
343
|
+
metadata=None):
|
|
344
|
+
return grpc.experimental.unary_unary(
|
|
345
|
+
request,
|
|
346
|
+
target,
|
|
347
|
+
'/v1beta1.DevicePlugin/PreStartContainer',
|
|
348
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreStartContainerRequest.SerializeToString,
|
|
349
|
+
gpustack__runtime_dot_deployer_dot_k8s_dot_types_dot_kubelet_dot_deviceplugin_dot_v1beta1_dot_api__pb2.PreStartContainerResponse.FromString,
|
|
350
|
+
options,
|
|
351
|
+
channel_credentials,
|
|
352
|
+
insecure,
|
|
353
|
+
call_credentials,
|
|
354
|
+
compression,
|
|
355
|
+
wait_for_ready,
|
|
356
|
+
timeout,
|
|
357
|
+
metadata,
|
|
358
|
+
_registered_method=True)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
Healthy = "Healthy"
|
|
4
|
+
"""
|
|
5
|
+
Healthy means that the device is healthy
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
Unhealthy = "Unhealthy"
|
|
9
|
+
"""
|
|
10
|
+
Unhealthy means that the device is unhealthy
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
Version = "v1beta1"
|
|
14
|
+
"""
|
|
15
|
+
Version means current version of the API supported by kubelet
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
DevicePluginPath = Path("/var/lib/kubelet/device-plugins")
|
|
19
|
+
"""
|
|
20
|
+
DevicePluginPath is the folder the Device Plugin is expecting sockets to be on
|
|
21
|
+
Only privileged pods have access to this path
|
|
22
|
+
Note: Placeholder until we find a "standard path"
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
KubeletSocket = DevicePluginPath / "kubelet.sock"
|
|
26
|
+
"""
|
|
27
|
+
KubeletSocket is the path of the Kubelet registry socket
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
KubeletPreStartContainerRPCTimeoutInSecs = 30
|
|
31
|
+
"""
|
|
32
|
+
KubeletPreStartContainerRPCTimeoutInSecs is the timeout duration in secs for PreStartContainer RPC
|
|
33
|
+
Timeout duration in secs for PreStartContainer RPC
|
|
34
|
+
"""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
1
|
+
from __future__ import annotations as __future_annotations__
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
4
|
import json
|
|
@@ -9,11 +9,12 @@ from dataclasses import dataclass, field
|
|
|
9
9
|
from enum import Enum
|
|
10
10
|
from functools import lru_cache, reduce
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import TYPE_CHECKING
|
|
12
|
+
from typing import TYPE_CHECKING, Literal
|
|
13
13
|
|
|
14
14
|
import kubernetes
|
|
15
15
|
import kubernetes.stream.ws_client
|
|
16
16
|
import urllib3.connection
|
|
17
|
+
from cachetools.func import ttl_cache
|
|
17
18
|
from dataclasses_json import dataclass_json
|
|
18
19
|
|
|
19
20
|
from .. import envs
|
|
@@ -42,6 +43,7 @@ from .__utils__ import (
|
|
|
42
43
|
sensitive_env_var,
|
|
43
44
|
validate_rfc1123_domain_name,
|
|
44
45
|
)
|
|
46
|
+
from .k8s.deviceplugin import cdi_kind_to_kdp_resource, is_kubelet_socket_accessible
|
|
45
47
|
|
|
46
48
|
if TYPE_CHECKING:
|
|
47
49
|
from collections.abc import Callable, Generator
|
|
@@ -302,7 +304,7 @@ class KubernetesDeployer(EndoscopicDeployer):
|
|
|
302
304
|
"""
|
|
303
305
|
|
|
304
306
|
@staticmethod
|
|
305
|
-
@
|
|
307
|
+
@ttl_cache(maxsize=1, ttl=60)
|
|
306
308
|
def is_supported() -> bool:
|
|
307
309
|
"""
|
|
308
310
|
Check if the deployer is supported in the current environment.
|
|
@@ -379,6 +381,22 @@ class KubernetesDeployer(EndoscopicDeployer):
|
|
|
379
381
|
|
|
380
382
|
return wrapper
|
|
381
383
|
|
|
384
|
+
@staticmethod
|
|
385
|
+
@lru_cache
|
|
386
|
+
def _get_resource_injection_policy() -> Literal["env", "kdp"]:
|
|
387
|
+
"""
|
|
388
|
+
Get the resource injection policy (in lowercase) for the deployer.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
The resource injection policy.
|
|
392
|
+
|
|
393
|
+
"""
|
|
394
|
+
policy = envs.GPUSTACK_RUNTIME_KUBERNETES_RESOURCE_INJECTION_POLICY.lower()
|
|
395
|
+
if policy != "auto":
|
|
396
|
+
return policy
|
|
397
|
+
|
|
398
|
+
return "kdp" if is_kubelet_socket_accessible() else "env"
|
|
399
|
+
|
|
382
400
|
def _create_ephemeral_configmaps(
|
|
383
401
|
self,
|
|
384
402
|
workload: KubernetesWorkloadPlan,
|
|
@@ -990,10 +1008,12 @@ class KubernetesDeployer(EndoscopicDeployer):
|
|
|
990
1008
|
|
|
991
1009
|
# Parameterize resources
|
|
992
1010
|
if c.resources:
|
|
1011
|
+
kdp = self._get_resource_injection_policy() == "kdp"
|
|
1012
|
+
|
|
993
1013
|
resources: dict[str, str] = {}
|
|
994
1014
|
r_k_runtime_env = workload.resource_key_runtime_env_mapping or {}
|
|
995
1015
|
r_k_backend_env = workload.resource_key_backend_env_mapping or {}
|
|
996
|
-
_, vd_env,
|
|
1016
|
+
_, vd_env, vd_cdis, vd_values = self.get_visible_devices_materials()
|
|
997
1017
|
for r_k, r_v in c.resources.items():
|
|
998
1018
|
if r_k in ("cpu", "memory"):
|
|
999
1019
|
resources[r_k] = str(r_v)
|
|
@@ -1032,6 +1052,15 @@ class KubernetesDeployer(EndoscopicDeployer):
|
|
|
1032
1052
|
# so that the container backend (e.g., NVIDIA Container Toolkit) can handle it,
|
|
1033
1053
|
# and mount corresponding libs if needed.
|
|
1034
1054
|
for re in runtime_env:
|
|
1055
|
+
# Request device via KDP.
|
|
1056
|
+
if kdp:
|
|
1057
|
+
for v in vd_values.get(re) or []:
|
|
1058
|
+
kdp_resource = cdi_kind_to_kdp_resource(
|
|
1059
|
+
cdi_kind=vd_cdis[re],
|
|
1060
|
+
device_index=v,
|
|
1061
|
+
)
|
|
1062
|
+
resources[kdp_resource] = "1"
|
|
1063
|
+
continue
|
|
1035
1064
|
# Request device via visible devices env.
|
|
1036
1065
|
rv = ",".join(vd_values.get(re) or ["all"])
|
|
1037
1066
|
container.env.append(
|
|
@@ -1046,6 +1075,23 @@ class KubernetesDeployer(EndoscopicDeployer):
|
|
|
1046
1075
|
# so that the container backend (e.g., NVIDIA Container Toolkit) can handle it,
|
|
1047
1076
|
# and mount corresponding libs if needed.
|
|
1048
1077
|
for re in runtime_env:
|
|
1078
|
+
# Request device via KDP.
|
|
1079
|
+
if kdp:
|
|
1080
|
+
if not privileged:
|
|
1081
|
+
for v in str(r_v).split(","):
|
|
1082
|
+
kdp_resource = cdi_kind_to_kdp_resource(
|
|
1083
|
+
cdi_kind=vd_cdis[re],
|
|
1084
|
+
device_index=int(v.strip()),
|
|
1085
|
+
)
|
|
1086
|
+
resources[kdp_resource] = "1"
|
|
1087
|
+
else:
|
|
1088
|
+
for v in vd_values.get(re) or []:
|
|
1089
|
+
kdp_resource = cdi_kind_to_kdp_resource(
|
|
1090
|
+
cdi_kind=vd_cdis[re],
|
|
1091
|
+
device_index=v,
|
|
1092
|
+
)
|
|
1093
|
+
resources[kdp_resource] = "1"
|
|
1094
|
+
continue
|
|
1049
1095
|
# Request device via visible devices env.
|
|
1050
1096
|
if not privileged:
|
|
1051
1097
|
rv = str(r_v)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
1
|
+
from __future__ import annotations as __future_annotations__
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
4
|
import io
|
|
@@ -10,7 +10,7 @@ import socket
|
|
|
10
10
|
import sys
|
|
11
11
|
import tarfile
|
|
12
12
|
from dataclasses import dataclass, field
|
|
13
|
-
from functools import
|
|
13
|
+
from functools import reduce
|
|
14
14
|
from math import ceil
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
from typing import TYPE_CHECKING, Any
|
|
@@ -22,6 +22,7 @@ import podman.domain.containers
|
|
|
22
22
|
import podman.domain.images
|
|
23
23
|
import podman.domain.volumes
|
|
24
24
|
import podman.errors
|
|
25
|
+
from cachetools.func import ttl_cache
|
|
25
26
|
from dataclasses_json import dataclass_json
|
|
26
27
|
from gpustack_runner import split_image
|
|
27
28
|
from podman.domain.containers_create import CreateMixin
|
|
@@ -57,7 +58,7 @@ from .__utils__ import (
|
|
|
57
58
|
safe_json,
|
|
58
59
|
sensitive_env_var,
|
|
59
60
|
)
|
|
60
|
-
from .cdi import
|
|
61
|
+
from .cdi import dump_config as cdi_dump_config
|
|
61
62
|
|
|
62
63
|
if TYPE_CHECKING:
|
|
63
64
|
from collections.abc import Callable, Generator
|
|
@@ -317,7 +318,7 @@ class PodmanDeployer(EndoscopicDeployer):
|
|
|
317
318
|
"""
|
|
318
319
|
|
|
319
320
|
@staticmethod
|
|
320
|
-
@
|
|
321
|
+
@ttl_cache(maxsize=1, ttl=60)
|
|
321
322
|
def is_supported() -> bool:
|
|
322
323
|
"""
|
|
323
324
|
Check if Podman is supported in the current environment.
|
|
@@ -998,9 +999,9 @@ class PodmanDeployer(EndoscopicDeployer):
|
|
|
998
999
|
privileged = create_options.get("privileged", False)
|
|
999
1000
|
|
|
1000
1001
|
# Generate CDI config if not yet.
|
|
1001
|
-
if envs.
|
|
1002
|
+
if envs.GPUSTACK_RUNTIME_PODMAN_CDI_SPECS_GENERATE:
|
|
1002
1003
|
for re in runtime_env:
|
|
1003
|
-
|
|
1004
|
+
cdi_dump_config(
|
|
1004
1005
|
manufacturer=vd_manus[re],
|
|
1005
1006
|
output=envs.GPUSTACK_RUNTIME_DEPLOY_CDI_SPECS_DIRECTORY,
|
|
1006
1007
|
)
|
|
@@ -1484,7 +1485,7 @@ class PodmanDeployer(EndoscopicDeployer):
|
|
|
1484
1485
|
def _get(
|
|
1485
1486
|
self,
|
|
1486
1487
|
name: WorkloadName,
|
|
1487
|
-
namespace: WorkloadNamespace | None = None,
|
|
1488
|
+
namespace: WorkloadNamespace | None = None,
|
|
1488
1489
|
) -> WorkloadStatus | None:
|
|
1489
1490
|
"""
|
|
1490
1491
|
Get the status of a Podman workload.
|
|
@@ -1605,7 +1606,7 @@ class PodmanDeployer(EndoscopicDeployer):
|
|
|
1605
1606
|
@_supported
|
|
1606
1607
|
def _list(
|
|
1607
1608
|
self,
|
|
1608
|
-
namespace: WorkloadNamespace | None = None,
|
|
1609
|
+
namespace: WorkloadNamespace | None = None,
|
|
1609
1610
|
labels: dict[str, str] | None = None,
|
|
1610
1611
|
) -> list[WorkloadStatus]:
|
|
1611
1612
|
"""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
1
|
+
from __future__ import annotations as __future_annotations__
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
@@ -13,9 +13,8 @@ from .__types__ import (
|
|
|
13
13
|
backend_to_manufacturer,
|
|
14
14
|
manufacturer_to_backend,
|
|
15
15
|
reduce_devices_distances,
|
|
16
|
-
supported_backends,
|
|
17
|
-
supported_manufacturers,
|
|
18
16
|
)
|
|
17
|
+
from .__utils__ import str_range_to_list
|
|
19
18
|
from .amd import AMDDetector
|
|
20
19
|
from .ascend import AscendDetector
|
|
21
20
|
from .cambricon import CambriconDetector
|
|
@@ -62,6 +61,42 @@ def supported_list() -> list[Detector]:
|
|
|
62
61
|
return [det for det in _DETECTORS if det.is_supported()]
|
|
63
62
|
|
|
64
63
|
|
|
64
|
+
def available_manufacturers() -> list[ManufacturerEnum]:
|
|
65
|
+
"""
|
|
66
|
+
Get a list of available manufacturers,
|
|
67
|
+
regardless of whether they are supported or not.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
A list of available manufacturers.
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
return list(_DETECTORS_MAP.keys())
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def supported_manufacturers() -> list[ManufacturerEnum]:
|
|
77
|
+
"""
|
|
78
|
+
Get a list of supported manufacturers,
|
|
79
|
+
must be supported in the current environment.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
A list of supported manufacturers.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
return [det.manufacturer for det in _DETECTORS if det.is_supported()]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def available_backends() -> list[str]:
|
|
89
|
+
"""
|
|
90
|
+
Get a list of available backends,
|
|
91
|
+
regardless of whether they are supported or not.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
A list of available backends.
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
return [manufacturer_to_backend(manu) for manu in _DETECTORS_MAP]
|
|
98
|
+
|
|
99
|
+
|
|
65
100
|
def detect_backend(
|
|
66
101
|
fast: bool = True,
|
|
67
102
|
manufacturer: ManufacturerEnum = None,
|
|
@@ -186,7 +221,7 @@ def get_devices_topologies(
|
|
|
186
221
|
devices = detect_devices(fast=fast, manufacturer=manufacturer)
|
|
187
222
|
if not devices:
|
|
188
223
|
return []
|
|
189
|
-
group =
|
|
224
|
+
group = not fast
|
|
190
225
|
|
|
191
226
|
# Group devices by manufacturer.
|
|
192
227
|
if group:
|
|
@@ -260,6 +295,8 @@ __all__ = [
|
|
|
260
295
|
"Devices",
|
|
261
296
|
"ManufacturerEnum",
|
|
262
297
|
"Topology",
|
|
298
|
+
"available_backends",
|
|
299
|
+
"available_manufacturers",
|
|
263
300
|
"backend_to_manufacturer",
|
|
264
301
|
"detect_backend",
|
|
265
302
|
"detect_devices",
|
|
@@ -268,7 +305,7 @@ __all__ = [
|
|
|
268
305
|
"group_devices_by_manufacturer",
|
|
269
306
|
"manufacturer_to_backend",
|
|
270
307
|
"reduce_devices_distances",
|
|
271
|
-
"
|
|
308
|
+
"str_range_to_list",
|
|
272
309
|
"supported_list",
|
|
273
310
|
"supported_manufacturers",
|
|
274
311
|
]
|