2016-02-05 00:03:17 +00:00
|
|
|
package driver
|
2016-02-03 19:54:54 +00:00
|
|
|
|
|
|
|
import (
|
2016-02-05 01:36:31 +00:00
|
|
|
"io"
|
2016-02-03 19:54:54 +00:00
|
|
|
"log"
|
2016-02-04 18:09:52 +00:00
|
|
|
"net"
|
2016-02-03 19:54:54 +00:00
|
|
|
"net/rpc"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-plugin"
|
2016-02-05 00:03:17 +00:00
|
|
|
"github.com/hashicorp/nomad/client/driver/executor"
|
2016-02-03 19:54:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var HandshakeConfig = plugin.HandshakeConfig{
|
|
|
|
ProtocolVersion: 1,
|
2016-02-05 00:38:17 +00:00
|
|
|
MagicCookieKey: "NOMAD_PLUGIN_MAGIC_COOKIE",
|
|
|
|
MagicCookieValue: "e4327c2e01eabfd75a8a67adb114fb34a757d57eee7728d857a8cec6e91a7255",
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 01:36:31 +00:00
|
|
|
func GetPluginMap(w io.Writer) map[string]plugin.Plugin {
|
|
|
|
p := new(ExecutorPlugin)
|
2016-02-08 23:07:18 +00:00
|
|
|
p.logger = log.New(w, "", log.LstdFlags)
|
2016-02-05 01:36:31 +00:00
|
|
|
return map[string]plugin.Plugin{"executor": p}
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 00:38:17 +00:00
|
|
|
// ExecutorReattachConfig is the config that we seralize and de-serialize and
|
|
|
|
// store in disk
|
2016-02-04 18:09:52 +00:00
|
|
|
type ExecutorReattachConfig struct {
|
|
|
|
Pid int
|
|
|
|
AddrNet string
|
|
|
|
AddrName string
|
|
|
|
}
|
|
|
|
|
2016-02-05 00:38:17 +00:00
|
|
|
// PluginConfig returns a config from an ExecutorReattachConfig
|
2016-02-04 18:09:52 +00:00
|
|
|
func (c *ExecutorReattachConfig) PluginConfig() *plugin.ReattachConfig {
|
|
|
|
var addr net.Addr
|
|
|
|
switch c.AddrNet {
|
|
|
|
case "unix", "unixgram", "unixpacket":
|
|
|
|
addr, _ = net.ResolveUnixAddr(c.AddrNet, c.AddrName)
|
|
|
|
case "tcp", "tcp4", "tcp6":
|
|
|
|
addr, _ = net.ResolveTCPAddr(c.AddrNet, c.AddrName)
|
|
|
|
}
|
|
|
|
return &plugin.ReattachConfig{Pid: c.Pid, Addr: addr}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewExecutorReattachConfig(c *plugin.ReattachConfig) *ExecutorReattachConfig {
|
|
|
|
return &ExecutorReattachConfig{Pid: c.Pid, AddrNet: c.Addr.Network(), AddrName: c.Addr.String()}
|
|
|
|
}
|
|
|
|
|
2016-02-03 19:54:54 +00:00
|
|
|
type ExecutorRPC struct {
|
|
|
|
client *rpc.Client
|
|
|
|
}
|
|
|
|
|
2016-02-05 00:38:17 +00:00
|
|
|
// LaunchCmdArgs wraps a user command and the args for the purposes of RPC
|
2016-02-03 19:54:54 +00:00
|
|
|
type LaunchCmdArgs struct {
|
2016-02-05 00:03:17 +00:00
|
|
|
Cmd *executor.ExecCommand
|
|
|
|
Ctx *executor.ExecutorContext
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 00:03:17 +00:00
|
|
|
func (e *ExecutorRPC) LaunchCmd(cmd *executor.ExecCommand, ctx *executor.ExecutorContext) (*executor.ProcessState, error) {
|
|
|
|
var ps *executor.ProcessState
|
2016-02-04 03:00:21 +00:00
|
|
|
err := e.client.Call("Plugin.LaunchCmd", LaunchCmdArgs{Cmd: cmd, Ctx: ctx}, &ps)
|
2016-02-04 01:22:21 +00:00
|
|
|
return ps, err
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 00:03:17 +00:00
|
|
|
func (e *ExecutorRPC) Wait() (*executor.ProcessState, error) {
|
|
|
|
var ps executor.ProcessState
|
2016-02-03 19:54:54 +00:00
|
|
|
err := e.client.Call("Plugin.Wait", new(interface{}), &ps)
|
|
|
|
return &ps, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ExecutorRPC) ShutDown() error {
|
2016-02-05 00:28:31 +00:00
|
|
|
return e.client.Call("Plugin.ShutDown", new(interface{}), new(interface{}))
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ExecutorRPC) Exit() error {
|
2016-02-05 00:28:31 +00:00
|
|
|
return e.client.Call("Plugin.Exit", new(interface{}), new(interface{}))
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ExecutorRPCServer struct {
|
2016-02-05 00:03:17 +00:00
|
|
|
Impl executor.Executor
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 00:03:17 +00:00
|
|
|
func (e *ExecutorRPCServer) LaunchCmd(args LaunchCmdArgs, ps *executor.ProcessState) error {
|
2016-02-04 03:00:21 +00:00
|
|
|
state, err := e.Impl.LaunchCmd(args.Cmd, args.Ctx)
|
2016-02-04 19:51:43 +00:00
|
|
|
if state != nil {
|
|
|
|
*ps = *state
|
|
|
|
}
|
2016-02-03 19:54:54 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-02-05 00:03:17 +00:00
|
|
|
func (e *ExecutorRPCServer) Wait(args interface{}, ps *executor.ProcessState) error {
|
2016-02-04 19:51:43 +00:00
|
|
|
state, err := e.Impl.Wait()
|
|
|
|
if state != nil {
|
|
|
|
*ps = *state
|
|
|
|
}
|
2016-02-03 19:54:54 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-02-05 00:28:31 +00:00
|
|
|
func (e *ExecutorRPCServer) ShutDown(args interface{}, resp *interface{}) error {
|
|
|
|
return e.Impl.ShutDown()
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 00:28:31 +00:00
|
|
|
func (e *ExecutorRPCServer) Exit(args interface{}, resp *interface{}) error {
|
|
|
|
return e.Impl.Exit()
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type ExecutorPlugin struct {
|
|
|
|
logger *log.Logger
|
2016-02-08 19:56:48 +00:00
|
|
|
Impl *ExecutorRPCServer
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *ExecutorPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
|
2016-02-08 19:56:48 +00:00
|
|
|
if p.Impl == nil {
|
|
|
|
p.Impl = &ExecutorRPCServer{Impl: executor.NewExecutor(p.logger)}
|
|
|
|
}
|
|
|
|
return p.Impl, nil
|
2016-02-03 19:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *ExecutorPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
|
|
|
|
return &ExecutorRPC{client: c}, nil
|
|
|
|
}
|