k8s.io/kubernetes@v1.29.3/pkg/kubelet/cm/dra/plugin/client.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package plugin
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	"google.golang.org/grpc"
    25  	grpccodes "google.golang.org/grpc/codes"
    26  	grpcstatus "google.golang.org/grpc/status"
    27  
    28  	"k8s.io/klog/v2"
    29  	drapbv1alpha2 "k8s.io/kubelet/pkg/apis/dra/v1alpha2"
    30  	drapb "k8s.io/kubelet/pkg/apis/dra/v1alpha3"
    31  )
    32  
    33  const PluginClientTimeout = 45 * time.Second
    34  
    35  type (
    36  	nodeResourceManager interface {
    37  		Prepare(context.Context, *grpc.ClientConn, *plugin, *drapb.NodePrepareResourcesRequest) (*drapb.NodePrepareResourcesResponse, error)
    38  		Unprepare(context.Context, *grpc.ClientConn, *plugin, *drapb.NodeUnprepareResourcesRequest) (*drapb.NodeUnprepareResourcesResponse, error)
    39  	}
    40  
    41  	v1alpha2NodeResourceManager struct{}
    42  	v1alpha3NodeResourceManager struct{}
    43  )
    44  
    45  var nodeResourceManagers = map[string]nodeResourceManager{
    46  	v1alpha2Version: v1alpha2NodeResourceManager{},
    47  	v1alpha3Version: v1alpha3NodeResourceManager{},
    48  }
    49  
    50  func (v1alpha2rm v1alpha2NodeResourceManager) Prepare(ctx context.Context, conn *grpc.ClientConn, _ *plugin, req *drapb.NodePrepareResourcesRequest) (*drapb.NodePrepareResourcesResponse, error) {
    51  	nodeClient := drapbv1alpha2.NewNodeClient(conn)
    52  	response := &drapb.NodePrepareResourcesResponse{
    53  		Claims: make(map[string]*drapb.NodePrepareResourceResponse),
    54  	}
    55  
    56  	for _, claim := range req.Claims {
    57  		res, err := nodeClient.NodePrepareResource(ctx,
    58  			&drapbv1alpha2.NodePrepareResourceRequest{
    59  				Namespace:      claim.Namespace,
    60  				ClaimUid:       claim.Uid,
    61  				ClaimName:      claim.Name,
    62  				ResourceHandle: claim.ResourceHandle,
    63  			})
    64  		result := &drapb.NodePrepareResourceResponse{}
    65  		if err != nil {
    66  			result.Error = err.Error()
    67  		} else {
    68  			result.CDIDevices = res.CdiDevices
    69  		}
    70  		response.Claims[claim.Uid] = result
    71  	}
    72  
    73  	return response, nil
    74  }
    75  
    76  func (v1alpha2rm v1alpha2NodeResourceManager) Unprepare(ctx context.Context, conn *grpc.ClientConn, _ *plugin, req *drapb.NodeUnprepareResourcesRequest) (*drapb.NodeUnprepareResourcesResponse, error) {
    77  	nodeClient := drapbv1alpha2.NewNodeClient(conn)
    78  	response := &drapb.NodeUnprepareResourcesResponse{
    79  		Claims: make(map[string]*drapb.NodeUnprepareResourceResponse),
    80  	}
    81  
    82  	for _, claim := range req.Claims {
    83  		_, err := nodeClient.NodeUnprepareResource(ctx,
    84  			&drapbv1alpha2.NodeUnprepareResourceRequest{
    85  				Namespace:      claim.Namespace,
    86  				ClaimUid:       claim.Uid,
    87  				ClaimName:      claim.Name,
    88  				ResourceHandle: claim.ResourceHandle,
    89  			})
    90  		result := &drapb.NodeUnprepareResourceResponse{}
    91  		if err != nil {
    92  			result.Error = err.Error()
    93  		}
    94  		response.Claims[claim.Uid] = result
    95  	}
    96  
    97  	return response, nil
    98  }
    99  
   100  func (v1alpha3rm v1alpha3NodeResourceManager) Prepare(ctx context.Context, conn *grpc.ClientConn, p *plugin, req *drapb.NodePrepareResourcesRequest) (*drapb.NodePrepareResourcesResponse, error) {
   101  	nodeClient := drapb.NewNodeClient(conn)
   102  	response, err := nodeClient.NodePrepareResources(ctx, req)
   103  	if err != nil {
   104  		status, _ := grpcstatus.FromError(err)
   105  		if status.Code() == grpccodes.Unimplemented {
   106  			p.setVersion(v1alpha2Version)
   107  			return nodeResourceManagers[v1alpha2Version].Prepare(ctx, conn, p, req)
   108  		}
   109  		return nil, err
   110  	}
   111  
   112  	return response, nil
   113  }
   114  
   115  func (v1alpha3rm v1alpha3NodeResourceManager) Unprepare(ctx context.Context, conn *grpc.ClientConn, p *plugin, req *drapb.NodeUnprepareResourcesRequest) (*drapb.NodeUnprepareResourcesResponse, error) {
   116  	nodeClient := drapb.NewNodeClient(conn)
   117  	response, err := nodeClient.NodeUnprepareResources(ctx, req)
   118  	if err != nil {
   119  		status, _ := grpcstatus.FromError(err)
   120  		if status.Code() == grpccodes.Unimplemented {
   121  			p.setVersion(v1alpha2Version)
   122  			return nodeResourceManagers[v1alpha2Version].Unprepare(ctx, conn, p, req)
   123  		}
   124  		return nil, err
   125  	}
   126  
   127  	return response, nil
   128  }
   129  
   130  func NewDRAPluginClient(pluginName string) (drapb.NodeClient, error) {
   131  	if pluginName == "" {
   132  		return nil, fmt.Errorf("plugin name is empty")
   133  	}
   134  
   135  	existingPlugin := draPlugins.get(pluginName)
   136  	if existingPlugin == nil {
   137  		return nil, fmt.Errorf("plugin name %s not found in the list of registered DRA plugins", pluginName)
   138  	}
   139  
   140  	return existingPlugin, nil
   141  }
   142  
   143  func (p *plugin) NodePrepareResources(
   144  	ctx context.Context,
   145  	req *drapb.NodePrepareResourcesRequest,
   146  	opts ...grpc.CallOption,
   147  ) (*drapb.NodePrepareResourcesResponse, error) {
   148  	logger := klog.FromContext(ctx)
   149  	logger.V(4).Info(log("calling NodePrepareResources rpc"), "request", req)
   150  
   151  	conn, err := p.getOrCreateGRPCConn()
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	ctx, cancel := context.WithTimeout(ctx, PluginClientTimeout)
   157  	defer cancel()
   158  
   159  	version := p.getVersion()
   160  	resourceManager, exists := nodeResourceManagers[version]
   161  	if !exists {
   162  		err := fmt.Errorf("unsupported plugin version: %s", version)
   163  		logger.V(4).Info(log("done calling NodePrepareResources rpc"), "response", nil, "err", err)
   164  		return nil, err
   165  	}
   166  
   167  	response, err := resourceManager.Prepare(ctx, conn, p, req)
   168  	logger.V(4).Info(log("done calling NodePrepareResources rpc"), "response", response, "err", err)
   169  	return response, err
   170  }
   171  
   172  func (p *plugin) NodeUnprepareResources(
   173  	ctx context.Context,
   174  	req *drapb.NodeUnprepareResourcesRequest,
   175  	opts ...grpc.CallOption,
   176  ) (*drapb.NodeUnprepareResourcesResponse, error) {
   177  	logger := klog.FromContext(ctx)
   178  	logger.V(4).Info(log("calling NodeUnprepareResource rpc"), "request", req)
   179  
   180  	conn, err := p.getOrCreateGRPCConn()
   181  	if err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	ctx, cancel := context.WithTimeout(ctx, PluginClientTimeout)
   186  	defer cancel()
   187  
   188  	version := p.getVersion()
   189  	resourceManager, exists := nodeResourceManagers[version]
   190  	if !exists {
   191  		err := fmt.Errorf("unsupported plugin version: %s", version)
   192  		logger.V(4).Info(log("done calling NodeUnprepareResources rpc"), "response", nil, "err", err)
   193  		return nil, err
   194  	}
   195  
   196  	response, err := resourceManager.Unprepare(ctx, conn, p, req)
   197  	logger.V(4).Info(log("done calling NodeUnprepareResources rpc"), "response", response, "err", err)
   198  	return response, err
   199  }