@@ -24,6 +24,9 @@ import (
24
24
"strings"
25
25
"time"
26
26
27
+ "google.golang.org/grpc/codes"
28
+ "google.golang.org/grpc/status"
29
+
27
30
"github.com/container-storage-interface/spec/lib/go/csi"
28
31
"github.com/kubernetes-csi/csi-lib-utils/protosanitizer"
29
32
"google.golang.org/grpc"
@@ -33,6 +36,9 @@ import (
33
36
const (
34
37
// Interval of logging connection errors
35
38
connectionLoggingInterval = 10 * time .Second
39
+
40
+ // Interval of trying to call Probe() until it succeeds
41
+ probeInterval = 1 * time .Second
36
42
)
37
43
38
44
// Connect opens insecure gRPC connection to a CSI driver. Address must be either absolute path to UNIX domain socket
@@ -163,6 +169,7 @@ func LogGRPC(ctx context.Context, method string, req, reply interface{}, cc *grp
163
169
return err
164
170
}
165
171
172
+ // GetDriverName returns name of CSI driver.
166
173
func GetDriverName (ctx context.Context , conn * grpc.ClientConn ) (string , error ) {
167
174
client := csi .NewIdentityClient (conn )
168
175
@@ -177,3 +184,104 @@ func GetDriverName(ctx context.Context, conn *grpc.ClientConn) (string, error) {
177
184
}
178
185
return name , nil
179
186
}
187
+
188
+ // PluginCapabilitySet is set of CSI plugin capabilities. Only supported capabilities are in the map.
189
+ type PluginCapabilitySet map [csi.PluginCapability_Service_Type ]bool
190
+
191
+ // GetPluginCapabilities returns set of supported capabilities of CSI driver.
192
+ func GetPluginCapabilities (ctx context.Context , conn * grpc.ClientConn ) (PluginCapabilitySet , error ) {
193
+ client := csi .NewIdentityClient (conn )
194
+ req := csi.GetPluginCapabilitiesRequest {}
195
+ rsp , err := client .GetPluginCapabilities (ctx , & req )
196
+ if err != nil {
197
+ return nil , err
198
+ }
199
+ caps := PluginCapabilitySet {}
200
+ for _ , cap := range rsp .GetCapabilities () {
201
+ if cap == nil {
202
+ continue
203
+ }
204
+ srv := cap .GetService ()
205
+ if srv == nil {
206
+ continue
207
+ }
208
+ t := srv .GetType ()
209
+ caps [t ] = true
210
+ }
211
+ return caps , nil
212
+ }
213
+
214
+ // ControllerCapabilitySet is set of CSI controller capabilities. Only supported capabilities are in the map.
215
+ type ControllerCapabilitySet map [csi.ControllerServiceCapability_RPC_Type ]bool
216
+
217
+ // GetControllerCapabilities returns set of supported controller capabilities of CSI driver.
218
+ func GetControllerCapabilities (ctx context.Context , conn * grpc.ClientConn ) (ControllerCapabilitySet , error ) {
219
+ client := csi .NewControllerClient (conn )
220
+ req := csi.ControllerGetCapabilitiesRequest {}
221
+ rsp , err := client .ControllerGetCapabilities (ctx , & req )
222
+ if err != nil {
223
+ return nil , err
224
+ }
225
+
226
+ caps := ControllerCapabilitySet {}
227
+ for _ , cap := range rsp .GetCapabilities () {
228
+ if cap == nil {
229
+ continue
230
+ }
231
+ rpc := cap .GetRpc ()
232
+ if rpc == nil {
233
+ continue
234
+ }
235
+ t := rpc .GetType ()
236
+ caps [t ] = true
237
+ }
238
+ return caps , nil
239
+ }
240
+
241
+ // Probe calls Probe() of a CSI driver and waits until the driver becomes ready.
242
+ // Any error other than timeout is returned.
243
+ func Probe (conn * grpc.ClientConn , singleProbeTimeout time.Duration ) error {
244
+ client := csi .NewIdentityClient (conn )
245
+
246
+ for {
247
+ klog .Info ("Probing CSI driver for readiness" )
248
+ ready , err := probeOnce (client , singleProbeTimeout )
249
+ if err != nil {
250
+ st , ok := status .FromError (err )
251
+ if ! ok {
252
+ // This is not gRPC error. The probe must have failed before gRPC
253
+ // method was called, otherwise we would get gRPC error.
254
+ return fmt .Errorf ("CSI driver probe failed: %s" , err )
255
+ }
256
+ if st .Code () != codes .DeadlineExceeded {
257
+ return fmt .Errorf ("CSI driver probe failed: %s" , err )
258
+ }
259
+ // Timeout -> driver is not ready. Fall through to sleep() below.
260
+ klog .Warning ("CSI driver probe timed out" )
261
+ } else {
262
+ if ready {
263
+ return nil
264
+ }
265
+ klog .Warning ("CSI driver is not ready" )
266
+ }
267
+ // Timeout was returned or driver is not ready.
268
+ time .Sleep (probeInterval )
269
+ }
270
+ }
271
+
272
+ func probeOnce (client csi.IdentityClient , timeout time.Duration ) (ready bool , err error ) {
273
+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
274
+ defer cancel ()
275
+ req := csi.ProbeRequest {}
276
+ rsp , err := client .Probe (ctx , & req )
277
+
278
+ if err != nil {
279
+ return false , err
280
+ }
281
+
282
+ r := rsp .GetReady ()
283
+ if r != nil && r .GetValue () {
284
+ return true , nil
285
+ }
286
+ return false , nil
287
+ }
0 commit comments