From 13f64b4e66f9040e90c8867c00ab0800585df446 Mon Sep 17 00:00:00 2001 From: Kathryn Baldauf Date: Tue, 27 Oct 2020 13:57:08 -0700 Subject: [PATCH] Add new diag function to exec a command on the host system Signed-off-by: Kathryn Baldauf --- cmd/containerd-shim-runhcs-v1/task.go | 3 +++ cmd/containerd-shim-runhcs-v1/task_hcs.go | 4 ++-- .../task_wcow_podsandbox.go | 4 ++-- internal/cmd/diag.go | 24 +++++++++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/cmd/containerd-shim-runhcs-v1/task.go b/cmd/containerd-shim-runhcs-v1/task.go index 0d6070460e..29b309c266 100644 --- a/cmd/containerd-shim-runhcs-v1/task.go +++ b/cmd/containerd-shim-runhcs-v1/task.go @@ -2,6 +2,7 @@ package main import ( "context" + "errors" "time" "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" @@ -11,6 +12,8 @@ import ( specs "github.com/opencontainers/runtime-spec/specs-go" ) +var errTaskNotIsolated = errors.New("task is not isolated") + // shimTaskPidPair groups a process pid to its execID if it was user generated. type shimTaskPidPair struct { // Pid is the pid of the container process. diff --git a/cmd/containerd-shim-runhcs-v1/task_hcs.go b/cmd/containerd-shim-runhcs-v1/task_hcs.go index c3e3810360..825864eeea 100644 --- a/cmd/containerd-shim-runhcs-v1/task_hcs.go +++ b/cmd/containerd-shim-runhcs-v1/task_hcs.go @@ -594,7 +594,7 @@ func (ht *hcsTask) closeHost(ctx context.Context) { func (ht *hcsTask) ExecInHost(ctx context.Context, req *shimdiag.ExecProcessRequest) (int, error) { if ht.host == nil { - return 0, errors.New("task is not isolated") + return cmd.ExecInShimHost(ctx, req) } return cmd.ExecInUvm(ctx, ht.host, req) } @@ -613,7 +613,7 @@ func (ht *hcsTask) DumpGuestStacks(ctx context.Context) string { func (ht *hcsTask) Share(ctx context.Context, req *shimdiag.ShareRequest) error { if ht.host == nil { - return errors.New("task is not isolated") + return errTaskNotIsolated } // For hyper-v isolated WCOW the task used isn't the standard hcsTask so we // only have to deal with the LCOW case here. diff --git a/cmd/containerd-shim-runhcs-v1/task_wcow_podsandbox.go b/cmd/containerd-shim-runhcs-v1/task_wcow_podsandbox.go index 238e964f35..f00934eda7 100644 --- a/cmd/containerd-shim-runhcs-v1/task_wcow_podsandbox.go +++ b/cmd/containerd-shim-runhcs-v1/task_wcow_podsandbox.go @@ -222,7 +222,7 @@ func (wpst *wcowPodSandboxTask) waitParentExit() { func (wpst *wcowPodSandboxTask) ExecInHost(ctx context.Context, req *shimdiag.ExecProcessRequest) (int, error) { if wpst.host == nil { - return 0, errors.New("task is not isolated") + return 0, errTaskNotIsolated } return cmd.ExecInUvm(ctx, wpst.host, req) } @@ -241,7 +241,7 @@ func (wpst *wcowPodSandboxTask) DumpGuestStacks(ctx context.Context) string { func (wpst *wcowPodSandboxTask) Share(ctx context.Context, req *shimdiag.ShareRequest) error { if wpst.host == nil { - return errors.New("task is not isolated") + return errTaskNotIsolated } options := wpst.host.DefaultVSMBOptions(req.ReadOnly) _, err := wpst.host.AddVSMB(ctx, req.HostPath, options) diff --git a/internal/cmd/diag.go b/internal/cmd/diag.go index 30fa18a7de..cbe9595842 100644 --- a/internal/cmd/diag.go +++ b/internal/cmd/diag.go @@ -3,13 +3,16 @@ package cmd import ( "context" "errors" + "os/exec" "github.com/Microsoft/hcsshim/internal/log" "github.com/Microsoft/hcsshim/internal/logfields" "github.com/Microsoft/hcsshim/internal/shimdiag" "github.com/Microsoft/hcsshim/internal/uvm" + errorspkg "github.com/pkg/errors" ) +// ExecInUvm is a helper function used to execute commands specified in `req` inside the given UVM. func ExecInUvm(ctx context.Context, vm *uvm.UtilityVM, req *shimdiag.ExecProcessRequest) (int, error) { if len(req.Args) == 0 { return 0, errors.New("missing command") @@ -34,3 +37,24 @@ func ExecInUvm(ctx context.Context, vm *uvm.UtilityVM, req *shimdiag.ExecProcess err = cmd.Run() return cmd.ExitState.ExitCode(), err } + +// ExecInShimHost is a helper function used to execute commands specified in `req` in the shim's +// hosting system. +func ExecInShimHost(ctx context.Context, req *shimdiag.ExecProcessRequest) (int, error) { + if len(req.Args) == 0 { + return 0, errors.New("missing command") + } + cmdArgsWithoutName := []string{""} + if len(req.Args) > 1 { + cmdArgsWithoutName = req.Args[1:] + } + cmd := exec.Command(req.Args[0], cmdArgsWithoutName...) + output, err := cmd.CombinedOutput() + if err != nil { + if exiterr, ok := err.(*exec.ExitError); ok { + return exiterr.ExitCode(), errorspkg.Wrapf(exiterr, "command output: %v", string(output)) + } + return -1, errorspkg.Wrapf(err, "command output: %v", string(output)) + } + return 0, nil +}