github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/drivers/shared/executor/utils.go (about)

     1  package executor
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  
     9  	"github.com/golang/protobuf/ptypes"
    10  	hclog "github.com/hashicorp/go-hclog"
    11  	plugin "github.com/hashicorp/go-plugin"
    12  	"github.com/hashicorp/nomad/drivers/shared/executor/proto"
    13  	"github.com/hashicorp/nomad/plugins/base"
    14  )
    15  
    16  const (
    17  	// ExecutorDefaultMaxPort is the default max port used by the executor for
    18  	// searching for an available port
    19  	ExecutorDefaultMaxPort = 14512
    20  
    21  	// ExecutorDefaultMinPort is the default min port used by the executor for
    22  	// searching for an available port
    23  	ExecutorDefaultMinPort = 14000
    24  )
    25  
    26  // CreateExecutor launches an executor plugin and returns an instance of the
    27  // Executor interface
    28  func CreateExecutor(logger hclog.Logger, driverConfig *base.ClientDriverConfig,
    29  	executorConfig *ExecutorConfig) (Executor, *plugin.Client, error) {
    30  
    31  	c, err := json.Marshal(executorConfig)
    32  	if err != nil {
    33  		return nil, nil, fmt.Errorf("unable to create executor config: %v", err)
    34  	}
    35  	bin, err := os.Executable()
    36  	if err != nil {
    37  		return nil, nil, fmt.Errorf("unable to find the nomad binary: %v", err)
    38  	}
    39  
    40  	p := &ExecutorPlugin{
    41  		logger:      logger,
    42  		fsIsolation: executorConfig.FSIsolation,
    43  	}
    44  
    45  	config := &plugin.ClientConfig{
    46  		HandshakeConfig:  base.Handshake,
    47  		Plugins:          map[string]plugin.Plugin{"executor": p},
    48  		Cmd:              exec.Command(bin, "executor", string(c)),
    49  		AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
    50  		Logger:           logger.Named("executor"),
    51  	}
    52  
    53  	if driverConfig != nil {
    54  		config.MaxPort = driverConfig.ClientMaxPort
    55  		config.MinPort = driverConfig.ClientMinPort
    56  	} else {
    57  		config.MaxPort = ExecutorDefaultMaxPort
    58  		config.MinPort = ExecutorDefaultMinPort
    59  	}
    60  
    61  	// setting the setsid of the plugin process so that it doesn't get signals sent to
    62  	// the nomad client.
    63  	if config.Cmd != nil {
    64  		isolateCommand(config.Cmd)
    65  	}
    66  
    67  	return newExecutorClient(config, logger)
    68  }
    69  
    70  // ReattachToExecutor launches a plugin with a given plugin config
    71  func ReattachToExecutor(reattachConfig *plugin.ReattachConfig, logger hclog.Logger) (Executor, *plugin.Client, error) {
    72  	config := &plugin.ClientConfig{
    73  		HandshakeConfig:  base.Handshake,
    74  		Reattach:         reattachConfig,
    75  		Plugins:          GetPluginMap(logger, false),
    76  		AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
    77  		Logger:           logger.Named("executor"),
    78  	}
    79  
    80  	return newExecutorClient(config, logger)
    81  }
    82  
    83  // ReattachToPre09Executor creates a plugin client that reattaches to an existing
    84  // pre 0.9 Nomad executor
    85  func ReattachToPre09Executor(reattachConfig *plugin.ReattachConfig, logger hclog.Logger) (Executor, *plugin.Client, error) {
    86  	config := &plugin.ClientConfig{
    87  		HandshakeConfig:  base.Handshake,
    88  		Reattach:         reattachConfig,
    89  		Plugins:          GetPre09PluginMap(logger, false),
    90  		AllowedProtocols: []plugin.Protocol{plugin.ProtocolNetRPC},
    91  		Logger:           logger.Named("executor"),
    92  	}
    93  	return newExecutorClient(config, logger)
    94  }
    95  
    96  func newExecutorClient(config *plugin.ClientConfig, logger hclog.Logger) (Executor, *plugin.Client, error) {
    97  	executorClient := plugin.NewClient(config)
    98  	rpcClient, err := executorClient.Client()
    99  	if err != nil {
   100  		return nil, nil, fmt.Errorf("error creating rpc client for executor plugin: %v", err)
   101  	}
   102  
   103  	raw, err := rpcClient.Dispense("executor")
   104  	if err != nil {
   105  		return nil, nil, fmt.Errorf("unable to dispense the executor plugin: %v", err)
   106  	}
   107  	executorPlugin, ok := raw.(Executor)
   108  	if !ok {
   109  		return nil, nil, fmt.Errorf("unexpected executor rpc type: %T", raw)
   110  	}
   111  	return executorPlugin, executorClient, nil
   112  }
   113  
   114  func processStateToProto(ps *ProcessState) (*proto.ProcessState, error) {
   115  	timestamp, err := ptypes.TimestampProto(ps.Time)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	pb := &proto.ProcessState{
   120  		Pid:      int32(ps.Pid),
   121  		ExitCode: int32(ps.ExitCode),
   122  		Signal:   int32(ps.Signal),
   123  		Time:     timestamp,
   124  	}
   125  
   126  	return pb, nil
   127  }
   128  
   129  func processStateFromProto(pb *proto.ProcessState) (*ProcessState, error) {
   130  	timestamp, err := ptypes.Timestamp(pb.Time)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	return &ProcessState{
   136  		Pid:      int(pb.Pid),
   137  		ExitCode: int(pb.ExitCode),
   138  		Signal:   int(pb.Signal),
   139  		Time:     timestamp,
   140  	}, nil
   141  }