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:
parent
952520472f
commit
003e04775b
12 changed files with 73 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) == "" {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue