소스 검색

Merge pull request #547 from mrjana/config

Push driver config during `Init`
Madhu Venugopal 9 년 전
부모
커밋
ba09d91d0e

+ 47 - 54
libnetwork/README.md

@@ -17,61 +17,55 @@ There are many networking solutions available to suit a broad range of use-cases
 
 
 ```go
-        // Create a new controller instance
-        controller, err := libnetwork.New()
-        if err != nil {
-                return
-        }
-
-        // Select and configure the network driver
-        networkType := "bridge"
-
-        driverOptions := options.Generic{}
-        genericOption := make(map[string]interface{})
-        genericOption[netlabel.GenericData] = driverOptions
-        err = controller.ConfigureNetworkDriver(networkType, genericOption)
-        if err != nil {
-                return
-        }
-
-        // Create a network for containers to join.
-        // NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use.
-        network, err := controller.NewNetwork(networkType, "network1")
-        if err != nil {
-                return
-        }
-
-        // For each new container: allocate IP and interfaces. The returned network
-        // settings will be used for container infos (inspect and such), as well as
-        // iptables rules for port publishing. This info is contained or accessible
-        // from the returned endpoint.
-        ep, err := network.CreateEndpoint("Endpoint1")
-        if err != nil {
-                return
-        }
-
-        // Create the sandbox for the containr.
-        sbx, err := controller.NewSandbox("container1",
-        libnetwork.OptionHostname("test"),
-        libnetwork.OptionDomainname("docker.io"))
-		
-        // A sandbox can join the endpoint via the join api.
-        // Join accepts Variadic arguments which libnetwork and Drivers can use.
-        err = ep.Join(sbx)
-        if err != nil {
-                return
-        }
-
-		// libnetwork client can check the endpoint's operational data via the Info() API
-		epInfo, err := ep.DriverInfo()
-		mapData, ok := epInfo[netlabel.PortMap]
+	// Select and configure the network driver
+	networkType := "bridge"
+
+	// Create a new controller instance
+	driverOptions := options.Generic{}
+	genericOption := make(map[string]interface{})
+	genericOption[netlabel.GenericData] = driverOptions
+	controller, err := libnetwork.New(config.OptionDriverConfig(networkType, genericOption))
+	if err != nil {
+		return
+	}
+
+	// Create a network for containers to join.
+	// NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use.
+	network, err := controller.NewNetwork(networkType, "network1")
+	if err != nil {
+		return
+	}
+
+	// For each new container: allocate IP and interfaces. The returned network
+	// settings will be used for container infos (inspect and such), as well as
+	// iptables rules for port publishing. This info is contained or accessible
+	// from the returned endpoint.
+	ep, err := network.CreateEndpoint("Endpoint1")
+	if err != nil {
+		return
+	}
+
+	// Create the sandbox for the containr.
+	sbx, err := controller.NewSandbox("container1",
+		libnetwork.OptionHostname("test"),
+		libnetwork.OptionDomainname("docker.io"))
+
+	// A sandbox can join the endpoint via the join api.
+	// Join accepts Variadic arguments which libnetwork and Drivers can use.
+	err = ep.Join(sbx)
+	if err != nil {
+		return
+	}
+
+	// libnetwork client can check the endpoint's operational data via the Info() API
+	epInfo, err := ep.DriverInfo()
+	mapData, ok := epInfo[netlabel.PortMap]
+	if ok {
+		portMapping, ok := mapData.([]types.PortBinding)
 		if ok {
-			portMapping, ok := mapData.([]types.PortBinding)
-			if ok {
-				fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
-			}
+			fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
 		}
-
+	}
 ```
 #### Current Status
 Please watch this space for updates on the progress.
@@ -87,4 +81,3 @@ Want to hack on libnetwork? [Docker's contributions guidelines](https://github.c
 
 ## Copyright and license
 Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons.
-

+ 0 - 35
libnetwork/api/api_test.go

@@ -93,11 +93,6 @@ func createTestNetwork(t *testing.T, network string) (libnetwork.NetworkControll
 		t.Fatal(err)
 	}
 
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
 	netOption := options.Generic{
 		netlabel.GenericData: options.Generic{
 			"BridgeName":            network,
@@ -184,10 +179,6 @@ func TestCreateDeleteNetwork(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	badBody, err := json.Marshal("bad body")
 	if err != nil {
@@ -262,10 +253,6 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	ops := options.Generic{
 		netlabel.GenericData: map[string]string{
@@ -536,11 +523,6 @@ func TestProcGetServices(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
 	// Create 2 networks
 	netName1 := "production"
 	netOption := options.Generic{
@@ -1124,10 +1106,6 @@ func TestCreateDeleteEndpoints(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	nc := networkCreate{Name: "firstNet", NetworkType: bridgeNetType}
 	body, err := json.Marshal(nc)
@@ -1250,10 +1228,6 @@ func TestJoinLeave(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	nb, err := json.Marshal(networkCreate{Name: "network", NetworkType: bridgeNetType})
 	if err != nil {
@@ -1694,11 +1668,6 @@ func TestHttpHandlerUninit(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
 	h := &httpHandler{c: c}
 	h.initRouter()
 	if h.r == nil {
@@ -1796,10 +1765,6 @@ func TestEndToEnd(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = c.ConfigureNetworkDriver(bridgeNetType, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
 
 	handleRequest := NewHTTPHandler(c)
 

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

@@ -65,12 +65,6 @@ func main() {
 		return
 	}
 
-	r := &router{}
-	if err := overlay.Init(r); err != nil {
-		fmt.Printf("Failed to initialize overlay driver: %v\n", err)
-		os.Exit(1)
-	}
-
 	opt := make(map[string]interface{})
 	if len(os.Args) > 1 {
 		opt[netlabel.OverlayBindInterface] = os.Args[1]
@@ -85,7 +79,11 @@ func main() {
 		opt[netlabel.KVProviderURL] = os.Args[4]
 	}
 
-	r.d.Config(opt)
+	r := &router{}
+	if err := overlay.Init(r, opt); err != nil {
+		fmt.Printf("Failed to initialize overlay driver: %v\n", err)
+		os.Exit(1)
+	}
 
 	if err := r.d.CreateNetwork("testnetwork",
 		map[string]interface{}{}); err != nil {

+ 3 - 7
libnetwork/cmd/readme_test/readme.go

@@ -4,25 +4,21 @@ import (
 	"fmt"
 
 	"github.com/docker/libnetwork"
+	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/types"
 )
 
 func main() {
-	// Create a new controller instance
-	controller, err := libnetwork.New()
-	if err != nil {
-		return
-	}
-
 	// Select and configure the network driver
 	networkType := "bridge"
 
+	// Create a new controller instance
 	driverOptions := options.Generic{}
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = driverOptions
-	err = controller.ConfigureNetworkDriver(networkType, genericOption)
+	controller, err := libnetwork.New(config.OptionDriverConfig(networkType, genericOption))
 	if err != nil {
 		return
 	}

+ 0 - 12
libnetwork/cmd/test/libnetwork.toml

@@ -1,12 +0,0 @@
-title = "LibNetwork Configuration file"
-
-[daemon]
-  debug = false
-[cluster]
-  discovery = "token://22aa23948f4f6b31230687689636959e"
-  Address = "1.1.1.1"
-[datastore]
-  embedded = false
-[datastore.client]
-  provider = "consul"
-  Address = "localhost:8500"

+ 0 - 49
libnetwork/cmd/test/main.go

@@ -1,49 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"net"
-	"time"
-
-	log "github.com/Sirupsen/logrus"
-
-	"github.com/docker/libnetwork"
-	"github.com/docker/libnetwork/options"
-)
-
-func main() {
-	log.SetLevel(log.DebugLevel)
-	controller, err := libnetwork.New()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	netType := "null"
-	ip, net, _ := net.ParseCIDR("192.168.100.1/24")
-	net.IP = ip
-	options := options.Generic{"AddressIPv4": net}
-
-	err = controller.ConfigureNetworkDriver(netType, options)
-	for i := 0; i < 10; i++ {
-		netw, err := controller.NewNetwork(netType, fmt.Sprintf("Gordon-%d", i))
-		if err != nil {
-			if _, ok := err.(libnetwork.NetworkNameError); !ok {
-				log.Fatal(err)
-			}
-		} else {
-			fmt.Println("Network Created Successfully :", netw)
-		}
-		netw, _ = controller.NetworkByName(fmt.Sprintf("Gordon-%d", i))
-		_, err = netw.CreateEndpoint(fmt.Sprintf("Gordon-Ep-%d", i), nil)
-		if err != nil {
-			log.Fatalf("Error creating endpoint 1 %v", err)
-		}
-
-		_, err = netw.CreateEndpoint(fmt.Sprintf("Gordon-Ep2-%d", i), nil)
-		if err != nil {
-			log.Fatalf("Error creating endpoint 2 %v", err)
-		}
-
-		time.Sleep(2 * time.Second)
-	}
-}

+ 8 - 0
libnetwork/config/config.go

@@ -21,6 +21,7 @@ type DaemonCfg struct {
 	DefaultNetwork string
 	DefaultDriver  string
 	Labels         []string
+	DriverCfg      map[string]interface{}
 }
 
 // ClusterCfg represents cluster configuration
@@ -71,6 +72,13 @@ func OptionDefaultDriver(dd string) Option {
 	}
 }
 
+// OptionDriverConfig returns an option setter for driver configuration.
+func OptionDriverConfig(networkType string, config map[string]interface{}) Option {
+	return func(c *Config) {
+		c.Daemon.DriverCfg[networkType] = config
+	}
+}
+
 // OptionLabels function returns an option setter for labels
 func OptionLabels(labels []string) Option {
 	return func(c *Config) {

+ 5 - 40
libnetwork/controller.go

@@ -47,7 +47,6 @@ import (
 	"container/heap"
 	"fmt"
 	"net"
-	"strings"
 	"sync"
 
 	log "github.com/Sirupsen/logrus"
@@ -57,7 +56,6 @@ import (
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/hostdiscovery"
-	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/osl"
 	"github.com/docker/libnetwork/types"
 )
@@ -68,9 +66,6 @@ type NetworkController interface {
 	// ID provides an unique identity for the controller
 	ID() string
 
-	// ConfigureNetworkDriver applies the passed options to the driver instance for the specified network type
-	ConfigureNetworkDriver(networkType string, options map[string]interface{}) error
-
 	// Config method returns the bootup configuration for the controller
 	Config() config.Config
 
@@ -139,7 +134,11 @@ type controller struct {
 func New(cfgOptions ...config.Option) (NetworkController, error) {
 	var cfg *config.Config
 	if len(cfgOptions) > 0 {
-		cfg = &config.Config{}
+		cfg = &config.Config{
+			Daemon: config.DaemonCfg{
+				DriverCfg: make(map[string]interface{}),
+			},
+		}
 		cfg.ProcessOptions(cfgOptions...)
 	}
 	c := &controller{
@@ -207,16 +206,6 @@ func (c *controller) Config() config.Config {
 	return *c.cfg
 }
 
-func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error {
-	c.Lock()
-	dd, ok := c.drivers[networkType]
-	c.Unlock()
-	if !ok {
-		return NetworkTypeError(networkType)
-	}
-	return dd.driver.Config(options)
-}
-
 func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver, capability driverapi.Capability) error {
 	if !config.IsValidName(networkType) {
 		return ErrInvalidName(networkType)
@@ -228,32 +217,8 @@ func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver,
 		return driverapi.ErrActiveRegistration(networkType)
 	}
 	c.drivers[networkType] = &driverData{driver, capability}
-
-	if c.cfg == nil {
-		c.Unlock()
-		return nil
-	}
-
-	opt := make(map[string]interface{})
-	for _, label := range c.cfg.Daemon.Labels {
-		if strings.HasPrefix(label, netlabel.DriverPrefix+"."+networkType) {
-			opt[netlabel.Key(label)] = netlabel.Value(label)
-		}
-	}
-
-	if capability.Scope == driverapi.GlobalScope && c.validateDatastoreConfig() {
-		opt[netlabel.KVProvider] = c.cfg.Datastore.Client.Provider
-		opt[netlabel.KVProviderURL] = c.cfg.Datastore.Client.Address
-	}
-
 	c.Unlock()
 
-	if len(opt) != 0 {
-		if err := driver.Config(opt); err != nil {
-			return err
-		}
-	}
-
 	return nil
 }
 

+ 0 - 3
libnetwork/driverapi/driverapi.go

@@ -7,9 +7,6 @@ const NetworkPluginEndpointType = "NetworkDriver"
 
 // Driver is an interface that every plugin driver needs to implement.
 type Driver interface {
-	// Push driver specific config to the driver
-	Config(options map[string]interface{}) error
-
 	// CreateNetwork invokes the driver method to create a network passing
 	// the network id and network specific config. The config mechanism will
 	// eventually be replaced with labels which are yet to be introduced.

+ 55 - 0
libnetwork/drivers.go

@@ -0,0 +1,55 @@
+package libnetwork
+
+import (
+	"strings"
+
+	"github.com/docker/libnetwork/driverapi"
+	"github.com/docker/libnetwork/netlabel"
+)
+
+type initializer struct {
+	fn    func(driverapi.DriverCallback, map[string]interface{}) error
+	ntype string
+}
+
+func initDrivers(c *controller) error {
+	for _, i := range getInitializers() {
+		if err := i.fn(c, makeDriverConfig(c, i.ntype)); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func makeDriverConfig(c *controller, ntype string) map[string]interface{} {
+	if c.cfg == nil {
+		return nil
+	}
+
+	config := make(map[string]interface{})
+
+	if c.validateDatastoreConfig() {
+		config[netlabel.KVProvider] = c.cfg.Datastore.Client.Provider
+		config[netlabel.KVProviderURL] = c.cfg.Datastore.Client.Address
+	}
+
+	for _, label := range c.cfg.Daemon.Labels {
+		if !strings.HasPrefix(netlabel.Key(label), netlabel.DriverPrefix+"."+ntype) {
+			continue
+		}
+
+		config[netlabel.Key(label)] = netlabel.Value(label)
+	}
+
+	drvCfg, ok := c.cfg.Daemon.DriverCfg[ntype]
+	if !ok {
+		return config
+	}
+
+	for k, v := range drvCfg.(map[string]interface{}) {
+		config[k] = v
+	}
+
+	return config
+}

+ 10 - 23
libnetwork/drivers/bridge/bridge.go

@@ -97,7 +97,6 @@ type bridgeNetwork struct {
 
 type driver struct {
 	config      *configuration
-	configured  bool
 	network     *bridgeNetwork
 	natChain    *iptables.ChainInfo
 	filterChain *iptables.ChainInfo
@@ -106,13 +105,13 @@ type driver struct {
 }
 
 // New constructs a new bridge driver
-func newDriver() driverapi.Driver {
+func newDriver() *driver {
 	ipAllocator = ipallocator.New()
 	return &driver{networks: map[string]*bridgeNetwork{}, config: &configuration{}}
 }
 
 // Init registers a new instance of bridge driver
-func Init(dc driverapi.DriverCallback) error {
+func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
 	if _, err := os.Stat("/proc/sys/net/bridge"); err != nil {
 		if out, err := exec.Command("modprobe", "-va", "bridge", "br_netfilter").CombinedOutput(); err != nil {
 			logrus.Warnf("Running modprobe bridge br_netfilter failed with message: %s, error: %v", out, err)
@@ -128,10 +127,15 @@ func Init(dc driverapi.DriverCallback) error {
 		logrus.Warnf("Failed to remove existing iptables entries in %s : %v", DockerChain, err)
 	}
 
+	d := newDriver()
+	if err := d.configure(config); err != nil {
+		return err
+	}
+
 	c := driverapi.Capability{
 		Scope: driverapi.LocalScope,
 	}
-	return dc.RegisterDriver(networkType, newDriver(), c)
+	return dc.RegisterDriver(networkType, d, c)
 }
 
 // Validate performs a static validation on the network configuration parameters.
@@ -426,17 +430,13 @@ func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridge
 	return nil
 }
 
-func (d *driver) Config(option map[string]interface{}) error {
+func (d *driver) configure(option map[string]interface{}) error {
 	var config *configuration
 	var err error
 
 	d.Lock()
 	defer d.Unlock()
 
-	if d.configured {
-		return &ErrConfigExists{}
-	}
-
 	genericData, ok := option[netlabel.GenericData]
 	if !ok || genericData == nil {
 		return nil
@@ -469,7 +469,6 @@ func (d *driver) Config(option map[string]interface{}) error {
 		}
 	}
 
-	d.configured = true
 	d.config = config
 	return nil
 }
@@ -567,20 +566,12 @@ func (d *driver) getNetworks() []*bridgeNetwork {
 
 // Create a new network using bridge plugin
 func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
-	var (
-		err          error
-		configLocked bool
-	)
+	var err error
 
 	defer osl.InitOSContext()()
 
 	// Sanity checks
 	d.Lock()
-	if !d.configured {
-		configLocked = true
-		d.configured = true
-	}
-
 	if _, ok := d.networks[id]; ok {
 		d.Unlock()
 		return types.ForbiddenErrorf("network %s exists", id)
@@ -619,10 +610,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
 	defer func() {
 		if err != nil {
 			d.Lock()
-			if configLocked {
-				d.configured = false
-			}
-
 			delete(d.networks, id)
 			d.Unlock()
 		}

+ 15 - 17
libnetwork/drivers/bridge/bridge_test.go

@@ -44,7 +44,7 @@ func TestCreateFullOptions(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = config
 
-	if err := d.Config(genericOption); err != nil {
+	if err := d.configure(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -86,7 +86,7 @@ func TestCreate(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -119,7 +119,7 @@ func TestCreateFail(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -135,7 +135,6 @@ func TestCreateFail(t *testing.T) {
 func TestCreateMultipleNetworks(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
-	dd, _ := d.(*driver)
 
 	config := &configuration{
 		EnableIPTables: true,
@@ -143,7 +142,7 @@ func TestCreateMultipleNetworks(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = config
 
-	if err := d.Config(genericOption); err != nil {
+	if err := d.configure(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -167,7 +166,7 @@ func TestCreateMultipleNetworks(t *testing.T) {
 	}
 
 	// Verify the network isolation rules are installed, each network subnet should appear 4 times
-	verifyV4INCEntries(dd.networks, 4, t)
+	verifyV4INCEntries(d.networks, 4, t)
 
 	config4 := &networkConfiguration{BridgeName: "net_test_4", AllowNonDefaultBridge: true}
 	genericOption[netlabel.GenericData] = config4
@@ -176,19 +175,19 @@ func TestCreateMultipleNetworks(t *testing.T) {
 	}
 
 	// Now 6 times
-	verifyV4INCEntries(dd.networks, 6, t)
+	verifyV4INCEntries(d.networks, 6, t)
 
 	d.DeleteNetwork("1")
-	verifyV4INCEntries(dd.networks, 4, t)
+	verifyV4INCEntries(d.networks, 4, t)
 
 	d.DeleteNetwork("2")
-	verifyV4INCEntries(dd.networks, 2, t)
+	verifyV4INCEntries(d.networks, 2, t)
 
 	d.DeleteNetwork("3")
-	verifyV4INCEntries(dd.networks, 0, t)
+	verifyV4INCEntries(d.networks, 0, t)
 
 	d.DeleteNetwork("4")
-	verifyV4INCEntries(dd.networks, 0, t)
+	verifyV4INCEntries(d.networks, 0, t)
 }
 
 func verifyV4INCEntries(networks map[string]*bridgeNetwork, numEntries int, t *testing.T) {
@@ -290,7 +289,6 @@ func TestQueryEndpointInfoHairpin(t *testing.T) {
 func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
-	dd, _ := d.(*driver)
 
 	config := &configuration{
 		EnableIPTables:      true,
@@ -299,7 +297,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = config
 
-	if err := d.Config(genericOption); err != nil {
+	if err := d.configure(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -325,7 +323,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
 		t.Fatalf("Failed to create an endpoint : %s", err.Error())
 	}
 
-	network, ok := dd.networks["net1"]
+	network, ok := d.networks["net1"]
 	if !ok {
 		t.Fatalf("Cannot find network %s inside driver", "net1")
 	}
@@ -362,7 +360,7 @@ func TestCreateLinkWithOptions(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -428,7 +426,7 @@ func TestLinkContainers(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = config
 
-	if err := d.Config(genericOption); err != nil {
+	if err := d.configure(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -638,7 +636,7 @@ func TestSetDefaultGw(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 

+ 5 - 6
libnetwork/drivers/bridge/network_test.go

@@ -12,9 +12,8 @@ import (
 func TestLinkCreate(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
-	dr := d.(*driver)
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -79,7 +78,7 @@ func TestLinkCreate(t *testing.T) {
 		t.Fatalf("Could not find source link %s: %v", te.iface.srcName, err)
 	}
 
-	n, ok := dr.networks["dummy"]
+	n, ok := d.networks["dummy"]
 	if !ok {
 		t.Fatalf("Cannot find network %s inside driver", "dummy")
 	}
@@ -108,7 +107,7 @@ func TestLinkCreateTwo(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -144,7 +143,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -178,7 +177,7 @@ func TestLinkDelete(t *testing.T) {
 	defer testutils.SetupTestOSContext(t)()
 	d := newDriver()
 
-	if err := d.Config(nil); err != nil {
+	if err := d.configure(nil); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 

+ 2 - 3
libnetwork/drivers/bridge/port_mapping_test.go

@@ -27,7 +27,7 @@ func TestPortMappingConfig(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = config
 
-	if err := d.Config(genericOption); err != nil {
+	if err := d.configure(genericOption); err != nil {
 		t.Fatalf("Failed to setup driver config: %v", err)
 	}
 
@@ -55,8 +55,7 @@ func TestPortMappingConfig(t *testing.T) {
 		t.Fatalf("Failed to create the endpoint: %s", err.Error())
 	}
 
-	dd := d.(*driver)
-	network, ok := dd.networks["dummy"]
+	network, ok := d.networks["dummy"]
 	if !ok {
 		t.Fatalf("Cannot find network %s inside driver", "dummy")
 	}

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

@@ -15,17 +15,13 @@ type driver struct {
 }
 
 // Init registers a new instance of host driver
-func Init(dc driverapi.DriverCallback) error {
+func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
 	c := driverapi.Capability{
 		Scope: driverapi.LocalScope,
 	}
 	return dc.RegisterDriver(networkType, &driver{}, c)
 }
 
-func (d *driver) Config(option map[string]interface{}) error {
-	return nil
-}
-
 func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
 	d.Lock()
 	defer d.Unlock()

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

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

+ 14 - 4
libnetwork/drivers/overlay/overlay.go

@@ -67,19 +67,25 @@ func onceInit() {
 }
 
 // Init registers a new instance of overlay driver
-func Init(dc driverapi.DriverCallback) error {
+func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
 	once.Do(onceInit)
 
 	c := driverapi.Capability{
 		Scope: driverapi.GlobalScope,
 	}
 
-	return dc.RegisterDriver(networkType, &driver{
+	d := &driver{
 		networks: networkTable{},
 		peerDb: peerNetworkMap{
 			mp: map[string]peerMap{},
 		},
-	}, c)
+	}
+
+	if err := d.configure(config); err != nil {
+		return err
+	}
+
+	return dc.RegisterDriver(networkType, d, c)
 }
 
 // Fini cleans up the driver resources
@@ -95,10 +101,14 @@ func Fini(drv driverapi.Driver) {
 	}
 }
 
-func (d *driver) Config(option map[string]interface{}) error {
+func (d *driver) configure(option map[string]interface{}) error {
 	var onceDone bool
 	var err error
 
+	if len(option) == 0 {
+		return nil
+	}
+
 	d.Do(func() {
 		onceDone = true
 

+ 11 - 23
libnetwork/drivers/overlay/overlay_test.go

@@ -5,24 +5,22 @@ import (
 	"time"
 
 	"github.com/docker/libnetwork/driverapi"
+	"github.com/docker/libnetwork/netlabel"
 	_ "github.com/docker/libnetwork/testutils"
 )
 
 type driverTester struct {
 	t *testing.T
-	d driverapi.Driver
+	d *driver
 }
 
 const testNetworkType = "overlay"
 
 func setupDriver(t *testing.T) *driverTester {
-	dt := &driverTester{t: t}
-	if err := Init(dt); err != nil {
-		t.Fatal(err)
-	}
-
 	opt := make(map[string]interface{})
-	if err := dt.d.Config(opt); err != nil {
+	opt[netlabel.OverlayBindInterface] = "eth0"
+	dt := &driverTester{t: t}
+	if err := Init(dt, opt); err != nil {
 		t.Fatal(err)
 	}
 
@@ -60,14 +58,14 @@ func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
 }
 
 func TestOverlayInit(t *testing.T) {
-	if err := Init(&driverTester{t: t}); err != nil {
+	if err := Init(&driverTester{t: t}, nil); err != nil {
 		t.Fatal(err)
 	}
 }
 
 func TestOverlayFiniWithoutConfig(t *testing.T) {
 	dt := &driverTester{t: t}
-	if err := Init(dt); err != nil {
+	if err := Init(dt, nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -76,11 +74,11 @@ func TestOverlayFiniWithoutConfig(t *testing.T) {
 
 func TestOverlayNilConfig(t *testing.T) {
 	dt := &driverTester{t: t}
-	if err := Init(dt); err != nil {
+	if err := Init(dt, nil); err != nil {
 		t.Fatal(err)
 	}
 
-	if err := dt.d.Config(nil); err != nil {
+	if err := dt.d.configure(nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -92,7 +90,7 @@ func TestOverlayConfig(t *testing.T) {
 
 	time.Sleep(1 * time.Second)
 
-	d := dt.d.(*driver)
+	d := dt.d
 	if d.notifyCh == nil {
 		t.Fatal("Driver notify channel wasn't initialzed after Config method")
 	}
@@ -108,19 +106,9 @@ func TestOverlayConfig(t *testing.T) {
 	cleanupDriver(t, dt)
 }
 
-func TestOverlayMultipleConfig(t *testing.T) {
-	dt := setupDriver(t)
-
-	if err := dt.d.Config(nil); err == nil {
-		t.Fatal("Expected a failure, instead succeded")
-	}
-
-	cleanupDriver(t, dt)
-}
-
 func TestOverlayType(t *testing.T) {
 	dt := &driverTester{t: t}
-	if err := Init(dt); err != nil {
+	if err := Init(dt, nil); err != nil {
 		t.Fatal(err)
 	}
 

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

@@ -26,7 +26,7 @@ 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) error {
+func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
 	plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
 		// negotiate driver capability with client
 		d := newDriver(name, client)

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

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

+ 4 - 10
libnetwork/drivers_freebsd.go

@@ -1,19 +1,13 @@
 package libnetwork
 
 import (
-	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/drivers/null"
 	"github.com/docker/libnetwork/drivers/remote"
 )
 
-func initDrivers(dc driverapi.DriverCallback) error {
-	for _, fn := range [](func(driverapi.DriverCallback) error){
-		null.Init,
-		remote.Init,
-	} {
-		if err := fn(dc); err != nil {
-			return err
-		}
+func getInitializers() []initializer {
+	return []initializer{
+		{null.Init, "null"},
+		{remote.Init, "remote"},
 	}
-	return nil
 }

+ 8 - 14
libnetwork/drivers_linux.go

@@ -1,25 +1,19 @@
 package libnetwork
 
 import (
-	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/drivers/bridge"
 	"github.com/docker/libnetwork/drivers/host"
 	"github.com/docker/libnetwork/drivers/null"
-	o "github.com/docker/libnetwork/drivers/overlay"
+	"github.com/docker/libnetwork/drivers/overlay"
 	"github.com/docker/libnetwork/drivers/remote"
 )
 
-func initDrivers(dc driverapi.DriverCallback) error {
-	for _, fn := range [](func(driverapi.DriverCallback) error){
-		bridge.Init,
-		host.Init,
-		null.Init,
-		remote.Init,
-		o.Init,
-	} {
-		if err := fn(dc); err != nil {
-			return err
-		}
+func getInitializers() []initializer {
+	return []initializer{
+		{bridge.Init, "bridge"},
+		{host.Init, "host"},
+		{null.Init, "null"},
+		{remote.Init, "remote"},
+		{overlay.Init, "overlay"},
 	}
-	return nil
 }

+ 4 - 12
libnetwork/drivers_windows.go

@@ -1,17 +1,9 @@
 package libnetwork
 
-import (
-	"github.com/docker/libnetwork/driverapi"
-	"github.com/docker/libnetwork/drivers/windows"
-)
+import "github.com/docker/libnetwork/drivers/windows"
 
-func initDrivers(dc driverapi.DriverCallback) error {
-	for _, fn := range [](func(driverapi.DriverCallback) error){
-		windows.Init,
-	} {
-		if err := fn(dc); err != nil {
-			return err
-		}
+func getInitializers() []initializer {
+	return []initializer{
+		{windows.Init, "windows"},
 	}
-	return nil
 }

+ 9 - 12
libnetwork/libnetwork_test.go

@@ -21,6 +21,7 @@ import (
 	"github.com/docker/docker/pkg/plugins"
 	"github.com/docker/docker/pkg/reexec"
 	"github.com/docker/libnetwork"
+	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/netlabel"
@@ -48,17 +49,6 @@ func TestMain(m *testing.M) {
 	if err := createController(); err != nil {
 		os.Exit(1)
 	}
-	option := options.Generic{
-		"EnableIPForwarding": true,
-	}
-
-	genericOption := make(map[string]interface{})
-	genericOption[netlabel.GenericData] = option
-
-	err := controller.ConfigureNetworkDriver(bridgeNetType, genericOption)
-	if err != nil {
-		os.Exit(1)
-	}
 
 	libnetwork.SetTestDataStore(controller, datastore.NewCustomDataStore(datastore.NewMockStore()))
 
@@ -68,7 +58,14 @@ func TestMain(m *testing.M) {
 func createController() error {
 	var err error
 
-	controller, err = libnetwork.New()
+	option := options.Generic{
+		"EnableIPForwarding": true,
+	}
+
+	genericOption := make(map[string]interface{})
+	genericOption[netlabel.GenericData] = option
+
+	controller, err = libnetwork.New(config.OptionDriverConfig(bridgeNetType, genericOption))
 	if err != nil {
 		return err
 	}

+ 5 - 6
libnetwork/sandbox_test.go

@@ -3,6 +3,7 @@ package libnetwork
 import (
 	"testing"
 
+	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/osl"
@@ -14,21 +15,19 @@ func createEmptyCtrlr() *controller {
 }
 
 func getTestEnv(t *testing.T) (NetworkController, Network, Network) {
-	c, err := New()
-	if err != nil {
-		t.Fatal(err)
-	}
+	netType := "bridge"
 
 	option := options.Generic{
 		"EnableIPForwarding": true,
 	}
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = option
-	if err := c.ConfigureNetworkDriver("bridge", genericOption); err != nil {
+
+	c, err := New(config.OptionDriverConfig(netType, genericOption))
+	if err != nil {
 		t.Fatal(err)
 	}
 
-	netType := "bridge"
 	name1 := "test_nw_1"
 	netOption1 := options.Generic{
 		netlabel.GenericData: options.Generic{