bundle.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // +build linux
  2. /*
  3. Copyright The containerd Authors.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. package linux
  15. import (
  16. "context"
  17. "io/ioutil"
  18. "os"
  19. "path/filepath"
  20. "github.com/containerd/containerd/events/exchange"
  21. "github.com/containerd/containerd/runtime/linux/runctypes"
  22. "github.com/containerd/containerd/runtime/v1/shim"
  23. "github.com/containerd/containerd/runtime/v1/shim/client"
  24. "github.com/pkg/errors"
  25. )
  26. // loadBundle loads an existing bundle from disk
  27. func loadBundle(id, path, workdir string) *bundle {
  28. return &bundle{
  29. id: id,
  30. path: path,
  31. workDir: workdir,
  32. }
  33. }
  34. // newBundle creates a new bundle on disk at the provided path for the given id
  35. func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
  36. if err := os.MkdirAll(path, 0711); err != nil {
  37. return nil, err
  38. }
  39. path = filepath.Join(path, id)
  40. if err := os.Mkdir(path, 0711); err != nil {
  41. return nil, err
  42. }
  43. defer func() {
  44. if err != nil {
  45. os.RemoveAll(path)
  46. }
  47. }()
  48. workDir = filepath.Join(workDir, id)
  49. if err := os.MkdirAll(workDir, 0711); err != nil {
  50. return nil, err
  51. }
  52. defer func() {
  53. if err != nil {
  54. os.RemoveAll(workDir)
  55. }
  56. }()
  57. if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil {
  58. return nil, err
  59. }
  60. err = ioutil.WriteFile(filepath.Join(path, configFilename), spec, 0666)
  61. return &bundle{
  62. id: id,
  63. path: path,
  64. workDir: workDir,
  65. }, err
  66. }
  67. type bundle struct {
  68. id string
  69. path string
  70. workDir string
  71. }
  72. // ShimOpt specifies shim options for initialization and connection
  73. type ShimOpt func(*bundle, string, *runctypes.RuncOptions) (shim.Config, client.Opt)
  74. // ShimRemote is a ShimOpt for connecting and starting a remote shim
  75. func ShimRemote(c *Config, daemonAddress, cgroup string, exitHandler func()) ShimOpt {
  76. return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
  77. config := b.shimConfig(ns, c, ropts)
  78. return config,
  79. client.WithStart(c.Shim, b.shimAddress(ns), daemonAddress, cgroup, c.ShimDebug, exitHandler)
  80. }
  81. }
  82. // ShimLocal is a ShimOpt for using an in process shim implementation
  83. func ShimLocal(c *Config, exchange *exchange.Exchange) ShimOpt {
  84. return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
  85. return b.shimConfig(ns, c, ropts), client.WithLocal(exchange)
  86. }
  87. }
  88. // ShimConnect is a ShimOpt for connecting to an existing remote shim
  89. func ShimConnect(c *Config, onClose func()) ShimOpt {
  90. return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
  91. return b.shimConfig(ns, c, ropts), client.WithConnect(b.shimAddress(ns), onClose)
  92. }
  93. }
  94. // NewShimClient connects to the shim managing the bundle and tasks creating it if needed
  95. func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientOpts ShimOpt, runcOpts *runctypes.RuncOptions) (*client.Client, error) {
  96. cfg, opt := getClientOpts(b, namespace, runcOpts)
  97. return client.New(ctx, cfg, opt)
  98. }
  99. // Delete deletes the bundle from disk
  100. func (b *bundle) Delete() error {
  101. err := os.RemoveAll(b.path)
  102. if err == nil {
  103. return os.RemoveAll(b.workDir)
  104. }
  105. // error removing the bundle path; still attempt removing work dir
  106. err2 := os.RemoveAll(b.workDir)
  107. if err2 == nil {
  108. return err
  109. }
  110. return errors.Wrapf(err, "Failed to remove both bundle and workdir locations: %v", err2)
  111. }
  112. func (b *bundle) shimAddress(namespace string) string {
  113. return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock")
  114. }
  115. func (b *bundle) shimConfig(namespace string, c *Config, runcOptions *runctypes.RuncOptions) shim.Config {
  116. var (
  117. criuPath string
  118. runtimeRoot = c.RuntimeRoot
  119. systemdCgroup bool
  120. )
  121. if runcOptions != nil {
  122. criuPath = runcOptions.CriuPath
  123. systemdCgroup = runcOptions.SystemdCgroup
  124. if runcOptions.RuntimeRoot != "" {
  125. runtimeRoot = runcOptions.RuntimeRoot
  126. }
  127. }
  128. return shim.Config{
  129. Path: b.path,
  130. WorkDir: b.workDir,
  131. Namespace: namespace,
  132. Criu: criuPath,
  133. RuntimeRoot: runtimeRoot,
  134. SystemdCgroup: systemdCgroup,
  135. }
  136. }