| // +build linux |
| |
| package linux |
| |
| import ( |
| "bytes" |
| "context" |
| "io" |
| "os" |
| "path/filepath" |
| |
| "github.com/containerd/containerd/events/exchange" |
| "github.com/containerd/containerd/linux/runctypes" |
| "github.com/containerd/containerd/linux/shim" |
| "github.com/containerd/containerd/linux/shim/client" |
| "github.com/pkg/errors" |
| ) |
| |
| // loadBundle loads an existing bundle from disk |
| func loadBundle(id, path, workdir string) *bundle { |
| return &bundle{ |
| id: id, |
| path: path, |
| workDir: workdir, |
| } |
| } |
| |
| // newBundle creates a new bundle on disk at the provided path for the given id |
| func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) { |
| if err := os.MkdirAll(path, 0711); err != nil { |
| return nil, err |
| } |
| path = filepath.Join(path, id) |
| defer func() { |
| if err != nil { |
| os.RemoveAll(path) |
| } |
| }() |
| workDir = filepath.Join(workDir, id) |
| if err := os.MkdirAll(workDir, 0711); err != nil { |
| return nil, err |
| } |
| defer func() { |
| if err != nil { |
| os.RemoveAll(workDir) |
| } |
| }() |
| |
| if err := os.Mkdir(path, 0711); err != nil { |
| return nil, err |
| } |
| if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil { |
| return nil, err |
| } |
| f, err := os.Create(filepath.Join(path, configFilename)) |
| if err != nil { |
| return nil, err |
| } |
| defer f.Close() |
| _, err = io.Copy(f, bytes.NewReader(spec)) |
| return &bundle{ |
| id: id, |
| path: path, |
| workDir: workDir, |
| }, err |
| } |
| |
| type bundle struct { |
| id string |
| path string |
| workDir string |
| } |
| |
| // ShimOpt specifies shim options for initialization and connection |
| type ShimOpt func(*bundle, string, *runctypes.RuncOptions) (shim.Config, client.Opt) |
| |
| // ShimRemote is a ShimOpt for connecting and starting a remote shim |
| func ShimRemote(shimBinary, daemonAddress, cgroup string, nonewns, debug bool, exitHandler func()) ShimOpt { |
| return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) { |
| return b.shimConfig(ns, ropts), |
| client.WithStart(shimBinary, b.shimAddress(ns), daemonAddress, cgroup, nonewns, debug, exitHandler) |
| } |
| } |
| |
| // ShimLocal is a ShimOpt for using an in process shim implementation |
| func ShimLocal(exchange *exchange.Exchange) ShimOpt { |
| return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) { |
| return b.shimConfig(ns, ropts), client.WithLocal(exchange) |
| } |
| } |
| |
| // ShimConnect is a ShimOpt for connecting to an existing remote shim |
| func ShimConnect() ShimOpt { |
| return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) { |
| return b.shimConfig(ns, ropts), client.WithConnect(b.shimAddress(ns)) |
| } |
| } |
| |
| // NewShimClient connects to the shim managing the bundle and tasks creating it if needed |
| func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientOpts ShimOpt, runcOpts *runctypes.RuncOptions) (*client.Client, error) { |
| cfg, opt := getClientOpts(b, namespace, runcOpts) |
| return client.New(ctx, cfg, opt) |
| } |
| |
| // Delete deletes the bundle from disk |
| func (b *bundle) Delete() error { |
| err := os.RemoveAll(b.path) |
| if err == nil { |
| return os.RemoveAll(b.workDir) |
| } |
| // error removing the bundle path; still attempt removing work dir |
| err2 := os.RemoveAll(b.workDir) |
| if err2 == nil { |
| return err |
| } |
| return errors.Wrapf(err, "Failed to remove both bundle and workdir locations: %v", err2) |
| } |
| |
| func (b *bundle) shimAddress(namespace string) string { |
| return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock") |
| } |
| |
| func (b *bundle) shimConfig(namespace string, runcOptions *runctypes.RuncOptions) shim.Config { |
| var ( |
| criuPath string |
| runtimeRoot string |
| systemdCgroup bool |
| ) |
| if runcOptions != nil { |
| criuPath = runcOptions.CriuPath |
| systemdCgroup = runcOptions.SystemdCgroup |
| runtimeRoot = runcOptions.RuntimeRoot |
| } |
| return shim.Config{ |
| Path: b.path, |
| WorkDir: b.workDir, |
| Namespace: namespace, |
| Criu: criuPath, |
| RuntimeRoot: runtimeRoot, |
| SystemdCgroup: systemdCgroup, |
| } |
| } |