containerd/linux/shim.go
Stephen J Day 12a6beaeeb
*: update import paths to use versioned services
Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-06-21 18:29:06 -07:00

91 lines
2.6 KiB
Go

// +build linux
package linux
import (
"context"
"fmt"
"net"
"os/exec"
"path/filepath"
"syscall"
"time"
"google.golang.org/grpc"
"github.com/containerd/containerd/api/services/shim/v1"
localShim "github.com/containerd/containerd/linux/shim"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/reaper"
"github.com/containerd/containerd/sys"
"github.com/pkg/errors"
)
func newShim(ctx context.Context, shimName string, path, namespace string, remote bool) (shim.ShimClient, error) {
if !remote {
return localShim.Client(path, namespace)
}
socket := filepath.Join(path, "shim.sock")
l, err := sys.CreateUnixSocket(socket)
if err != nil {
return nil, err
}
cmd := exec.Command(shimName, "--namespace", namespace)
cmd.Dir = path
f, err := l.(*net.UnixListener).File()
if err != nil {
return nil, err
}
// close our side of the socket, do not close the listener as it will
// remove the socket from disk
defer f.Close()
cmd.ExtraFiles = append(cmd.ExtraFiles, f)
// make sure the shim can be re-parented to system init
// and is cloned in a new mount namespace because the overlay/filesystems
// will be mounted by the shim
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWNS,
Setpgid: true,
}
if err := reaper.Default.Start(cmd); err != nil {
return nil, errors.Wrapf(err, "failed to start shim")
}
defer func() {
if err != nil {
cmd.Process.Kill()
reaper.Default.Wait(cmd)
} else {
log.G(ctx).WithField("socket", socket).Infof("new shim started")
}
}()
if err = sys.SetOOMScore(cmd.Process.Pid, sys.OOMScoreMaxKillable); err != nil {
return nil, errors.Wrap(err, "failed to set OOM Score on shim")
}
return connectShim(socket)
}
func loadShim(path, namespace string, remote bool) (shim.ShimClient, error) {
if !remote {
return localShim.Client(path, namespace)
}
socket := filepath.Join(path, "shim.sock")
return connectShim(socket)
}
func connectShim(socket string) (shim.ShimClient, error) {
// reset the logger for grpc to log to dev/null so that it does not mess with our stdio
dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(100 * time.Second)}
dialOpts = append(dialOpts,
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", socket, timeout)
}),
grpc.WithBlock(),
grpc.WithTimeout(2*time.Second),
)
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", socket), dialOpts...)
if err != nil {
return nil, errors.Wrapf(err, "failed to connect to shim via \"%s\"", fmt.Sprintf("unix://%s", socket))
}
return shim.NewShimClient(conn), nil
}