manager_linux.go 2.4 KB

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