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 }