manager_linux.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // +build linux,experimental
  2. package plugin
  3. import (
  4. "os"
  5. "path/filepath"
  6. "syscall"
  7. "github.com/Sirupsen/logrus"
  8. "github.com/docker/docker/libcontainerd"
  9. "github.com/docker/docker/oci"
  10. "github.com/docker/docker/pkg/plugins"
  11. "github.com/docker/docker/pkg/system"
  12. "github.com/docker/docker/restartmanager"
  13. "github.com/docker/engine-api/types"
  14. "github.com/docker/engine-api/types/container"
  15. "github.com/opencontainers/specs/specs-go"
  16. )
  17. func (pm *Manager) enable(p *plugin) error {
  18. spec, err := pm.initSpec(p)
  19. if err != nil {
  20. return err
  21. }
  22. p.restartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0)
  23. if err := pm.containerdClient.Create(p.P.ID, libcontainerd.Spec(*spec), libcontainerd.WithRestartManager(p.restartManager)); err != nil { // POC-only
  24. return err
  25. }
  26. socket := p.P.Manifest.Interface.Socket
  27. p.client, err = plugins.NewClient("unix://"+filepath.Join(p.runtimeSourcePath, socket), nil)
  28. if err != nil {
  29. return err
  30. }
  31. //TODO: check net.Dial
  32. pm.Lock() // fixme: lock single record
  33. p.P.Active = true
  34. pm.save()
  35. pm.Unlock()
  36. for _, typ := range p.P.Manifest.Interface.Types {
  37. if handler := pm.handlers[typ.String()]; handler != nil {
  38. handler(p.Name(), p.Client())
  39. }
  40. }
  41. return nil
  42. }
  43. func (pm *Manager) restore(p *plugin) error {
  44. p.restartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0)
  45. return pm.containerdClient.Restore(p.P.ID, libcontainerd.WithRestartManager(p.restartManager))
  46. }
  47. func (pm *Manager) initSpec(p *plugin) (*specs.Spec, error) {
  48. s := oci.DefaultSpec()
  49. rootfs := filepath.Join(pm.libRoot, p.P.ID, "rootfs")
  50. s.Root = specs.Root{
  51. Path: rootfs,
  52. Readonly: false, // TODO: all plugins should be readonly? settable in manifest?
  53. }
  54. mounts := append(p.P.Config.Mounts, types.PluginMount{
  55. Source: &p.runtimeSourcePath,
  56. Destination: defaultPluginRuntimeDestination,
  57. Type: "bind",
  58. Options: []string{"rbind", "rshared"},
  59. }, types.PluginMount{
  60. Source: &p.stateSourcePath,
  61. Destination: defaultPluginStateDestination,
  62. Type: "bind",
  63. Options: []string{"rbind", "rshared"},
  64. })
  65. for _, mount := range mounts {
  66. m := specs.Mount{
  67. Destination: mount.Destination,
  68. Type: mount.Type,
  69. Options: mount.Options,
  70. }
  71. // TODO: if nil, then it's required and user didn't set it
  72. if mount.Source != nil {
  73. m.Source = *mount.Source
  74. }
  75. if m.Source != "" && m.Type == "bind" {
  76. fi, err := os.Lstat(filepath.Join(rootfs, string(os.PathSeparator), m.Destination)) // TODO: followsymlinks
  77. if err != nil {
  78. return nil, err
  79. }
  80. if fi.IsDir() {
  81. if err := os.MkdirAll(m.Source, 0700); err != nil {
  82. return nil, err
  83. }
  84. }
  85. }
  86. s.Mounts = append(s.Mounts, m)
  87. }
  88. envs := make([]string, 1, len(p.P.Config.Env)+1)
  89. envs[0] = "PATH=" + system.DefaultPathEnv
  90. envs = append(envs, p.P.Config.Env...)
  91. args := append(p.P.Manifest.Entrypoint, p.P.Config.Args...)
  92. s.Process = specs.Process{
  93. Terminal: false,
  94. Args: args,
  95. Cwd: "/", // TODO: add in manifest?
  96. Env: envs,
  97. }
  98. return &s, nil
  99. }
  100. func (pm *Manager) disable(p *plugin) error {
  101. if err := p.restartManager.Cancel(); err != nil {
  102. logrus.Error(err)
  103. }
  104. if err := pm.containerdClient.Signal(p.P.ID, int(syscall.SIGKILL)); err != nil {
  105. logrus.Error(err)
  106. }
  107. os.RemoveAll(p.runtimeSourcePath)
  108. pm.Lock() // fixme: lock single record
  109. defer pm.Unlock()
  110. p.P.Active = false
  111. pm.save()
  112. return nil
  113. }