github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/plugin/manager_linux.go (about) 1 // +build linux,experimental 2 3 package plugin 4 5 import ( 6 "fmt" 7 "path/filepath" 8 "syscall" 9 "time" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/docker/docker/api/types/container" 13 "github.com/docker/docker/libcontainerd" 14 "github.com/docker/docker/oci" 15 "github.com/docker/docker/pkg/plugins" 16 "github.com/docker/docker/plugin/v2" 17 "github.com/docker/docker/restartmanager" 18 "github.com/opencontainers/runtime-spec/specs-go" 19 ) 20 21 func (pm *Manager) enable(p *v2.Plugin, force bool) error { 22 if p.IsEnabled() && !force { 23 return fmt.Errorf("plugin %s is already enabled", p.Name()) 24 } 25 spec, err := p.InitSpec(oci.DefaultSpec(), pm.libRoot) 26 if err != nil { 27 return err 28 } 29 30 p.RestartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0) 31 if err := pm.containerdClient.Create(p.GetID(), "", "", specs.Spec(*spec), libcontainerd.WithRestartManager(p.RestartManager)); err != nil { 32 if err := p.RestartManager.Cancel(); err != nil { 33 logrus.Errorf("enable: restartManager.Cancel failed due to %v", err) 34 } 35 return err 36 } 37 38 p.PClient, err = plugins.NewClient("unix://"+filepath.Join(p.RuntimeSourcePath, p.GetSocket()), nil) 39 if err != nil { 40 if err := p.RestartManager.Cancel(); err != nil { 41 logrus.Errorf("enable: restartManager.Cancel failed due to %v", err) 42 } 43 return err 44 } 45 46 pm.pluginStore.SetState(p, true) 47 pm.pluginStore.CallHandler(p) 48 49 return nil 50 } 51 52 func (pm *Manager) restore(p *v2.Plugin) error { 53 p.RestartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0) 54 return pm.containerdClient.Restore(p.GetID(), libcontainerd.WithRestartManager(p.RestartManager)) 55 } 56 57 func (pm *Manager) disable(p *v2.Plugin) error { 58 if !p.IsEnabled() { 59 return fmt.Errorf("plugin %s is already disabled", p.Name()) 60 } 61 if err := p.RestartManager.Cancel(); err != nil { 62 logrus.Error(err) 63 } 64 if err := pm.containerdClient.Signal(p.GetID(), int(syscall.SIGKILL)); err != nil { 65 logrus.Error(err) 66 } 67 if err := p.RemoveFromDisk(); err != nil { 68 logrus.Error(err) 69 } 70 pm.pluginStore.SetState(p, false) 71 return nil 72 } 73 74 // Shutdown stops all plugins and called during daemon shutdown. 75 func (pm *Manager) Shutdown() { 76 pm.Lock() 77 pm.shutdown = true 78 pm.Unlock() 79 80 pm.RLock() 81 defer pm.RUnlock() 82 plugins := pm.pluginStore.GetAll() 83 for _, p := range plugins { 84 if pm.liveRestore && p.IsEnabled() { 85 logrus.Debug("Plugin active when liveRestore is set, skipping shutdown") 86 continue 87 } 88 if p.RestartManager != nil { 89 if err := p.RestartManager.Cancel(); err != nil { 90 logrus.Error(err) 91 } 92 } 93 if pm.containerdClient != nil && p.IsEnabled() { 94 pluginID := p.GetID() 95 p.ExitChan = make(chan bool) 96 err := pm.containerdClient.Signal(p.PluginObj.ID, int(syscall.SIGTERM)) 97 if err != nil { 98 logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err) 99 } else { 100 select { 101 case <-p.ExitChan: 102 logrus.Debug("Clean shutdown of plugin") 103 case <-time.After(time.Second * 10): 104 logrus.Debug("Force shutdown plugin") 105 if err := pm.containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil { 106 logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err) 107 } 108 } 109 } 110 } 111 if err := p.RemoveFromDisk(); err != nil { 112 logrus.Errorf("Remove plugin runtime failed with error: %v", err) 113 } 114 } 115 }