Browse Source

Make libnetwork understand pluginv2.

As part of daemon init, network and ipam drivers are passed a
pluginstore object that implements the plugin/getter interface. Use this
interface methods in libnetwork to interact with network plugins. This
interface provides the new and improved pluginv2 functionality and falls
back to pluginv1 (legacy) if necessary.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>
Anusha Ragunathan 8 years ago
parent
commit
003e04775b

+ 5 - 0
libnetwork/cmd/ovrouter/ovrouter.go

@@ -7,6 +7,7 @@ import (
 	"os/signal"
 
 	"github.com/docker/docker/pkg/reexec"
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/drivers/overlay"
 	"github.com/docker/libnetwork/netlabel"
@@ -24,6 +25,10 @@ type endpoint struct {
 	name string
 }
 
+func (r *router) GetPluginGetter() getter.PluginGetter {
+	return nil
+}
+
 func (r *router) RegisterDriver(name string, driver driverapi.Driver, c driverapi.Capability) error {
 	r.d = driver
 	return nil

+ 9 - 0
libnetwork/config/config.go

@@ -6,6 +6,7 @@ import (
 	"github.com/BurntSushi/toml"
 	log "github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/discovery"
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/go-connections/tlsconfig"
 	"github.com/docker/libkv/store"
 	"github.com/docker/libnetwork/cluster"
@@ -20,6 +21,7 @@ type Config struct {
 	Cluster         ClusterCfg
 	Scopes          map[string]*datastore.ScopeCfg
 	ActiveSandboxes map[string]interface{}
+	PluginGetter    getter.PluginGetter
 }
 
 // DaemonCfg represents libnetwork core configuration
@@ -205,6 +207,13 @@ func OptionExecRoot(execRoot string) Option {
 	}
 }
 
+// OptionPluginGetter returns a plugingetter for remote drivers.
+func OptionPluginGetter(pg getter.PluginGetter) Option {
+	return func(c *Config) {
+		c.PluginGetter = pg
+	}
+}
+
 // ProcessOptions processes options and stores it in config
 func (c *Config) ProcessOptions(options ...Option) {
 	for _, opt := range options {

+ 7 - 2
libnetwork/controller.go

@@ -55,6 +55,7 @@ import (
 	"github.com/docker/docker/pkg/locker"
 	"github.com/docker/docker/pkg/plugins"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/cluster"
 	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/datastore"
@@ -178,7 +179,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
 		return nil, err
 	}
 
-	drvRegistry, err := drvregistry.New(c.getStore(datastore.LocalScope), c.getStore(datastore.GlobalScope), c.RegisterDriver, nil)
+	drvRegistry, err := drvregistry.New(c.getStore(datastore.LocalScope), c.getStore(datastore.GlobalScope), c.RegisterDriver, nil, c.cfg.PluginGetter)
 	if err != nil {
 		return nil, err
 	}
@@ -601,6 +602,10 @@ func (c *controller) isDistributedControl() bool {
 	return !c.isManager() && !c.isAgent()
 }
 
+func (c *controller) GetPluginGetter() getter.PluginGetter {
+	return c.drvRegistry.GetPluginGetter()
+}
+
 func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver, capability driverapi.Capability) error {
 	c.Lock()
 	hd := c.discovery
@@ -1074,7 +1079,7 @@ func (c *controller) loadDriver(networkType string) error {
 }
 
 func (c *controller) loadIPAMDriver(name string) error {
-	if _, err := plugins.Get(name, ipamapi.PluginEndpointType); err != nil {
+	if _, err := c.GetPluginGetter().Get(name, ipamapi.PluginEndpointType, getter.LOOKUP); err != nil {
 		if err == plugins.ErrNotFound {
 			return types.NotFoundErrorf(err.Error())
 		}

+ 3 - 0
libnetwork/driverapi/driverapi.go

@@ -3,6 +3,7 @@ package driverapi
 import (
 	"net"
 
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/discoverapi"
 )
 
@@ -139,6 +140,8 @@ type JoinInfo interface {
 
 // DriverCallback provides a Callback interface for Drivers into LibNetwork
 type DriverCallback interface {
+	// GetPluginGetter returns the pluginv2 getter.
+	GetPluginGetter() getter.PluginGetter
 	// RegisterDriver provides a way for Remote drivers to dynamically register new NetworkType and associate with a driver instance
 	RegisterDriver(name string, driver Driver, capability Capability) error
 }

+ 5 - 0
libnetwork/drivers/ipvlan/ipvlan_test.go

@@ -3,6 +3,7 @@ package ipvlan
 import (
 	"testing"
 
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/driverapi"
 	_ "github.com/docker/libnetwork/testutils"
 )
@@ -14,6 +15,10 @@ type driverTester struct {
 	d *driver
 }
 
+func (dt *driverTester) GetPluginGetter() getter.PluginGetter {
+	return nil
+}
+
 func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
 	cap driverapi.Capability) error {
 	if name != testNetworkType {

+ 5 - 0
libnetwork/drivers/macvlan/macvlan_test.go

@@ -3,6 +3,7 @@ package macvlan
 import (
 	"testing"
 
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/driverapi"
 	_ "github.com/docker/libnetwork/testutils"
 )
@@ -14,6 +15,10 @@ type driverTester struct {
 	d *driver
 }
 
+func (dt *driverTester) GetPluginGetter() getter.PluginGetter {
+	return nil
+}
+
 func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
 	cap driverapi.Capability) error {
 	if name != testNetworkType {

+ 5 - 0
libnetwork/drivers/overlay/overlay_test.go

@@ -5,6 +5,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libkv/store/consul"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/discoverapi"
@@ -67,6 +68,10 @@ func cleanupDriver(t *testing.T, dt *driverTester) {
 	}
 }
 
+func (dt *driverTester) GetPluginGetter() getter.PluginGetter {
+	return nil
+}
+
 func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
 	cap driverapi.Capability) error {
 	if name != testNetworkType {

+ 6 - 1
libnetwork/drivers/remote/driver.go

@@ -29,7 +29,12 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver {
 // Init makes sure a remote driver is registered when a network driver
 // plugin is activated.
 func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
-	plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
+	// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
+	handleFunc := plugins.Handle
+	if pg := dc.GetPluginGetter(); pg != nil {
+		handleFunc = pg.Handle
+	}
+	handleFunc(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
 		// negotiate driver capability with client
 		d := newDriver(name, client)
 		c, err := d.(*driver).getCapabilities()

+ 17 - 9
libnetwork/drvregistry/drvregistry.go

@@ -5,6 +5,7 @@ import (
 	"strings"
 	"sync"
 
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/ipamapi"
 	"github.com/docker/libnetwork/types"
@@ -28,10 +29,11 @@ type ipamTable map[string]*ipamData
 // DrvRegistry holds the registry of all network drivers and IPAM drivers that it knows about.
 type DrvRegistry struct {
 	sync.Mutex
-	drivers     driverTable
-	ipamDrivers ipamTable
-	dfn         DriverNotifyFunc
-	ifn         IPAMNotifyFunc
+	drivers      driverTable
+	ipamDrivers  ipamTable
+	dfn          DriverNotifyFunc
+	ifn          IPAMNotifyFunc
+	pluginGetter getter.PluginGetter
 }
 
 // Functors definition
@@ -52,12 +54,13 @@ type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capabili
 type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error
 
 // New retruns a new driver registry handle.
-func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc) (*DrvRegistry, error) {
+func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc, pg getter.PluginGetter) (*DrvRegistry, error) {
 	r := &DrvRegistry{
-		drivers:     make(driverTable),
-		ipamDrivers: make(ipamTable),
-		dfn:         dfn,
-		ifn:         ifn,
+		drivers:      make(driverTable),
+		ipamDrivers:  make(ipamTable),
+		dfn:          dfn,
+		ifn:          ifn,
+		pluginGetter: pg,
 	}
 
 	return r, nil
@@ -149,6 +152,11 @@ func (r *DrvRegistry) IPAMDefaultAddressSpaces(name string) (string, string, err
 	return i.defaultLocalAddressSpace, i.defaultGlobalAddressSpace, nil
 }
 
+// GetPluginGetter returns the plugingetter
+func (r *DrvRegistry) GetPluginGetter() getter.PluginGetter {
+	return r.pluginGetter
+}
+
 // RegisterDriver registers the network driver when it gets discovered.
 func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error {
 	if strings.TrimSpace(ntype) == "" {

+ 1 - 1
libnetwork/drvregistry/drvregistry_test.go

@@ -88,7 +88,7 @@ func (m *mockDriver) EventNotify(etype driverapi.EventType, nid, tableName, key
 }
 
 func getNew(t *testing.T) *DrvRegistry {
-	reg, err := New(nil, nil, nil, nil)
+	reg, err := New(nil, nil, nil, nil, nil)
 	if err != nil {
 		t.Fatal(err)
 	}

+ 3 - 0
libnetwork/ipamapi/contract.go

@@ -4,6 +4,7 @@ package ipamapi
 import (
 	"net"
 
+	"github.com/docker/docker/plugin/getter"
 	"github.com/docker/libnetwork/discoverapi"
 	"github.com/docker/libnetwork/types"
 )
@@ -25,6 +26,8 @@ const (
 
 // Callback provides a Callback interface for registering an IPAM instance into LibNetwork
 type Callback interface {
+	// GetPluginGetter returns the pluginv2 getter.
+	GetPluginGetter() getter.PluginGetter
 	// RegisterIpamDriver provides a way for Remote drivers to dynamically register with libnetwork
 	RegisterIpamDriver(name string, driver Ipam) error
 	// RegisterIpamDriverWithCapabilities provides a way for Remote drivers to dynamically register with libnetwork and specify capabilities

+ 7 - 1
libnetwork/ipams/remote/remote.go

@@ -30,7 +30,13 @@ func newAllocator(name string, client *plugins.Client) ipamapi.Ipam {
 
 // Init registers a remote ipam when its plugin is activated
 func Init(cb ipamapi.Callback, l, g interface{}) error {
-	plugins.Handle(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) {
+
+	// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
+	handleFunc := plugins.Handle
+	if pg := cb.GetPluginGetter(); pg != nil {
+		handleFunc = pg.Handle
+	}
+	handleFunc(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) {
 		a := newAllocator(name, client)
 		if cps, err := a.(*allocator).getCapabilities(); err == nil {
 			if err := cb.RegisterIpamDriverWithCapabilities(name, a, cps); err != nil {