github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/driver/executor_plugin.go (about) 1 package driver 2 3 import ( 4 "encoding/gob" 5 "log" 6 "net/rpc" 7 "os" 8 "syscall" 9 "time" 10 11 "github.com/hashicorp/go-plugin" 12 "github.com/hashicorp/nomad/client/driver/executor" 13 cstructs "github.com/hashicorp/nomad/client/structs" 14 "github.com/hashicorp/nomad/nomad/structs" 15 ) 16 17 // Registering these types since we have to serialize and de-serialize the Task 18 // structs over the wire between drivers and the executor. 19 func init() { 20 gob.Register([]interface{}{}) 21 gob.Register(map[string]interface{}{}) 22 gob.Register([]map[string]string{}) 23 gob.Register([]map[string]int{}) 24 gob.Register(syscall.Signal(0x1)) 25 } 26 27 type ExecutorRPC struct { 28 client *rpc.Client 29 logger *log.Logger 30 } 31 32 // LaunchCmdArgs wraps a user command and the args for the purposes of RPC 33 type LaunchCmdArgs struct { 34 Cmd *executor.ExecCommand 35 } 36 37 type ExecCmdArgs struct { 38 Deadline time.Time 39 Name string 40 Args []string 41 } 42 43 type ExecCmdReturn struct { 44 Output []byte 45 Code int 46 } 47 48 func (e *ExecutorRPC) LaunchCmd(cmd *executor.ExecCommand) (*executor.ProcessState, error) { 49 var ps *executor.ProcessState 50 err := e.client.Call("Plugin.LaunchCmd", LaunchCmdArgs{Cmd: cmd}, &ps) 51 return ps, err 52 } 53 54 func (e *ExecutorRPC) LaunchSyslogServer() (*executor.SyslogServerState, error) { 55 var ss *executor.SyslogServerState 56 err := e.client.Call("Plugin.LaunchSyslogServer", new(interface{}), &ss) 57 return ss, err 58 } 59 60 func (e *ExecutorRPC) Wait() (*executor.ProcessState, error) { 61 var ps executor.ProcessState 62 err := e.client.Call("Plugin.Wait", new(interface{}), &ps) 63 return &ps, err 64 } 65 66 func (e *ExecutorRPC) ShutDown() error { 67 return e.client.Call("Plugin.ShutDown", new(interface{}), new(interface{})) 68 } 69 70 func (e *ExecutorRPC) Exit() error { 71 return e.client.Call("Plugin.Exit", new(interface{}), new(interface{})) 72 } 73 74 func (e *ExecutorRPC) SetContext(ctx *executor.ExecutorContext) error { 75 return e.client.Call("Plugin.SetContext", ctx, new(interface{})) 76 } 77 78 func (e *ExecutorRPC) UpdateLogConfig(logConfig *structs.LogConfig) error { 79 return e.client.Call("Plugin.UpdateLogConfig", logConfig, new(interface{})) 80 } 81 82 func (e *ExecutorRPC) UpdateTask(task *structs.Task) error { 83 return e.client.Call("Plugin.UpdateTask", task, new(interface{})) 84 } 85 86 func (e *ExecutorRPC) DeregisterServices() error { 87 return e.client.Call("Plugin.DeregisterServices", new(interface{}), new(interface{})) 88 } 89 90 func (e *ExecutorRPC) Version() (*executor.ExecutorVersion, error) { 91 var version executor.ExecutorVersion 92 err := e.client.Call("Plugin.Version", new(interface{}), &version) 93 return &version, err 94 } 95 96 func (e *ExecutorRPC) Stats() (*cstructs.TaskResourceUsage, error) { 97 var resourceUsage cstructs.TaskResourceUsage 98 err := e.client.Call("Plugin.Stats", new(interface{}), &resourceUsage) 99 return &resourceUsage, err 100 } 101 102 func (e *ExecutorRPC) Signal(s os.Signal) error { 103 return e.client.Call("Plugin.Signal", &s, new(interface{})) 104 } 105 106 func (e *ExecutorRPC) Exec(deadline time.Time, name string, args []string) ([]byte, int, error) { 107 req := ExecCmdArgs{ 108 Deadline: deadline, 109 Name: name, 110 Args: args, 111 } 112 var resp *ExecCmdReturn 113 err := e.client.Call("Plugin.Exec", req, &resp) 114 if resp == nil { 115 return nil, 0, err 116 } 117 return resp.Output, resp.Code, err 118 } 119 120 type ExecutorRPCServer struct { 121 Impl executor.Executor 122 logger *log.Logger 123 } 124 125 func (e *ExecutorRPCServer) LaunchCmd(args LaunchCmdArgs, ps *executor.ProcessState) error { 126 state, err := e.Impl.LaunchCmd(args.Cmd) 127 if state != nil { 128 *ps = *state 129 } 130 return err 131 } 132 133 func (e *ExecutorRPCServer) LaunchSyslogServer(args interface{}, ss *executor.SyslogServerState) error { 134 state, err := e.Impl.LaunchSyslogServer() 135 if state != nil { 136 *ss = *state 137 } 138 return err 139 } 140 141 func (e *ExecutorRPCServer) Wait(args interface{}, ps *executor.ProcessState) error { 142 state, err := e.Impl.Wait() 143 if state != nil { 144 *ps = *state 145 } 146 return err 147 } 148 149 func (e *ExecutorRPCServer) ShutDown(args interface{}, resp *interface{}) error { 150 return e.Impl.ShutDown() 151 } 152 153 func (e *ExecutorRPCServer) Exit(args interface{}, resp *interface{}) error { 154 return e.Impl.Exit() 155 } 156 157 func (e *ExecutorRPCServer) SetContext(args *executor.ExecutorContext, resp *interface{}) error { 158 return e.Impl.SetContext(args) 159 } 160 161 func (e *ExecutorRPCServer) UpdateLogConfig(args *structs.LogConfig, resp *interface{}) error { 162 return e.Impl.UpdateLogConfig(args) 163 } 164 165 func (e *ExecutorRPCServer) UpdateTask(args *structs.Task, resp *interface{}) error { 166 return e.Impl.UpdateTask(args) 167 } 168 169 func (e *ExecutorRPCServer) DeregisterServices(args interface{}, resp *interface{}) error { 170 // In 0.6 this is a noop. Goes away in 0.7. 171 return nil 172 } 173 174 func (e *ExecutorRPCServer) Version(args interface{}, version *executor.ExecutorVersion) error { 175 ver, err := e.Impl.Version() 176 if ver != nil { 177 *version = *ver 178 } 179 return err 180 } 181 182 func (e *ExecutorRPCServer) Stats(args interface{}, resourceUsage *cstructs.TaskResourceUsage) error { 183 ru, err := e.Impl.Stats() 184 if ru != nil { 185 *resourceUsage = *ru 186 } 187 return err 188 } 189 190 func (e *ExecutorRPCServer) Signal(args os.Signal, resp *interface{}) error { 191 return e.Impl.Signal(args) 192 } 193 194 func (e *ExecutorRPCServer) Exec(args ExecCmdArgs, result *ExecCmdReturn) error { 195 out, code, err := e.Impl.Exec(args.Deadline, args.Name, args.Args) 196 ret := &ExecCmdReturn{ 197 Output: out, 198 Code: code, 199 } 200 *result = *ret 201 return err 202 } 203 204 type ExecutorPlugin struct { 205 logger *log.Logger 206 Impl *ExecutorRPCServer 207 } 208 209 func (p *ExecutorPlugin) Server(*plugin.MuxBroker) (interface{}, error) { 210 if p.Impl == nil { 211 p.Impl = &ExecutorRPCServer{Impl: executor.NewExecutor(p.logger), logger: p.logger} 212 } 213 return p.Impl, nil 214 } 215 216 func (p *ExecutorPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { 217 return &ExecutorRPC{client: c, logger: p.logger}, nil 218 }