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  }