浏览代码

Replacing isReservedNetwork with Driver capability

Currently store makes use of a static isReservedNetwork check to decide
if a network needs to be stored in the distributed store or not. But it
is better if the check is not static, but be determined based on the
capability of the driver that backs the network.

Hence introducing a new capability mechanism to the driver which it can
express its capability during registration. Making use of first such
capability : Scope. This can be expanded in the future for more such cases.

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 10 年之前
父节点
当前提交
9e8974cc64

+ 32 - 10
libnetwork/controller.go

@@ -92,6 +92,12 @@ type NetworkController interface {
 // When the function returns true, the walk will stop.
 // When the function returns true, the walk will stop.
 type NetworkWalker func(nw Network) bool
 type NetworkWalker func(nw Network) bool
 
 
+type driverData struct {
+	driver     driverapi.Driver
+	capability driverapi.Capability
+}
+
+type driverTable map[string]*driverData
 type networkTable map[types.UUID]*network
 type networkTable map[types.UUID]*network
 type endpointTable map[types.UUID]*endpoint
 type endpointTable map[types.UUID]*endpoint
 type sandboxTable map[string]*sandboxData
 type sandboxTable map[string]*sandboxData
@@ -175,21 +181,21 @@ func (c *controller) hostLeaveCallback(hosts []net.IP) {
 
 
 func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error {
 func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error {
 	c.Lock()
 	c.Lock()
-	d, ok := c.drivers[networkType]
+	dd, ok := c.drivers[networkType]
 	c.Unlock()
 	c.Unlock()
 	if !ok {
 	if !ok {
 		return NetworkTypeError(networkType)
 		return NetworkTypeError(networkType)
 	}
 	}
-	return d.Config(options)
+	return dd.driver.Config(options)
 }
 }
 
 
-func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver) error {
+func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver, capability driverapi.Capability) error {
 	c.Lock()
 	c.Lock()
 	defer c.Unlock()
 	defer c.Unlock()
 	if _, ok := c.drivers[networkType]; ok {
 	if _, ok := c.drivers[networkType]; ok {
 		return driverapi.ErrActiveRegistration(networkType)
 		return driverapi.ErrActiveRegistration(networkType)
 	}
 	}
-	c.drivers[networkType] = driver
+	c.drivers[networkType] = &driverData{driver, capability}
 	return nil
 	return nil
 }
 }
 
 
@@ -238,18 +244,21 @@ func (c *controller) addNetwork(n *network) error {
 
 
 	c.Lock()
 	c.Lock()
 	// Check if a driver for the specified network type is available
 	// Check if a driver for the specified network type is available
-	d, ok := c.drivers[n.networkType]
+	dd, ok := c.drivers[n.networkType]
 	c.Unlock()
 	c.Unlock()
 
 
 	if !ok {
 	if !ok {
 		var err error
 		var err error
-		d, err = c.loadDriver(n.networkType)
+		dd, err = c.loadDriver(n.networkType)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
 
 
-	n.driver = d
+	n.Lock()
+	n.driver = dd.driver
+	d := n.driver
+	n.Unlock()
 
 
 	// Create the network
 	// Create the network
 	if err := d.CreateNetwork(n.id, n.generic); err != nil {
 	if err := d.CreateNetwork(n.id, n.generic); err != nil {
@@ -317,7 +326,7 @@ func (c *controller) NetworkByID(id string) (Network, error) {
 	return nil, ErrNoSuchNetwork(id)
 	return nil, ErrNoSuchNetwork(id)
 }
 }
 
 
-func (c *controller) loadDriver(networkType string) (driverapi.Driver, error) {
+func (c *controller) loadDriver(networkType string) (*driverData, error) {
 	// Plugins pkg performs lazy loading of plugins that acts as remote drivers.
 	// Plugins pkg performs lazy loading of plugins that acts as remote drivers.
 	// As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available.
 	// As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available.
 	_, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType)
 	_, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType)
@@ -329,11 +338,24 @@ func (c *controller) loadDriver(networkType string) (driverapi.Driver, error) {
 	}
 	}
 	c.Lock()
 	c.Lock()
 	defer c.Unlock()
 	defer c.Unlock()
-	d, ok := c.drivers[networkType]
+	dd, ok := c.drivers[networkType]
 	if !ok {
 	if !ok {
 		return nil, ErrInvalidNetworkDriver(networkType)
 		return nil, ErrInvalidNetworkDriver(networkType)
 	}
 	}
-	return d, nil
+	return dd, nil
+}
+
+func (c *controller) isDriverGlobalScoped(networkType string) (bool, error) {
+	c.Lock()
+	dd, ok := c.drivers[networkType]
+	c.Unlock()
+	if !ok {
+		return false, types.NotFoundErrorf("driver not found for %s", networkType)
+	}
+	if dd.capability.Scope == driverapi.GlobalScope {
+		return true, nil
+	}
+	return false, nil
 }
 }
 
 
 func (c *controller) GC() {
 func (c *controller) GC() {

+ 16 - 1
libnetwork/driverapi/driverapi.go

@@ -118,5 +118,20 @@ type JoinInfo interface {
 // DriverCallback provides a Callback interface for Drivers into LibNetwork
 // DriverCallback provides a Callback interface for Drivers into LibNetwork
 type DriverCallback interface {
 type DriverCallback interface {
 	// RegisterDriver provides a way for Remote drivers to dynamically register new NetworkType and associate with a driver instance
 	// RegisterDriver provides a way for Remote drivers to dynamically register new NetworkType and associate with a driver instance
-	RegisterDriver(name string, driver Driver) error
+	RegisterDriver(name string, driver Driver, capability Capability) error
+}
+
+// Scope indicates the drivers scope capability
+type Scope int
+
+const (
+	// LocalScope represents the driver capable of providing networking services for containers in a single host
+	LocalScope Scope = iota
+	// GlobalScope represents the driver capable of providing networking services for containers across hosts
+	GlobalScope
+)
+
+// Capability represents the high level capabilities of the drivers which libnetwork can make use of
+type Capability struct {
+	Scope Scope
 }
 }

+ 4 - 1
libnetwork/drivers/bridge/bridge.go

@@ -110,7 +110,10 @@ func Init(dc driverapi.DriverCallback) error {
 	if out, err := exec.Command("modprobe", "-va", "bridge", "nf_nat", "br_netfilter").Output(); err != nil {
 	if out, err := exec.Command("modprobe", "-va", "bridge", "nf_nat", "br_netfilter").Output(); err != nil {
 		logrus.Warnf("Running modprobe bridge nf_nat failed with message: %s, error: %v", out, err)
 		logrus.Warnf("Running modprobe bridge nf_nat failed with message: %s, error: %v", out, err)
 	}
 	}
-	return dc.RegisterDriver(networkType, newDriver())
+	c := driverapi.Capability{
+		Scope: driverapi.LocalScope,
+	}
+	return dc.RegisterDriver(networkType, newDriver(), c)
 }
 }
 
 
 // Validate performs a static validation on the network configuration parameters.
 // Validate performs a static validation on the network configuration parameters.

+ 4 - 1
libnetwork/drivers/host/host.go

@@ -16,7 +16,10 @@ type driver struct {
 
 
 // Init registers a new instance of host driver
 // Init registers a new instance of host driver
 func Init(dc driverapi.DriverCallback) error {
 func Init(dc driverapi.DriverCallback) error {
-	return dc.RegisterDriver(networkType, &driver{})
+	c := driverapi.Capability{
+		Scope: driverapi.LocalScope,
+	}
+	return dc.RegisterDriver(networkType, &driver{}, c)
 }
 }
 
 
 func (d *driver) Config(option map[string]interface{}) error {
 func (d *driver) Config(option map[string]interface{}) error {

+ 4 - 1
libnetwork/drivers/null/null.go

@@ -16,7 +16,10 @@ type driver struct {
 
 
 // Init registers a new instance of null driver
 // Init registers a new instance of null driver
 func Init(dc driverapi.DriverCallback) error {
 func Init(dc driverapi.DriverCallback) error {
-	return dc.RegisterDriver(networkType, &driver{})
+	c := driverapi.Capability{
+		Scope: driverapi.LocalScope,
+	}
+	return dc.RegisterDriver(networkType, &driver{}, c)
 }
 }
 
 
 func (d *driver) Config(option map[string]interface{}) error {
 func (d *driver) Config(option map[string]interface{}) error {

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

@@ -23,7 +23,10 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver {
 // plugin is activated.
 // plugin is activated.
 func Init(dc driverapi.DriverCallback) error {
 func Init(dc driverapi.DriverCallback) error {
 	plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
 	plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
-		if err := dc.RegisterDriver(name, newDriver(name, client)); err != nil {
+		c := driverapi.Capability{
+			Scope: driverapi.GlobalScope,
+		}
+		if err := dc.RegisterDriver(name, newDriver(name, client), c); err != nil {
 			log.Errorf("error registering driver for %s due to %v", name, err)
 			log.Errorf("error registering driver for %s due to %v", name, err)
 		}
 		}
 	})
 	})

+ 4 - 1
libnetwork/drivers/windows/windows.go

@@ -13,7 +13,10 @@ type driver struct{}
 
 
 // Init registers a new instance of null driver
 // Init registers a new instance of null driver
 func Init(dc driverapi.DriverCallback) error {
 func Init(dc driverapi.DriverCallback) error {
-	return dc.RegisterDriver(networkType, &driver{})
+	c := driverapi.Capability{
+		Scope: driverapi.LocalScope,
+	}
+	return dc.RegisterDriver(networkType, &driver{}, c)
 }
 }
 
 
 func (d *driver) Config(option map[string]interface{}) error {
 func (d *driver) Config(option map[string]interface{}) error {

+ 0 - 2
libnetwork/drivers_freebsd.go

@@ -6,8 +6,6 @@ import (
 	"github.com/docker/libnetwork/drivers/remote"
 	"github.com/docker/libnetwork/drivers/remote"
 )
 )
 
 
-type driverTable map[string]driverapi.Driver
-
 func initDrivers(dc driverapi.DriverCallback) error {
 func initDrivers(dc driverapi.DriverCallback) error {
 	for _, fn := range [](func(driverapi.DriverCallback) error){
 	for _, fn := range [](func(driverapi.DriverCallback) error){
 		null.Init,
 		null.Init,

+ 0 - 2
libnetwork/drivers_linux.go

@@ -8,8 +8,6 @@ import (
 	"github.com/docker/libnetwork/drivers/remote"
 	"github.com/docker/libnetwork/drivers/remote"
 )
 )
 
 
-type driverTable map[string]driverapi.Driver
-
 func initDrivers(dc driverapi.DriverCallback) error {
 func initDrivers(dc driverapi.DriverCallback) error {
 	for _, fn := range [](func(driverapi.DriverCallback) error){
 	for _, fn := range [](func(driverapi.DriverCallback) error){
 		bridge.Init,
 		bridge.Init,

+ 0 - 2
libnetwork/drivers_windows.go

@@ -5,8 +5,6 @@ import (
 	"github.com/docker/libnetwork/drivers/windows"
 	"github.com/docker/libnetwork/drivers/windows"
 )
 )
 
 
-type driverTable map[string]driverapi.Driver
-
 func initDrivers(dc driverapi.DriverCallback) error {
 func initDrivers(dc driverapi.DriverCallback) error {
 	for _, fn := range [](func(driverapi.DriverCallback) error){
 	for _, fn := range [](func(driverapi.DriverCallback) error){
 		windows.Init,
 		windows.Init,

+ 2 - 2
libnetwork/libnetwork_internal_test.go

@@ -13,14 +13,14 @@ func TestDriverRegistration(t *testing.T) {
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	err = c.(*controller).RegisterDriver(bridgeNetType, nil)
+	err = c.(*controller).RegisterDriver(bridgeNetType, nil, driverapi.Capability{})
 	if err == nil {
 	if err == nil {
 		t.Fatalf("Expecting the RegisterDriver to fail for %s", bridgeNetType)
 		t.Fatalf("Expecting the RegisterDriver to fail for %s", bridgeNetType)
 	}
 	}
 	if _, ok := err.(driverapi.ErrActiveRegistration); !ok {
 	if _, ok := err.(driverapi.ErrActiveRegistration); !ok {
 		t.Fatalf("Failed for unexpected reason: %v", err)
 		t.Fatalf("Failed for unexpected reason: %v", err)
 	}
 	}
-	err = c.(*controller).RegisterDriver("test-dummy", nil)
+	err = c.(*controller).RegisterDriver("test-dummy", nil, driverapi.Capability{})
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Test failed with an error %v", err)
 		t.Fatalf("Test failed with an error %v", err)
 	}
 	}

+ 5 - 9
libnetwork/network.go

@@ -2,7 +2,6 @@ package libnetwork
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
-	"strings"
 	"sync"
 	"sync"
 
 
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
@@ -377,12 +376,9 @@ func (n *network) EndpointByID(id string) (Endpoint, error) {
 	return nil, ErrNoSuchEndpoint(id)
 	return nil, ErrNoSuchEndpoint(id)
 }
 }
 
 
-func isReservedNetwork(name string) bool {
-	reserved := []string{"bridge", "none", "host"}
-	for _, r := range reserved {
-		if strings.EqualFold(r, name) {
-			return true
-		}
-	}
-	return false
+func (n *network) isGlobalScoped() (bool, error) {
+	n.Lock()
+	c := n.ctrlr
+	n.Unlock()
+	return c.isDriverGlobalScoped(n.networkType)
 }
 }

+ 18 - 10
libnetwork/store.go

@@ -37,8 +37,9 @@ func (c *controller) newNetworkFromStore(n *network) error {
 }
 }
 
 
 func (c *controller) updateNetworkToStore(n *network) error {
 func (c *controller) updateNetworkToStore(n *network) error {
-	if isReservedNetwork(n.Name()) {
-		return nil
+	global, err := n.isGlobalScoped()
+	if err != nil || !global {
+		return err
 	}
 	}
 	c.Lock()
 	c.Lock()
 	cs := c.store
 	cs := c.store
@@ -52,8 +53,9 @@ func (c *controller) updateNetworkToStore(n *network) error {
 }
 }
 
 
 func (c *controller) deleteNetworkFromStore(n *network) error {
 func (c *controller) deleteNetworkFromStore(n *network) error {
-	if isReservedNetwork(n.Name()) {
-		return nil
+	global, err := n.isGlobalScoped()
+	if err != nil || !global {
+		return err
 	}
 	}
 	c.Lock()
 	c.Lock()
 	cs := c.store
 	cs := c.store
@@ -111,12 +113,13 @@ func (c *controller) newEndpointFromStore(key string, ep *endpoint) error {
 
 
 func (c *controller) updateEndpointToStore(ep *endpoint) error {
 func (c *controller) updateEndpointToStore(ep *endpoint) error {
 	ep.Lock()
 	ep.Lock()
+	n := ep.network
 	name := ep.name
 	name := ep.name
-	if isReservedNetwork(ep.network.name) {
-		ep.Unlock()
-		return nil
-	}
 	ep.Unlock()
 	ep.Unlock()
+	global, err := n.isGlobalScoped()
+	if err != nil || !global {
+		return err
+	}
 	c.Lock()
 	c.Lock()
 	cs := c.store
 	cs := c.store
 	c.Unlock()
 	c.Unlock()
@@ -137,9 +140,14 @@ func (c *controller) getEndpointFromStore(eid types.UUID) (*endpoint, error) {
 }
 }
 
 
 func (c *controller) deleteEndpointFromStore(ep *endpoint) error {
 func (c *controller) deleteEndpointFromStore(ep *endpoint) error {
-	if isReservedNetwork(ep.network.Name()) {
-		return nil
+	ep.Lock()
+	n := ep.network
+	ep.Unlock()
+	global, err := n.isGlobalScoped()
+	if err != nil || !global {
+		return err
 	}
 	}
+
 	c.Lock()
 	c.Lock()
 	cs := c.store
 	cs := c.store
 	c.Unlock()
 	c.Unlock()