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.Unlock()
  26. if err := pm.containerdClient.Create(p.GetID(), "", "", specs.Spec(*spec), attachToLog(p.GetID())); err != nil {
  27. return err
  28. }
  29. p.PClient, err = plugins.NewClientWithTimeout("unix://"+filepath.Join(p.RuntimeSourcePath, p.GetSocket()), nil, p.TimeoutInSecs)
  30. if err != nil {
  31. p.Lock()
  32. p.Restart = false
  33. p.Unlock()
  34. shutdownPlugin(p, pm.containerdClient)
  35. return err
  36. }
  37. pm.pluginStore.SetState(p, true)
  38. pm.pluginStore.CallHandler(p)
  39. return nil
  40. }
  41. func (pm *Manager) restore(p *v2.Plugin) error {
  42. return pm.containerdClient.Restore(p.GetID(), attachToLog(p.GetID()))
  43. }
  44. func shutdownPlugin(p *v2.Plugin, containerdClient libcontainerd.Client) {
  45. pluginID := p.GetID()
  46. err := containerdClient.Signal(pluginID, int(syscall.SIGTERM))
  47. if err != nil {
  48. logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
  49. } else {
  50. select {
  51. case <-p.ExitChan:
  52. logrus.Debug("Clean shutdown of plugin")
  53. case <-time.After(time.Second * 10):
  54. logrus.Debug("Force shutdown plugin")
  55. if err := containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
  56. logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
  57. }
  58. }
  59. }
  60. }
  61. func (pm *Manager) disable(p *v2.Plugin) error {
  62. if !p.IsEnabled() {
  63. return fmt.Errorf("plugin %s is already disabled", p.Name())
  64. }
  65. p.Lock()
  66. p.Restart = false
  67. p.Unlock()
  68. shutdownPlugin(p, pm.containerdClient)
  69. pm.pluginStore.SetState(p, false)
  70. return nil
  71. }
  72. // Shutdown stops all plugins and called during daemon shutdown.
  73. func (pm *Manager) Shutdown() {
  74. plugins := pm.pluginStore.GetAll()
  75. for _, p := range plugins {
  76. if pm.liveRestore && p.IsEnabled() {
  77. logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
  78. continue
  79. }
  80. if pm.containerdClient != nil && p.IsEnabled() {
  81. p.Lock()
  82. p.ExitChan = make(chan bool)
  83. p.Restart = false
  84. p.Unlock()
  85. shutdownPlugin(p, pm.containerdClient)
  86. }
  87. }
  88. }