Browse code

Adding pluginv2 support for libnetwork (part 1)

Legacy plugins (aka pluginv1) calls in libnetwork are replaced with
calls using the new plugin model (aka pluginv2). pkg/plugins is still
used for managing the http client connections to the plugin.

This commit makes the necessary changes in docker/docker. Part 2 will
will take care of the libnetwork changes.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>

Anusha Ragunathan authored on 2016/09/07 06:30:55
Showing 4 changed files
... ...
@@ -623,11 +623,12 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
623 623
 		return nil, err
624 624
 	}
625 625
 
626
-	if err := d.restore(); err != nil {
626
+	// Plugin system initialization should happen before restore. Dont change order.
627
+	if err := pluginInit(d, config, containerdRemote); err != nil {
627 628
 		return nil, err
628 629
 	}
629 630
 
630
-	if err := pluginInit(d, config, containerdRemote); err != nil {
631
+	if err := d.restore(); err != nil {
631 632
 		return nil, err
632 633
 	}
633 634
 
... ...
@@ -4,16 +4,13 @@ package plugin
4 4
 
5 5
 import (
6 6
 	"encoding/json"
7
-	"fmt"
8 7
 	"io"
9 8
 	"os"
10 9
 	"path/filepath"
11
-	"strings"
12 10
 	"sync"
13 11
 
14 12
 	"github.com/Sirupsen/logrus"
15 13
 	"github.com/docker/docker/libcontainerd"
16
-	"github.com/docker/docker/pkg/plugins"
17 14
 	"github.com/docker/docker/plugin/store"
18 15
 	"github.com/docker/docker/plugin/v2"
19 16
 	"github.com/docker/docker/registry"
... ...
@@ -21,12 +18,6 @@ import (
21 21
 
22 22
 var (
23 23
 	manager *Manager
24
-
25
-	/* allowV1PluginsFallback determines daemon's support for V1 plugins.
26
-	 * When the time comes to remove support for V1 plugins, flipping
27
-	 * this bool is all that will be needed.
28
-	 */
29
-	allowV1PluginsFallback = true
30 24
 )
31 25
 
32 26
 func (pm *Manager) restorePlugin(p *v2.Plugin) error {
... ...
@@ -45,7 +36,6 @@ type Manager struct {
45 45
 	libRoot           string
46 46
 	runRoot           string
47 47
 	pluginStore       *store.PluginStore
48
-	handlers          map[string]func(string, *plugins.Client)
49 48
 	containerdClient  libcontainerd.Client
50 49
 	registryService   registry.Service
51 50
 	liveRestore       bool
... ...
@@ -70,7 +60,6 @@ func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRes
70 70
 		libRoot:           root,
71 71
 		runRoot:           "/run/docker",
72 72
 		pluginStore:       store.NewPluginStore(root),
73
-		handlers:          make(map[string]func(string, *plugins.Client)),
74 73
 		registryService:   rs,
75 74
 		liveRestore:       liveRestore,
76 75
 		pluginEventLogger: evL,
... ...
@@ -88,16 +77,6 @@ func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRes
88 88
 	return nil
89 89
 }
90 90
 
91
-// Handle sets a callback for a given capability. The callback will be called for every plugin with a given capability.
92
-// TODO: append instead of set?
93
-func Handle(capability string, callback func(string, *plugins.Client)) {
94
-	pluginType := fmt.Sprintf("docker.%s/1", strings.ToLower(capability))
95
-	manager.handlers[pluginType] = callback
96
-	if allowV1PluginsFallback {
97
-		plugins.Handle(capability, callback)
98
-	}
99
-}
100
-
101 91
 // StateChanged updates plugin internals using libcontainerd events.
102 92
 func (pm *Manager) StateChanged(id string, e libcontainerd.StateInfo) error {
103 93
 	logrus.Debugf("plugin state changed %s %#v", id, e)
... ...
@@ -43,11 +43,7 @@ func (pm *Manager) enable(p *v2.Plugin, force bool) error {
43 43
 	}
44 44
 
45 45
 	pm.pluginStore.SetState(p, true)
46
-	for _, typ := range p.GetTypes() {
47
-		if handler := pm.handlers[typ.String()]; handler != nil {
48
-			handler(p.Name(), p.Client())
49
-		}
50
-	}
46
+	pm.pluginStore.CallHandler(p)
51 47
 
52 48
 	return nil
53 49
 }
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"encoding/json"
7 7
 	"fmt"
8 8
 	"path/filepath"
9
+	"strings"
9 10
 	"sync"
10 11
 
11 12
 	"github.com/Sirupsen/logrus"
... ...
@@ -32,7 +33,11 @@ func (name ErrNotFound) Error() string { return fmt.Sprintf("plugin %q not found
32 32
 // PluginStore manages the plugin inventory in memory and on-disk
33 33
 type PluginStore struct {
34 34
 	sync.RWMutex
35
-	plugins  map[string]*v2.Plugin
35
+	plugins map[string]*v2.Plugin
36
+	/* handlers are necessary for transition path of legacy plugins
37
+	 * to the new model. Legacy plugins use Handle() for registering an
38
+	 * activation callback.*/
39
+	handlers map[string]func(string, *plugins.Client)
36 40
 	nameToID map[string]string
37 41
 	plugindb string
38 42
 }
... ...
@@ -41,6 +46,7 @@ type PluginStore struct {
41 41
 func NewPluginStore(libRoot string) *PluginStore {
42 42
 	store = &PluginStore{
43 43
 		plugins:  make(map[string]*v2.Plugin),
44
+		handlers: make(map[string]func(string, *plugins.Client)),
44 45
 		nameToID: make(map[string]string),
45 46
 		plugindb: filepath.Join(libRoot, "plugins.json"),
46 47
 	}
... ...
@@ -222,3 +228,27 @@ func FindWithCapability(capability string) ([]CompatPlugin, error) {
222 222
 	}
223 223
 	return result, nil
224 224
 }
225
+
226
+// Handle sets a callback for a given capability. It is only used by network
227
+// and ipam drivers during plugin registration. The callback registers the
228
+// driver with the subsystem (network, ipam).
229
+func Handle(capability string, callback func(string, *plugins.Client)) {
230
+	pluginType := fmt.Sprintf("docker.%s/1", strings.ToLower(capability))
231
+
232
+	// Register callback with new plugin model.
233
+	store.handlers[pluginType] = callback
234
+
235
+	// Register callback with legacy plugin model.
236
+	if allowV1PluginsFallback {
237
+		plugins.Handle(capability, callback)
238
+	}
239
+}
240
+
241
+// CallHandler calls the registered callback. It is invoked during plugin enable.
242
+func (ps *PluginStore) CallHandler(p *v2.Plugin) {
243
+	for _, typ := range p.GetTypes() {
244
+		if handler := ps.handlers[typ.String()]; handler != nil {
245
+			handler(p.Name(), p.Client())
246
+		}
247
+	}
248
+}