github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/plugins/device/server.go (about)

     1  package device
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/golang/protobuf/ptypes"
     9  	"github.com/hashicorp/go-plugin"
    10  
    11  	"github.com/hashicorp/nomad/plugins/device/proto"
    12  )
    13  
    14  // devicePluginServer wraps a device plugin and exposes it via gRPC.
    15  type devicePluginServer struct {
    16  	broker *plugin.GRPCBroker
    17  	impl   DevicePlugin
    18  }
    19  
    20  func (d *devicePluginServer) Fingerprint(req *proto.FingerprintRequest, stream proto.DevicePlugin_FingerprintServer) error {
    21  	ctx := stream.Context()
    22  	outCh, err := d.impl.Fingerprint(ctx)
    23  	if err != nil {
    24  		return err
    25  	}
    26  
    27  	for {
    28  		select {
    29  		case <-ctx.Done():
    30  			return nil
    31  		case resp, ok := <-outCh:
    32  			// The output channel has been closed, end the stream
    33  			if !ok {
    34  				return nil
    35  			}
    36  
    37  			// Handle any error
    38  			if resp.Error != nil {
    39  				return resp.Error
    40  			}
    41  
    42  			// Convert the devices
    43  			out := convertStructDeviceGroups(resp.Devices)
    44  
    45  			// Build the response
    46  			presp := &proto.FingerprintResponse{
    47  				DeviceGroup: out,
    48  			}
    49  
    50  			// Send the devices
    51  			if err := stream.Send(presp); err != nil {
    52  				return err
    53  			}
    54  		}
    55  	}
    56  }
    57  
    58  func (d *devicePluginServer) Reserve(ctx context.Context, req *proto.ReserveRequest) (*proto.ReserveResponse, error) {
    59  	resp, err := d.impl.Reserve(req.GetDeviceIds())
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	// Make the response
    65  	presp := &proto.ReserveResponse{
    66  		ContainerRes: convertStructContainerReservation(resp),
    67  	}
    68  
    69  	return presp, nil
    70  }
    71  
    72  func (d *devicePluginServer) Stats(req *proto.StatsRequest, stream proto.DevicePlugin_StatsServer) error {
    73  	ctx := stream.Context()
    74  
    75  	// Retrieve the collection interval
    76  	interval, err := ptypes.Duration(req.CollectionInterval)
    77  	if err != nil {
    78  		return fmt.Errorf("failed to parse collection interval: %v", err)
    79  	}
    80  
    81  	// Default the duration if we get an invalid duration
    82  	if interval.Nanoseconds() == 0 {
    83  		interval = time.Second
    84  	}
    85  
    86  	outCh, err := d.impl.Stats(ctx, interval)
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	for {
    92  		select {
    93  		case <-ctx.Done():
    94  			return nil
    95  		case resp, ok := <-outCh:
    96  			// The output channel has been closed, end the stream
    97  			if !ok {
    98  				return nil
    99  			}
   100  
   101  			// Handle any error
   102  			if resp.Error != nil {
   103  				return resp.Error
   104  			}
   105  
   106  			// Convert the devices
   107  			out := convertStructDeviceGroupsStats(resp.Groups)
   108  
   109  			// Build the response
   110  			presp := &proto.StatsResponse{
   111  				Groups: out,
   112  			}
   113  
   114  			// Send the devices
   115  			if err := stream.Send(presp); err != nil {
   116  				return err
   117  			}
   118  		}
   119  	}
   120  }