2016-05-16 11:50:55 -04:00
|
|
|
// +build linux,experimental
|
|
|
|
|
|
|
|
package plugin
|
|
|
|
|
|
|
|
import (
|
2016-07-25 17:06:27 -04:00
|
|
|
"fmt"
|
2016-05-16 11:50:55 -04:00
|
|
|
"path/filepath"
|
|
|
|
"syscall"
|
2016-07-01 14:36:11 -04:00
|
|
|
"time"
|
2016-05-16 11:50:55 -04:00
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"github.com/docker/docker/libcontainerd"
|
|
|
|
"github.com/docker/docker/oci"
|
|
|
|
"github.com/docker/docker/pkg/plugins"
|
2016-08-26 13:02:38 -04:00
|
|
|
"github.com/docker/docker/plugin/v2"
|
2016-05-16 11:50:55 -04:00
|
|
|
"github.com/docker/docker/restartmanager"
|
|
|
|
"github.com/docker/engine-api/types/container"
|
|
|
|
)
|
|
|
|
|
2016-08-26 13:02:38 -04:00
|
|
|
func (pm *Manager) enable(p *v2.Plugin, force bool) error {
|
|
|
|
if p.IsEnabled() && !force {
|
2016-07-25 17:06:27 -04:00
|
|
|
return fmt.Errorf("plugin %s is already enabled", p.Name())
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
spec, err := p.InitSpec(oci.DefaultSpec(), pm.libRoot)
|
2016-05-16 11:50:55 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-08-26 13:02:38 -04:00
|
|
|
p.RestartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0)
|
|
|
|
if err := pm.containerdClient.Create(p.GetID(), libcontainerd.Spec(*spec), libcontainerd.WithRestartManager(p.RestartManager)); err != nil {
|
|
|
|
if err := p.RestartManager.Cancel(); err != nil {
|
2016-07-25 17:06:27 -04:00
|
|
|
logrus.Errorf("enable: restartManager.Cancel failed due to %v", err)
|
|
|
|
}
|
2016-05-16 11:50:55 -04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-08-26 13:02:38 -04:00
|
|
|
p.PClient, err = plugins.NewClient("unix://"+filepath.Join(p.RuntimeSourcePath, p.GetSocket()), nil)
|
2016-05-16 11:50:55 -04:00
|
|
|
if err != nil {
|
2016-08-26 13:02:38 -04:00
|
|
|
if err := p.RestartManager.Cancel(); err != nil {
|
2016-07-25 17:06:27 -04:00
|
|
|
logrus.Errorf("enable: restartManager.Cancel failed due to %v", err)
|
|
|
|
}
|
2016-05-16 11:50:55 -04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-08-26 13:02:38 -04:00
|
|
|
pm.pluginStore.SetState(p, true)
|
|
|
|
for _, typ := range p.GetTypes() {
|
2016-05-16 11:50:55 -04:00
|
|
|
if handler := pm.handlers[typ.String()]; handler != nil {
|
|
|
|
handler(p.Name(), p.Client())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-08-26 13:02:38 -04:00
|
|
|
func (pm *Manager) restore(p *v2.Plugin) error {
|
|
|
|
p.RestartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0)
|
|
|
|
return pm.containerdClient.Restore(p.GetID(), libcontainerd.WithRestartManager(p.RestartManager))
|
2016-06-15 13:39:33 -04:00
|
|
|
}
|
|
|
|
|
2016-08-26 13:02:38 -04:00
|
|
|
func (pm *Manager) disable(p *v2.Plugin) error {
|
|
|
|
if !p.IsEnabled() {
|
2016-07-25 17:06:27 -04:00
|
|
|
return fmt.Errorf("plugin %s is already disabled", p.Name())
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
if err := p.RestartManager.Cancel(); err != nil {
|
|
|
|
logrus.Error(err)
|
|
|
|
}
|
|
|
|
if err := pm.containerdClient.Signal(p.GetID(), int(syscall.SIGKILL)); err != nil {
|
2016-05-16 11:50:55 -04:00
|
|
|
logrus.Error(err)
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
if err := p.RemoveFromDisk(); err != nil {
|
2016-05-16 11:50:55 -04:00
|
|
|
logrus.Error(err)
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
pm.pluginStore.SetState(p, false)
|
2016-05-16 11:50:55 -04:00
|
|
|
return nil
|
|
|
|
}
|
2016-07-01 14:36:11 -04:00
|
|
|
|
|
|
|
// Shutdown stops all plugins and called during daemon shutdown.
|
|
|
|
func (pm *Manager) Shutdown() {
|
2016-08-15 12:27:36 -04:00
|
|
|
pm.Lock()
|
|
|
|
pm.shutdown = true
|
|
|
|
pm.Unlock()
|
|
|
|
|
2016-07-01 14:36:11 -04:00
|
|
|
pm.RLock()
|
|
|
|
defer pm.RUnlock()
|
2016-08-26 13:02:38 -04:00
|
|
|
plugins := pm.pluginStore.GetAll()
|
|
|
|
for _, p := range plugins {
|
|
|
|
if pm.liveRestore && p.IsEnabled() {
|
|
|
|
logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
|
2016-07-22 11:53:26 -04:00
|
|
|
continue
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
if p.RestartManager != nil {
|
|
|
|
if err := p.RestartManager.Cancel(); err != nil {
|
2016-07-01 14:36:11 -04:00
|
|
|
logrus.Error(err)
|
|
|
|
}
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
if pm.containerdClient != nil && p.IsEnabled() {
|
|
|
|
pluginID := p.GetID()
|
|
|
|
p.ExitChan = make(chan bool)
|
2016-07-18 11:02:12 -04:00
|
|
|
err := pm.containerdClient.Signal(p.PluginObj.ID, int(syscall.SIGTERM))
|
2016-07-01 14:36:11 -04:00
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
|
|
|
|
} else {
|
|
|
|
select {
|
2016-08-26 13:02:38 -04:00
|
|
|
case <-p.ExitChan:
|
2016-07-01 14:36:11 -04:00
|
|
|
logrus.Debug("Clean shutdown of plugin")
|
|
|
|
case <-time.After(time.Second * 10):
|
|
|
|
logrus.Debug("Force shutdown plugin")
|
2016-08-26 13:02:38 -04:00
|
|
|
if err := pm.containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
|
2016-07-01 14:36:11 -04:00
|
|
|
logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-26 13:02:38 -04:00
|
|
|
if err := p.RemoveFromDisk(); err != nil {
|
2016-07-01 14:36:11 -04:00
|
|
|
logrus.Errorf("Remove plugin runtime failed with error: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|