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 |
}
}
} |