Update runhcs-shim to use go-bindings
Signed-off-by: Justin Terry (VM) <juterry@microsoft.com>
This commit is contained in:
@@ -1,98 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package runhcs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os/exec"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
bytesBufferPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return bytes.NewBuffer(nil)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func getBuffer() *bytes.Buffer {
|
||||
return bytesBufferPool.Get().(*bytes.Buffer)
|
||||
}
|
||||
|
||||
func putBuffer(b *bytes.Buffer) {
|
||||
b.Reset()
|
||||
bytesBufferPool.Put(b)
|
||||
}
|
||||
|
||||
type processExit struct {
|
||||
pid uint32
|
||||
exitStatus uint32
|
||||
exitedAt time.Time
|
||||
exitErr error
|
||||
}
|
||||
|
||||
func runCmd(ctx context.Context, c *exec.Cmd) (*processExit, error) {
|
||||
ec, startErr := startCmd(ctx, c)
|
||||
if startErr != nil {
|
||||
return nil, startErr
|
||||
}
|
||||
er, cmdErr := waitCmd(ctx, ec)
|
||||
return er, cmdErr
|
||||
}
|
||||
|
||||
func startCmd(ctx context.Context, c *exec.Cmd) (<-chan *processExit, error) {
|
||||
if err := c.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ec := make(chan *processExit, 1)
|
||||
go func() {
|
||||
defer close(ec)
|
||||
|
||||
var status int
|
||||
eerr := c.Wait()
|
||||
if eerr != nil {
|
||||
status = 255
|
||||
if exitErr, ok := eerr.(*exec.ExitError); ok {
|
||||
if ws, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
status = ws.ExitStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
ec <- &processExit{
|
||||
pid: uint32(c.Process.Pid),
|
||||
exitStatus: uint32(status),
|
||||
exitedAt: time.Now(),
|
||||
exitErr: eerr,
|
||||
}
|
||||
}()
|
||||
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
func waitCmd(ctx context.Context, ec <-chan *processExit) (*processExit, error) {
|
||||
e := <-ec
|
||||
if e.exitStatus != 0 {
|
||||
return e, e.exitErr
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
@@ -31,6 +31,13 @@ import (
|
||||
"github.com/containerd/containerd/runtime"
|
||||
)
|
||||
|
||||
type processExit struct {
|
||||
pid uint32
|
||||
exitStatus uint32
|
||||
exitedAt time.Time
|
||||
exitErr error
|
||||
}
|
||||
|
||||
func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipeRelay, bundle, stdin, stdout, stderr string, terminal bool) (*process, error) {
|
||||
p, err := os.FindProcess(int(pid))
|
||||
if err != nil {
|
||||
|
||||
@@ -50,8 +50,7 @@ import (
|
||||
|
||||
const (
|
||||
runhcsBinary = "runhcs"
|
||||
runhcsVersion = "0.0.1"
|
||||
runhcsDebugLegacy = "--debug" // TODO: JTERRY75 remove when all cmd's are complete in go-runhcs
|
||||
runhcsShimVersion = "0.0.1"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -201,41 +200,9 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := exec.Command(runhcsBinary, runhcsDebugLegacy, "state", p.id)
|
||||
sout := getBuffer()
|
||||
defer putBuffer(sout)
|
||||
|
||||
cmd.Stdout = sout
|
||||
_, stateErr := runCmd(ctx, cmd)
|
||||
if stateErr != nil {
|
||||
return nil, stateErr
|
||||
}
|
||||
|
||||
// TODO: JTERRY75 merge this with runhcs declaration
|
||||
type containerState struct {
|
||||
// Version is the OCI version for the container
|
||||
Version string `json:"ociVersion"`
|
||||
// ID is the container ID
|
||||
ID string `json:"id"`
|
||||
// InitProcessPid is the init process id in the parent namespace
|
||||
InitProcessPid int `json:"pid"`
|
||||
// Status is the current status of the container, running, paused, ...
|
||||
Status string `json:"status"`
|
||||
// Bundle is the path on the filesystem to the bundle
|
||||
Bundle string `json:"bundle"`
|
||||
// Rootfs is a path to a directory containing the container's root filesystem.
|
||||
Rootfs string `json:"rootfs"`
|
||||
// Created is the unix timestamp for the creation time of the container in UTC
|
||||
Created time.Time `json:"created"`
|
||||
// Annotations is the user defined annotations added to the config.
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
// The owner of the state directory (the owner of the container).
|
||||
Owner string `json:"owner"`
|
||||
}
|
||||
|
||||
var cs containerState
|
||||
if err := json.NewDecoder(sout).Decode(&cs); err != nil {
|
||||
log.G(ctx).WithError(err).Debugf("failed to decode runhcs state output: %s", sout.Bytes())
|
||||
rhcs := newRunhcs(p.bundle)
|
||||
cs, err := rhcs.State(ctx, p.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -551,13 +518,14 @@ func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.Pi
|
||||
// Pause the container
|
||||
func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.Empty, error) {
|
||||
// TODO: Validate that 'id' is actually a valid parent container ID
|
||||
if _, err := s.getProcess(r.ID, ""); err != nil {
|
||||
var p *process
|
||||
var err error
|
||||
if p, err = s.getProcess(r.ID, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := exec.Command(runhcsBinary, runhcsDebugLegacy, "pause", r.ID)
|
||||
_, err := runCmd(ctx, cmd)
|
||||
if err != nil {
|
||||
rhcs := newRunhcs(p.bundle)
|
||||
if err = rhcs.Pause(ctx, p.id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -567,13 +535,14 @@ func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.E
|
||||
// Resume the container
|
||||
func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes.Empty, error) {
|
||||
// TODO: Validate that 'id' is actually a valid parent container ID
|
||||
if _, err := s.getProcess(r.ID, ""); err != nil {
|
||||
var p *process
|
||||
var err error
|
||||
if p, err = s.getProcess(r.ID, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := exec.Command(runhcsBinary, runhcsDebugLegacy, "resume", r.ID)
|
||||
_, err := runCmd(ctx, cmd)
|
||||
if err != nil {
|
||||
rhcs := newRunhcs(p.bundle)
|
||||
if err = rhcs.Resume(ctx, p.id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -599,7 +568,7 @@ func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Emp
|
||||
// TODO: JTERRY75 runhcs support for r.All?
|
||||
rhcs := newRunhcs(p.bundle)
|
||||
if err = rhcs.Kill(ctx, p.id, strconv.FormatUint(uint64(r.Signal), 10)); err != nil {
|
||||
if !strings.Contains(err.Error(), "container is not running") {
|
||||
if !strings.Contains(err.Error(), "container is stopped") {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -698,18 +667,12 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := exec.Command(
|
||||
runhcsBinary,
|
||||
runhcsDebugLegacy,
|
||||
"resize-tty",
|
||||
p.cid,
|
||||
"-p",
|
||||
strconv.FormatUint(uint64(p.pid), 10),
|
||||
strconv.FormatUint(uint64(r.Width), 10),
|
||||
strconv.FormatUint(uint64(r.Height), 10))
|
||||
|
||||
_, err = runCmd(ctx, cmd)
|
||||
if err != nil {
|
||||
pid := int(p.pid)
|
||||
opts := runhcs.ResizeTTYOpts{
|
||||
Pid: &pid,
|
||||
}
|
||||
rhcs := newRunhcs(p.bundle)
|
||||
if err = rhcs.ResizeTTY(ctx, p.cid, uint16(r.Width), uint16(r.Height), &opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -756,7 +719,7 @@ func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*task
|
||||
return &taskAPI.ConnectResponse{
|
||||
ShimPid: uint32(os.Getpid()),
|
||||
TaskPid: s.processes[s.id].pid,
|
||||
Version: runhcsVersion,
|
||||
Version: runhcsShimVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user