mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 02:15:43 +03:00
Switch java/exec to use Exec in Executor
This commit is contained in:
@@ -195,7 +195,6 @@ func (r *AllocRunner) RestoreState() error {
|
||||
|
||||
// Restart task runner if RestoreState gave a reason
|
||||
if restartReason != "" {
|
||||
r.logger.Printf("[INFO] client: restarting alloc %s task %q due to upgrade: %s", r.alloc.ID, name, restartReason)
|
||||
tr.Restart("upgrade", restartReason)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,12 @@ func (h *execHandle) Update(task *structs.Task) error {
|
||||
}
|
||||
|
||||
func (h *execHandle) Exec(ctx context.Context, cmd string, args []string) ([]byte, int, error) {
|
||||
return execChroot(ctx, h.taskDir.Dir, cmd, args)
|
||||
deadline, ok := ctx.Deadline()
|
||||
if !ok {
|
||||
// No deadline set on context; default to 1 minute
|
||||
deadline = time.Now().Add(time.Minute)
|
||||
}
|
||||
return h.executor.Exec(deadline, cmd, args)
|
||||
}
|
||||
|
||||
func (h *execHandle) Signal(s os.Signal) error {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/armon/circbuf"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/go-ps"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
@@ -57,6 +59,7 @@ type Executor interface {
|
||||
Version() (*ExecutorVersion, error)
|
||||
Stats() (*cstructs.TaskResourceUsage, error)
|
||||
Signal(s os.Signal) error
|
||||
Exec(deadline time.Time, cmd string, args []string) ([]byte, int, error)
|
||||
}
|
||||
|
||||
// ExecutorContext holds context to configure the command user
|
||||
@@ -203,8 +206,8 @@ func (e *UniversalExecutor) SetContext(ctx *ExecutorContext) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LaunchCmd launches a process and returns it's state. It also configures an
|
||||
// applies isolation on certain platforms.
|
||||
// LaunchCmd launches the main process and returns its state. It also
|
||||
// configures an applies isolation on certain platforms.
|
||||
func (e *UniversalExecutor) LaunchCmd(command *ExecCommand) (*ProcessState, error) {
|
||||
e.logger.Printf("[DEBUG] executor: launching command %v %v", command.Cmd, strings.Join(command.Args, " "))
|
||||
|
||||
@@ -283,6 +286,45 @@ func (e *UniversalExecutor) LaunchCmd(command *ExecCommand) (*ProcessState, erro
|
||||
return &ProcessState{Pid: e.cmd.Process.Pid, ExitCode: -1, IsolationConfig: ic, Time: time.Now()}, nil
|
||||
}
|
||||
|
||||
// Exec a command inside a container for exec and java drivers.
|
||||
func (e *UniversalExecutor) Exec(deadline time.Time, name string, args []string) ([]byte, int, error) {
|
||||
ctx, cancel := context.WithDeadline(context.Background(), deadline)
|
||||
defer cancel()
|
||||
|
||||
name = e.ctx.TaskEnv.ReplaceEnv(name)
|
||||
cmd := exec.CommandContext(ctx, name, e.ctx.TaskEnv.ParseAndReplace(args)...)
|
||||
|
||||
// Copy runtime environment from the main command
|
||||
cmd.SysProcAttr = e.cmd.SysProcAttr
|
||||
cmd.Dir = e.cmd.Dir
|
||||
cmd.Env = e.ctx.TaskEnv.EnvList()
|
||||
|
||||
// Capture output
|
||||
buf, _ := circbuf.NewBuffer(int64(dstructs.CheckBufSize))
|
||||
cmd.Stdout = buf
|
||||
cmd.Stderr = buf
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
exitErr, ok := err.(*exec.ExitError)
|
||||
if !ok {
|
||||
// Non-exit error, return it and let the caller treat
|
||||
// it as a critical failure
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Some kind of error happened; default to critical
|
||||
exitCode := 2
|
||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
exitCode = status.ExitStatus()
|
||||
}
|
||||
|
||||
// Don't return the exitError as the caller only needs the
|
||||
// output and code.
|
||||
return buf.Bytes(), exitCode, nil
|
||||
}
|
||||
return buf.Bytes(), 0, nil
|
||||
}
|
||||
|
||||
// configureLoggers sets up the standard out/error file rotators
|
||||
func (e *UniversalExecutor) configureLoggers() error {
|
||||
e.rotatorLock.Lock()
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/rpc"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/nomad/client/driver/executor"
|
||||
@@ -33,6 +34,17 @@ type LaunchCmdArgs struct {
|
||||
Cmd *executor.ExecCommand
|
||||
}
|
||||
|
||||
type ExecCmdArgs struct {
|
||||
Deadline time.Time
|
||||
Name string
|
||||
Args []string
|
||||
}
|
||||
|
||||
type ExecCmdReturn struct {
|
||||
Output []byte
|
||||
Code int
|
||||
}
|
||||
|
||||
func (e *ExecutorRPC) LaunchCmd(cmd *executor.ExecCommand) (*executor.ProcessState, error) {
|
||||
var ps *executor.ProcessState
|
||||
err := e.client.Call("Plugin.LaunchCmd", LaunchCmdArgs{Cmd: cmd}, &ps)
|
||||
@@ -91,6 +103,20 @@ func (e *ExecutorRPC) Signal(s os.Signal) error {
|
||||
return e.client.Call("Plugin.Signal", &s, new(interface{}))
|
||||
}
|
||||
|
||||
func (e *ExecutorRPC) Exec(deadline time.Time, name string, args []string) ([]byte, int, error) {
|
||||
req := ExecCmdArgs{
|
||||
Deadline: deadline,
|
||||
Name: name,
|
||||
Args: args,
|
||||
}
|
||||
var resp *ExecCmdReturn
|
||||
err := e.client.Call("Plugin.Exec", req, &resp)
|
||||
if resp == nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return resp.Output, resp.Code, err
|
||||
}
|
||||
|
||||
type ExecutorRPCServer struct {
|
||||
Impl executor.Executor
|
||||
logger *log.Logger
|
||||
@@ -165,6 +191,16 @@ func (e *ExecutorRPCServer) Signal(args os.Signal, resp *interface{}) error {
|
||||
return e.Impl.Signal(args)
|
||||
}
|
||||
|
||||
func (e *ExecutorRPCServer) Exec(args ExecCmdArgs, result *ExecCmdReturn) error {
|
||||
out, code, err := e.Impl.Exec(args.Deadline, args.Name, args.Args)
|
||||
ret := &ExecCmdReturn{
|
||||
Output: out,
|
||||
Code: code,
|
||||
}
|
||||
*result = *ret
|
||||
return err
|
||||
}
|
||||
|
||||
type ExecutorPlugin struct {
|
||||
logger *log.Logger
|
||||
Impl *ExecutorRPCServer
|
||||
|
||||
@@ -390,7 +390,12 @@ func (h *javaHandle) Update(task *structs.Task) error {
|
||||
}
|
||||
|
||||
func (h *javaHandle) Exec(ctx context.Context, cmd string, args []string) ([]byte, int, error) {
|
||||
return execChroot(ctx, h.taskDir, cmd, args)
|
||||
deadline, ok := ctx.Deadline()
|
||||
if !ok {
|
||||
// No deadline set on context; default to 1 minute
|
||||
deadline = time.Now().Add(time.Minute)
|
||||
}
|
||||
return h.executor.Exec(deadline, cmd, args)
|
||||
}
|
||||
|
||||
func (h *javaHandle) Signal(s os.Signal) error {
|
||||
|
||||
@@ -297,7 +297,7 @@ func (r *TaskRunner) RestoreState() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if pre06ScriptCheck(snap.Version, r.task.Services) {
|
||||
if pre06ScriptCheck(snap.Version, r.task.Driver, r.task.Services) {
|
||||
restartReason = "upgrading pre-0.6 script checks"
|
||||
}
|
||||
|
||||
@@ -323,7 +323,11 @@ func (r *TaskRunner) RestoreState() (string, error) {
|
||||
var ver06 = version.Must(version.NewVersion("0.6.0dev"))
|
||||
|
||||
// pre06ScriptCheck returns true if version is prior to 0.6.0dev.
|
||||
func pre06ScriptCheck(ver string, services []*structs.Service) bool {
|
||||
func pre06ScriptCheck(ver, driver string, services []*structs.Service) bool {
|
||||
if driver != "exec" && driver != "java" {
|
||||
// Only exec and java are affected
|
||||
return false
|
||||
}
|
||||
v, err := version.NewVersion(ver)
|
||||
if err != nil {
|
||||
// Treat it as old
|
||||
|
||||
Reference in New Issue
Block a user