github.com/hernad/nomad@v1.6.112/drivers/shared/executor/grpc_server.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package executor
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/golang/protobuf/ptypes"
    13  	"google.golang.org/grpc/codes"
    14  	"google.golang.org/grpc/status"
    15  
    16  	"github.com/hernad/nomad/drivers/shared/executor/proto"
    17  	"github.com/hernad/nomad/nomad/structs"
    18  	"github.com/hernad/nomad/plugins/drivers"
    19  	sproto "github.com/hernad/nomad/plugins/shared/structs/proto"
    20  )
    21  
    22  type grpcExecutorServer struct {
    23  	impl Executor
    24  }
    25  
    26  func (s *grpcExecutorServer) Launch(ctx context.Context, req *proto.LaunchRequest) (*proto.LaunchResponse, error) {
    27  	ps, err := s.impl.Launch(&ExecCommand{
    28  		Cmd:                req.Cmd,
    29  		Args:               req.Args,
    30  		Resources:          drivers.ResourcesFromProto(req.Resources),
    31  		StdoutPath:         req.StdoutPath,
    32  		StderrPath:         req.StderrPath,
    33  		Env:                req.Env,
    34  		User:               req.User,
    35  		TaskDir:            req.TaskDir,
    36  		ResourceLimits:     req.ResourceLimits,
    37  		BasicProcessCgroup: req.BasicProcessCgroup,
    38  		NoPivotRoot:        req.NoPivotRoot,
    39  		Mounts:             drivers.MountsFromProto(req.Mounts),
    40  		Devices:            drivers.DevicesFromProto(req.Devices),
    41  		NetworkIsolation:   drivers.NetworkIsolationSpecFromProto(req.NetworkIsolation),
    42  		ModePID:            req.DefaultPidMode,
    43  		ModeIPC:            req.DefaultIpcMode,
    44  		Capabilities:       req.Capabilities,
    45  	})
    46  
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	process, err := processStateToProto(ps)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	return &proto.LaunchResponse{
    57  		Process: process,
    58  	}, nil
    59  }
    60  
    61  func (s *grpcExecutorServer) Wait(ctx context.Context, req *proto.WaitRequest) (*proto.WaitResponse, error) {
    62  	ps, err := s.impl.Wait(ctx)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	process, err := processStateToProto(ps)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	return &proto.WaitResponse{
    73  		Process: process,
    74  	}, nil
    75  }
    76  
    77  func (s *grpcExecutorServer) Shutdown(ctx context.Context, req *proto.ShutdownRequest) (*proto.ShutdownResponse, error) {
    78  	if err := s.impl.Shutdown(req.Signal, time.Duration(req.GracePeriod)); err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	return &proto.ShutdownResponse{}, nil
    83  }
    84  
    85  func (s *grpcExecutorServer) UpdateResources(ctx context.Context, req *proto.UpdateResourcesRequest) (*proto.UpdateResourcesResponse, error) {
    86  	if err := s.impl.UpdateResources(drivers.ResourcesFromProto(req.Resources)); err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	return &proto.UpdateResourcesResponse{}, nil
    91  }
    92  
    93  func (s *grpcExecutorServer) Version(context.Context, *proto.VersionRequest) (*proto.VersionResponse, error) {
    94  	v, err := s.impl.Version()
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	return &proto.VersionResponse{
   100  		Version: v.Version,
   101  	}, nil
   102  }
   103  
   104  func (s *grpcExecutorServer) Stats(req *proto.StatsRequest, stream proto.Executor_StatsServer) error {
   105  	interval := time.Duration(req.Interval)
   106  	if interval == 0 {
   107  		interval = time.Second
   108  	}
   109  
   110  	outCh, err := s.impl.Stats(stream.Context(), interval)
   111  	if err != nil {
   112  		if rec, ok := err.(structs.Recoverable); ok {
   113  			st := status.New(codes.FailedPrecondition, rec.Error())
   114  			st, err := st.WithDetails(&sproto.RecoverableError{Recoverable: rec.IsRecoverable()})
   115  			if err != nil {
   116  				// If this error, it will always error
   117  				panic(err)
   118  			}
   119  			return st.Err()
   120  		}
   121  		return err
   122  	}
   123  
   124  	for resp := range outCh {
   125  		pbStats, err := drivers.TaskStatsToProto(resp)
   126  		if err != nil {
   127  			return err
   128  		}
   129  
   130  		presp := &proto.StatsResponse{
   131  			Stats: pbStats,
   132  		}
   133  
   134  		// Send the stats
   135  		if err := stream.Send(presp); err != nil {
   136  			return err
   137  		}
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  func (s *grpcExecutorServer) Signal(ctx context.Context, req *proto.SignalRequest) (*proto.SignalResponse, error) {
   144  	sig := syscall.Signal(req.Signal)
   145  	if err := s.impl.Signal(sig); err != nil {
   146  		return nil, err
   147  	}
   148  	return &proto.SignalResponse{}, nil
   149  }
   150  
   151  func (s *grpcExecutorServer) Exec(ctx context.Context, req *proto.ExecRequest) (*proto.ExecResponse, error) {
   152  	deadline, err := ptypes.Timestamp(req.Deadline)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	out, exit, err := s.impl.Exec(deadline, req.Cmd, req.Args)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  
   162  	return &proto.ExecResponse{
   163  		Output:   out,
   164  		ExitCode: int32(exit),
   165  	}, nil
   166  }
   167  
   168  func (s *grpcExecutorServer) ExecStreaming(server proto.Executor_ExecStreamingServer) error {
   169  	msg, err := server.Recv()
   170  	if err != nil {
   171  		return fmt.Errorf("failed to receive initial message: %v", err)
   172  	}
   173  
   174  	if msg.Setup == nil {
   175  		return fmt.Errorf("first message should always be setup")
   176  	}
   177  
   178  	return s.impl.ExecStreaming(server.Context(),
   179  		msg.Setup.Command, msg.Setup.Tty,
   180  		server)
   181  }