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>
This commit is contained in:
Anusha Ragunathan 2016-09-27 13:54:25 -07:00
parent 952520472f
commit 003e04775b
12 changed files with 73 additions and 14 deletions

View file

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

View file

@ -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 {

View file

@ -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())
}

View file

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

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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()

View file

@ -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) == "" {

View file

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

View file

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

View file

@ -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 {