plugin/manager_linux.go
7781a1bf
 // +build linux
f3711704
 
 package plugin
 
 import (
b867f6c6
 	"fmt"
f3711704
 	"path/filepath"
 	"syscall"
863ab9ab
 	"time"
f3711704
 
 	"github.com/Sirupsen/logrus"
846b198d
 	"github.com/docker/docker/libcontainerd"
f3711704
 	"github.com/docker/docker/oci"
3a571b72
 	"github.com/docker/docker/pkg/mount"
f3711704
 	"github.com/docker/docker/pkg/plugins"
27a55fba
 	"github.com/docker/docker/plugin/v2"
7781a1bf
 	specs "github.com/opencontainers/runtime-spec/specs-go"
f3711704
 )
 
213ee207
 func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error {
3a571b72
 	p.Rootfs = filepath.Join(pm.libRoot, p.PluginObj.ID, "rootfs")
27a55fba
 	if p.IsEnabled() && !force {
b867f6c6
 		return fmt.Errorf("plugin %s is already enabled", p.Name())
 	}
3a571b72
 	spec, err := p.InitSpec(oci.DefaultSpec())
f3711704
 	if err != nil {
 		return err
 	}
213ee207
 
 	c.restart = true
 	c.exitChan = make(chan bool)
 
 	pm.mu.Lock()
 	pm.cMap[p] = c
 	pm.mu.Unlock()
 
3a571b72
 	if p.PropagatedMount != "" {
 		if err := mount.MakeRShared(p.PropagatedMount); err != nil {
 			return err
 		}
 	}
 
37a3be24
 	if err := pm.containerdClient.Create(p.GetID(), "", "", specs.Spec(*spec), attachToLog(p.GetID())); err != nil {
1a86cbb0
 		if p.PropagatedMount != "" {
 			if err := mount.Unmount(p.PropagatedMount); err != nil {
 				logrus.Warnf("Could not unmount %s: %v", p.PropagatedMount, err)
 			}
 		}
f3711704
 		return err
 	}
 
4e08d8ef
 	return pm.pluginPostStart(p, c)
 }
 
 func (pm *Manager) pluginPostStart(p *v2.Plugin, c *controller) error {
213ee207
 	client, err := plugins.NewClientWithTimeout("unix://"+filepath.Join(p.GetRuntimeSourcePath(), p.GetSocket()), nil, c.timeoutInSecs)
f3711704
 	if err != nil {
213ee207
 		c.restart = false
 		shutdownPlugin(p, c, pm.containerdClient)
f3711704
 		return err
 	}
 
213ee207
 	p.SetPClient(client)
27a55fba
 	pm.pluginStore.SetState(p, true)
17b8aba1
 	pm.pluginStore.CallHandler(p)
f3711704
 	return nil
 }
 
27a55fba
 func (pm *Manager) restore(p *v2.Plugin) error {
4e08d8ef
 	if err := pm.containerdClient.Restore(p.GetID(), attachToLog(p.GetID())); err != nil {
 		return err
 	}
 
 	if pm.liveRestore {
 		c := &controller{}
 		if pids, _ := pm.containerdClient.GetPidsForContainer(p.GetID()); len(pids) == 0 {
 			// plugin is not running, so follow normal startup procedure
 			return pm.enable(p, c, true)
 		}
 
 		c.exitChan = make(chan bool)
 		c.restart = true
 		pm.mu.Lock()
 		pm.cMap[p] = c
 		pm.mu.Unlock()
 		return pm.pluginPostStart(p, c)
 	}
 
 	return nil
dfd91873
 }
 
213ee207
 func shutdownPlugin(p *v2.Plugin, c *controller, containerdClient libcontainerd.Client) {
846b198d
 	pluginID := p.GetID()
 
 	err := containerdClient.Signal(pluginID, int(syscall.SIGTERM))
 	if err != nil {
 		logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err)
 	} else {
 		select {
213ee207
 		case <-c.exitChan:
846b198d
 			logrus.Debug("Clean shutdown of plugin")
 		case <-time.After(time.Second * 10):
 			logrus.Debug("Force shutdown plugin")
 			if err := containerdClient.Signal(pluginID, int(syscall.SIGKILL)); err != nil {
 				logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err)
 			}
 		}
 	}
 }
 
213ee207
 func (pm *Manager) disable(p *v2.Plugin, c *controller) error {
27a55fba
 	if !p.IsEnabled() {
b867f6c6
 		return fmt.Errorf("plugin %s is already disabled", p.Name())
 	}
846b198d
 
213ee207
 	c.restart = false
 	shutdownPlugin(p, c, pm.containerdClient)
27a55fba
 	pm.pluginStore.SetState(p, false)
f3711704
 	return nil
 }
863ab9ab
 
 // Shutdown stops all plugins and called during daemon shutdown.
 func (pm *Manager) Shutdown() {
27a55fba
 	plugins := pm.pluginStore.GetAll()
 	for _, p := range plugins {
213ee207
 		pm.mu.RLock()
 		c := pm.cMap[p]
 		pm.mu.RUnlock()
 
27a55fba
 		if pm.liveRestore && p.IsEnabled() {
 			logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
4a44cf1d
 			continue
 		}
27a55fba
 		if pm.containerdClient != nil && p.IsEnabled() {
213ee207
 			c.restart = false
 			shutdownPlugin(p, c, pm.containerdClient)
863ab9ab
 		}
 	}
 }