linux: Bubble up runc error message
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
parent
33598cc5d3
commit
5922cfaba8
@ -86,7 +86,7 @@ func newExecProcess(context context.Context, path string, r *shimapi.ExecRequest
|
||||
spec.Terminal = r.Terminal
|
||||
|
||||
if err := parent.runc.Exec(context, parent.id, spec, opts); err != nil {
|
||||
return nil, err
|
||||
return nil, parent.runcError(err, "runc exec failed")
|
||||
}
|
||||
if r.Stdin != "" {
|
||||
sc, err := fifo.OpenFifo(context, r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0)
|
||||
|
@ -4,6 +4,7 @@ package shim
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -109,7 +110,7 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi.
|
||||
NoSubreaper: true,
|
||||
}
|
||||
if _, err := p.runc.Restore(context, r.ID, r.Bundle, opts); err != nil {
|
||||
return nil, err
|
||||
return nil, p.runcError(err, "runc restore failed")
|
||||
}
|
||||
} else {
|
||||
opts := &runc.CreateOpts{
|
||||
@ -121,7 +122,7 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi.
|
||||
opts.ConsoleSocket = socket
|
||||
}
|
||||
if err := p.runc.Create(context, r.ID, r.Bundle, opts); err != nil {
|
||||
return nil, err
|
||||
return nil, p.runcError(err, "runc create failed")
|
||||
}
|
||||
}
|
||||
if r.Stdin != "" {
|
||||
@ -173,7 +174,7 @@ func (p *initProcess) ExitedAt() time.Time {
|
||||
func (p *initProcess) ContainerStatus(ctx context.Context) (string, error) {
|
||||
c, err := p.runc.State(ctx, p.id)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", p.runcError(err, "runc state failed")
|
||||
}
|
||||
return c.Status, nil
|
||||
}
|
||||
@ -181,7 +182,8 @@ func (p *initProcess) ContainerStatus(ctx context.Context) (string, error) {
|
||||
func (p *initProcess) Start(context context.Context) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
return p.runc.Start(context, p.id)
|
||||
err := p.runc.Start(context, p.id)
|
||||
return p.runcError(err, "runc start failed")
|
||||
}
|
||||
|
||||
func (p *initProcess) Exited(status int) {
|
||||
@ -208,7 +210,7 @@ func (p *initProcess) Delete(context context.Context) error {
|
||||
}
|
||||
p.io.Close()
|
||||
}
|
||||
return err
|
||||
return p.runcError(err, "runc delete failed")
|
||||
}
|
||||
|
||||
func (p *initProcess) Resize(ws console.WinSize) error {
|
||||
@ -219,23 +221,27 @@ func (p *initProcess) Resize(ws console.WinSize) error {
|
||||
}
|
||||
|
||||
func (p *initProcess) Pause(context context.Context) error {
|
||||
return p.runc.Pause(context, p.id)
|
||||
err := p.runc.Pause(context, p.id)
|
||||
return p.runcError(err, "runc pause failed")
|
||||
}
|
||||
|
||||
func (p *initProcess) Resume(context context.Context) error {
|
||||
return p.runc.Resume(context, p.id)
|
||||
err := p.runc.Resume(context, p.id)
|
||||
return p.runcError(err, "runc resume failed")
|
||||
}
|
||||
|
||||
func (p *initProcess) Kill(context context.Context, signal uint32, all bool) error {
|
||||
return p.runc.Kill(context, p.id, int(signal), &runc.KillOpts{
|
||||
err := p.runc.Kill(context, p.id, int(signal), &runc.KillOpts{
|
||||
All: all,
|
||||
})
|
||||
return p.runcError(err, "runc kill failed")
|
||||
}
|
||||
|
||||
func (p *initProcess) killAll(context context.Context) error {
|
||||
return p.runc.Kill(context, p.id, int(syscall.SIGKILL), &runc.KillOpts{
|
||||
err := p.runc.Kill(context, p.id, int(syscall.SIGKILL), &runc.KillOpts{
|
||||
All: true,
|
||||
})
|
||||
return p.runcError(err, "runc killall failed")
|
||||
}
|
||||
|
||||
func (p *initProcess) Signal(sig int) error {
|
||||
@ -271,6 +277,55 @@ func (p *initProcess) Checkpoint(context context.Context, r *shimapi.CheckpointR
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(mlaventure): move to runc package?
|
||||
func getLastRuncError(r *runc.Runc) (string, error) {
|
||||
if r.Log == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(r.Log, os.O_RDONLY, 0400)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var (
|
||||
errMsg string
|
||||
log struct {
|
||||
Level string
|
||||
Msg string
|
||||
Time time.Time
|
||||
}
|
||||
)
|
||||
|
||||
dec := json.NewDecoder(f)
|
||||
for err = nil; err == nil; {
|
||||
if err = dec.Decode(&log); err != nil && err != io.EOF {
|
||||
return "", err
|
||||
}
|
||||
if log.Level == "error" {
|
||||
errMsg = strings.TrimSpace(log.Msg)
|
||||
}
|
||||
}
|
||||
|
||||
return errMsg, nil
|
||||
}
|
||||
|
||||
func (p *initProcess) runcError(rErr error, msg string) error {
|
||||
if rErr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
rMsg, err := getLastRuncError(p.runc)
|
||||
switch {
|
||||
case err != nil:
|
||||
return errors.Wrapf(err, "%s: %s (%s)", msg, "unable to retrieve runc error", err.Error())
|
||||
case rMsg == "":
|
||||
return errors.Wrap(err, msg)
|
||||
default:
|
||||
return errors.Errorf("%s: %s", msg, rMsg)
|
||||
}
|
||||
}
|
||||
|
||||
// criuError returns only the first line of the error message from criu
|
||||
// it tries to add an invalid dump log location when returning the message
|
||||
func criuError(err error) string {
|
||||
|
Loading…
Reference in New Issue
Block a user