manager_linux.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // +build linux
  2. package plugin
  3. import (
  4. "fmt"
  5. "path/filepath"
  6. "syscall"
  7. "time"
  8. "github.com/Sirupsen/logrus"
  9. "github.com/docker/docker/libcontainerd"
  10. "github.com/docker/docker/oci"
  11. "github.com/docker/docker/pkg/plugins"
  12. "github.com/docker/docker/plugin/v2"
  13. specs "github.com/opencontainers/runtime-spec/specs-go"
  14. )
  15. func (pm *Manager) enable(p *v2.Plugin, force bool) error {
  16. if p.IsEnabled() && !force {
  17. return fmt.Errorf("plugin %s is already enabled", p.Name())
  18. }
  19. spec, err := p.InitSpec(oci.DefaultSpec(), pm.libRoot)
  20. if err != nil {
  21. return err
  22. }
  23. p.Lock()
  24. p.Restart = true
  25. p.ExitChan = make(chan bool)
  26. p.Unlock()
  27. if err := pm.containerdClient.Create(p.GetID(), "", "", specs.Spec(*spec), attachToLog(p.GetID())); err != nil {
  28. return err
  29. }
  30. p.PClient, err = plugins.NewClientWithTimeout("unix://"+filepath.Join(p.RuntimeSourcePath, p.GetSocket()), nil, p.TimeoutInSecs)
  31. if err != nil {
  32. p.Lock()
  33. p.Restart = false
  34. p.Unlock()
  35. shutdownPlugin(p, pm.containerdClient)
  36. return err
  37. }
  38. pm.pluginStore.SetState(p, true)
  39. pm.pluginStore.CallHandler(p)
  40. return nil
  41. }
  42. func (pm *Manager) restore(p *v2.Plugin) error {
  43. return pm.containerdClient.Restore(p.GetID(), attachToLog(p.GetID()))
  44. }
  45. func shutdownPlugin(p *v2.Plugin, containerdClient libcontainerd.Client) {
  46. pluginID := p.GetID()
  47. err := containerdClient.Signal(pluginID, int(syscall.SIGTERM))
  48. if err != nil {
  49. logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
  50. } else {
  51. select {
  52. case <-p.ExitChan:
  53. logrus.Debug("Clean shutdown of plugin")
  54. case <-time.After(time.Second * 10):
  55. logrus.Debug("Force shutdown plugin")
  56. if err := containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
  57. logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
  58. }
  59. }
  60. }
  61. }
  62. func (pm *Manager) disable(p *v2.Plugin) error {
  63. if !p.IsEnabled() {
  64. return fmt.Errorf("plugin %s is already disabled", p.Name())
  65. }
  66. p.Lock()
  67. p.Restart = false
  68. p.Unlock()
  69. shutdownPlugin(p, pm.containerdClient)
  70. pm.pluginStore.SetState(p, false)
  71. return nil
  72. }
  73. // Shutdown stops all plugins and called during daemon shutdown.
  74. func (pm *Manager) Shutdown() {
  75. plugins := pm.pluginStore.GetAll()
  76. for _, p := range plugins {
  77. if pm.liveRestore && p.IsEnabled() {
  78. logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
  79. continue
  80. }
  81. if pm.containerdClient != nil && p.IsEnabled() {
  82. p.Lock()
  83. p.Restart = false
  84. p.Unlock()
  85. shutdownPlugin(p, pm.containerdClient)
  86. }
  87. }
  88. }