Push driver config during Init

Currently the driver configuration is pushed through a separate
api. This makes driver configuration possible at any arbitrary
time. This unncessarily complicates the driver implementation.
More importantly the driver does not get access to it's
configuration before it can do the handshake with libnetwork.
This make the internal drivers a little bit different to
external plugins which can get their configuration before the handshake
with libnetwork.

This PR attempts to fix that mismatch between internal drivers and
external plugins.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
Jana Radhakrishnan
2015-09-19 08:43:34 -07:00
parent 00a92f066e
commit 900aca112b
25 changed files with 208 additions and 347 deletions
+10 -23
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}