mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
This test exercises upgrades between 0.8 and Nomad versions greater than 0.9. We have not supported 0.8.x in a very long time and in any case the test has been marked to skip because the downloader doesn't work.
139 lines
3.9 KiB
Go
139 lines
3.9 KiB
Go
package executor
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/golang/protobuf/ptypes"
|
|
hclog "github.com/hashicorp/go-hclog"
|
|
plugin "github.com/hashicorp/go-plugin"
|
|
"github.com/hashicorp/nomad/drivers/shared/executor/proto"
|
|
"github.com/hashicorp/nomad/plugins/base"
|
|
)
|
|
|
|
const (
|
|
// ExecutorDefaultMaxPort is the default max port used by the executor for
|
|
// searching for an available port
|
|
ExecutorDefaultMaxPort = 14512
|
|
|
|
// ExecutorDefaultMinPort is the default min port used by the executor for
|
|
// searching for an available port
|
|
ExecutorDefaultMinPort = 14000
|
|
)
|
|
|
|
// CreateExecutor launches an executor plugin and returns an instance of the
|
|
// Executor interface
|
|
func CreateExecutor(logger hclog.Logger, driverConfig *base.ClientDriverConfig,
|
|
executorConfig *ExecutorConfig) (Executor, *plugin.Client, error) {
|
|
|
|
c, err := json.Marshal(executorConfig)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("unable to create executor config: %v", err)
|
|
}
|
|
bin, err := os.Executable()
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("unable to find the nomad binary: %v", err)
|
|
}
|
|
|
|
p := &ExecutorPlugin{
|
|
logger: logger,
|
|
fsIsolation: executorConfig.FSIsolation,
|
|
}
|
|
|
|
config := &plugin.ClientConfig{
|
|
HandshakeConfig: base.Handshake,
|
|
Plugins: map[string]plugin.Plugin{"executor": p},
|
|
Cmd: exec.Command(bin, "executor", string(c)),
|
|
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
|
|
Logger: logger.Named("executor"),
|
|
}
|
|
|
|
if driverConfig != nil {
|
|
config.MaxPort = driverConfig.ClientMaxPort
|
|
config.MinPort = driverConfig.ClientMinPort
|
|
} else {
|
|
config.MaxPort = ExecutorDefaultMaxPort
|
|
config.MinPort = ExecutorDefaultMinPort
|
|
}
|
|
|
|
// setting the setsid of the plugin process so that it doesn't get signals sent to
|
|
// the nomad client.
|
|
if config.Cmd != nil {
|
|
isolateCommand(config.Cmd)
|
|
}
|
|
|
|
return newExecutorClient(config, logger)
|
|
}
|
|
|
|
// ReattachToExecutor launches a plugin with a given plugin config
|
|
func ReattachToExecutor(reattachConfig *plugin.ReattachConfig, logger hclog.Logger) (Executor, *plugin.Client, error) {
|
|
config := &plugin.ClientConfig{
|
|
HandshakeConfig: base.Handshake,
|
|
Reattach: reattachConfig,
|
|
Plugins: GetPluginMap(logger, false),
|
|
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
|
|
Logger: logger.Named("executor"),
|
|
}
|
|
|
|
return newExecutorClient(config, logger)
|
|
}
|
|
|
|
func newExecutorClient(config *plugin.ClientConfig, logger hclog.Logger) (Executor, *plugin.Client, error) {
|
|
executorClient := plugin.NewClient(config)
|
|
rpcClient, err := executorClient.Client()
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error creating rpc client for executor plugin: %v", err)
|
|
}
|
|
|
|
raw, err := rpcClient.Dispense("executor")
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("unable to dispense the executor plugin: %v", err)
|
|
}
|
|
executorPlugin, ok := raw.(Executor)
|
|
if !ok {
|
|
return nil, nil, fmt.Errorf("unexpected executor rpc type: %T", raw)
|
|
}
|
|
return executorPlugin, executorClient, nil
|
|
}
|
|
|
|
func processStateToProto(ps *ProcessState) (*proto.ProcessState, error) {
|
|
timestamp, err := ptypes.TimestampProto(ps.Time)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pb := &proto.ProcessState{
|
|
Pid: int32(ps.Pid),
|
|
ExitCode: int32(ps.ExitCode),
|
|
Signal: int32(ps.Signal),
|
|
Time: timestamp,
|
|
}
|
|
|
|
return pb, nil
|
|
}
|
|
|
|
func processStateFromProto(pb *proto.ProcessState) (*ProcessState, error) {
|
|
timestamp, err := ptypes.Timestamp(pb.Time)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ProcessState{
|
|
Pid: int(pb.Pid),
|
|
ExitCode: int(pb.ExitCode),
|
|
Signal: int(pb.Signal),
|
|
Time: timestamp,
|
|
}, nil
|
|
}
|
|
|
|
// IsolationMode returns the namespace isolation mode as determined from agent
|
|
// plugin configuration and task driver configuration. The task configuration
|
|
// takes precedence, if it is configured.
|
|
func IsolationMode(plugin, task string) string {
|
|
if task != "" {
|
|
return task
|
|
}
|
|
return plugin
|
|
}
|