diff --git a/daemon/daemon.go b/daemon/daemon.go index efe7b0942a..c3e2de437f 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -623,11 +623,12 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot return nil, err } - if err := d.restore(); err != nil { + // Plugin system initialization should happen before restore. Dont change order. + if err := pluginInit(d, config, containerdRemote); err != nil { return nil, err } - if err := pluginInit(d, config, containerdRemote); err != nil { + if err := d.restore(); err != nil { return nil, err } diff --git a/plugin/manager.go b/plugin/manager.go index a577c95f96..4fa6b143b7 100644 --- a/plugin/manager.go +++ b/plugin/manager.go @@ -4,16 +4,13 @@ package plugin import ( "encoding/json" - "fmt" "io" "os" "path/filepath" - "strings" "sync" "github.com/Sirupsen/logrus" "github.com/docker/docker/libcontainerd" - "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/plugin/store" "github.com/docker/docker/plugin/v2" "github.com/docker/docker/registry" @@ -21,12 +18,6 @@ import ( var ( manager *Manager - - /* allowV1PluginsFallback determines daemon's support for V1 plugins. - * When the time comes to remove support for V1 plugins, flipping - * this bool is all that will be needed. - */ - allowV1PluginsFallback = true ) func (pm *Manager) restorePlugin(p *v2.Plugin) error { @@ -45,7 +36,6 @@ type Manager struct { libRoot string runRoot string pluginStore *store.PluginStore - handlers map[string]func(string, *plugins.Client) containerdClient libcontainerd.Client registryService registry.Service liveRestore bool @@ -70,7 +60,6 @@ func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRes libRoot: root, runRoot: "/run/docker", pluginStore: store.NewPluginStore(root), - handlers: make(map[string]func(string, *plugins.Client)), registryService: rs, liveRestore: liveRestore, pluginEventLogger: evL, @@ -88,16 +77,6 @@ func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRes return nil } -// Handle sets a callback for a given capability. The callback will be called for every plugin with a given capability. -// TODO: append instead of set? -func Handle(capability string, callback func(string, *plugins.Client)) { - pluginType := fmt.Sprintf("docker.%s/1", strings.ToLower(capability)) - manager.handlers[pluginType] = callback - if allowV1PluginsFallback { - plugins.Handle(capability, callback) - } -} - // StateChanged updates plugin internals using libcontainerd events. func (pm *Manager) StateChanged(id string, e libcontainerd.StateInfo) error { logrus.Debugf("plugin state changed %s %#v", id, e) diff --git a/plugin/manager_linux.go b/plugin/manager_linux.go index 2b2888d95e..4535212283 100644 --- a/plugin/manager_linux.go +++ b/plugin/manager_linux.go @@ -43,11 +43,7 @@ func (pm *Manager) enable(p *v2.Plugin, force bool) error { } pm.pluginStore.SetState(p, true) - for _, typ := range p.GetTypes() { - if handler := pm.handlers[typ.String()]; handler != nil { - handler(p.Name(), p.Client()) - } - } + pm.pluginStore.CallHandler(p) return nil } diff --git a/plugin/store/store.go b/plugin/store/store.go index 667e62b7ab..1d91816607 100644 --- a/plugin/store/store.go +++ b/plugin/store/store.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "path/filepath" + "strings" "sync" "github.com/Sirupsen/logrus" @@ -32,7 +33,11 @@ func (name ErrNotFound) Error() string { return fmt.Sprintf("plugin %q not found // PluginStore manages the plugin inventory in memory and on-disk type PluginStore struct { sync.RWMutex - plugins map[string]*v2.Plugin + plugins map[string]*v2.Plugin + /* handlers are necessary for transition path of legacy plugins + * to the new model. Legacy plugins use Handle() for registering an + * activation callback.*/ + handlers map[string]func(string, *plugins.Client) nameToID map[string]string plugindb string } @@ -41,6 +46,7 @@ type PluginStore struct { func NewPluginStore(libRoot string) *PluginStore { store = &PluginStore{ plugins: make(map[string]*v2.Plugin), + handlers: make(map[string]func(string, *plugins.Client)), nameToID: make(map[string]string), plugindb: filepath.Join(libRoot, "plugins.json"), } @@ -222,3 +228,27 @@ func FindWithCapability(capability string) ([]CompatPlugin, error) { } return result, nil } + +// Handle sets a callback for a given capability. It is only used by network +// and ipam drivers during plugin registration. The callback registers the +// driver with the subsystem (network, ipam). +func Handle(capability string, callback func(string, *plugins.Client)) { + pluginType := fmt.Sprintf("docker.%s/1", strings.ToLower(capability)) + + // Register callback with new plugin model. + store.handlers[pluginType] = callback + + // Register callback with legacy plugin model. + if allowV1PluginsFallback { + plugins.Handle(capability, callback) + } +} + +// CallHandler calls the registered callback. It is invoked during plugin enable. +func (ps *PluginStore) CallHandler(p *v2.Plugin) { + for _, typ := range p.GetTypes() { + if handler := ps.handlers[typ.String()]; handler != nil { + handler(p.Name(), p.Client()) + } + } +}