Browse code

Make driver packages register themselves via DriverCallback

In the present code, each driver package provides a `New()` method
which constructs a driver of its type, which is then registered with
the controller.

However, this is not suitable for the `drivers/remote` package, since
it does not provide a (singleton) driver, but a mechanism for drivers
to be added dynamically. As a result, the implementation is oddly
dual-purpose, and a spurious `"remote"` driver is added to the
controller's list of available drivers.

Instead, it is better to provide the registration callback to each
package and let it register its own driver or drivers. That way, the
singleton driver packages can construct one and register it, and the
remote package can hook the callback up with whatever the dynamic
driver mechanism turns out to be.

NB there are some method signature changes; in particular to
controller.New, which can return an error if the built-in driver
packages fail to initialise.

Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>

Michael Bridgen authored on 2015/05/11 21:46:29
Showing 16 changed files
... ...
@@ -11,7 +11,10 @@ import (
11 11
 
12 12
 func main() {
13 13
 	// Create a new controller instance
14
-	controller := libnetwork.New()
14
+	controller, err := libnetwork.New()
15
+	if err != nil {
16
+		return
17
+	}
15 18
 
16 19
 	// Select and configure the network driver
17 20
 	networkType := "bridge"
... ...
@@ -19,7 +22,7 @@ func main() {
19 19
 	driverOptions := options.Generic{}
20 20
 	genericOption := make(map[string]interface{})
21 21
 	genericOption[netlabel.GenericData] = driverOptions
22
-	err := controller.ConfigureNetworkDriver(networkType, genericOption)
22
+	err = controller.ConfigureNetworkDriver(networkType, genericOption)
23 23
 	if err != nil {
24 24
 		return
25 25
 	}
... ...
@@ -14,9 +14,12 @@ func main() {
14 14
 	net.IP = ip
15 15
 
16 16
 	options := options.Generic{"AddressIPv4": net}
17
-	controller := libnetwork.New()
17
+	controller, err := libnetwork.New()
18
+	if err != nil {
19
+		log.Fatal(err)
20
+	}
18 21
 	netType := "bridge"
19
-	err := controller.ConfigureNetworkDriver(netType, options)
22
+	err = controller.ConfigureNetworkDriver(netType, options)
20 23
 	netw, err := controller.NewNetwork(netType, "dummy")
21 24
 	if err != nil {
22 25
 		log.Fatal(err)
... ...
@@ -3,7 +3,7 @@ Package libnetwork provides the basic functionality and extension points to
3 3
 create network namespaces and allocate interfaces for containers to use.
4 4
 
5 5
         // Create a new controller instance
6
-        controller := libnetwork.New()
6
+        controller, _err := libnetwork.New()
7 7
 
8 8
         // Select and configure the network driver
9 9
         networkType := "bridge"
... ...
@@ -98,11 +98,15 @@ type controller struct {
98 98
 }
99 99
 
100 100
 // New creates a new instance of network controller.
101
-func New() NetworkController {
102
-	c := &controller{networks: networkTable{}, sandboxes: sandboxTable{}}
103
-	c.drivers = enumerateDrivers(c)
104
-	return c
105
-
101
+func New() (NetworkController, error) {
102
+	c := &controller{
103
+		networks:  networkTable{},
104
+		sandboxes: sandboxTable{},
105
+		drivers:   driverTable{}}
106
+	if err := initDrivers(c); err != nil {
107
+		return nil, err
108
+	}
109
+	return c, nil
106 110
 }
107 111
 
108 112
 func (c *controller) ConfigureNetworkDriver(networkType string, options map[string]interface{}) error {
... ...
@@ -119,7 +119,7 @@ The APIs are still work in progress and there can be changes to these based on t
119 119
 
120 120
 ## Implementations
121 121
 
122
-Libnetwork includes the following drivers:
122
+Libnetwork includes the following driver packages:
123 123
 
124 124
 - null
125 125
 - bridge
... ...
@@ -142,7 +142,7 @@ For more details on its design, please see the [Overlay Driver Design](overlay.m
142 142
 
143 143
 ### Remote
144 144
 
145
-The `remote` driver, provides a means of supporting drivers over a remote transport.
145
+The `remote` package does not provide a driver, but provides a means of supporting drivers over a remote transport.
146 146
 This allows a driver to be written in a language of your choice.
147 147
 For further details, please see the [Remote Driver Design](remote.md)
148 148
 
... ...
@@ -1,17 +1,13 @@
1
-Remote Driver
2
-=============
1
+Remote Drivers
2
+==============
3 3
 
4
-Remote driver is a special built-in driver. This driver in itself doesn't provide any networking functionality. But it depends on actual remote drivers aka `Dynamic Drivers` to provide the required networking between the containers. The dynamic drivers (such as : Weave, OVS, OVN, ACI, Calico and external networking plugins) registers itself with the Build-In `Remote` Driver.
4
+The remote driver package provides the integration point for dynamically-registered drivers.
5 5
 
6 6
 ## LibNetwork Integration
7 7
 
8
-When LibNetwork creates an instance of the Built-in `Remote` Driver via the `New()` function, it passes a `DriverCallback` as a parameter which implements the `RegisterDriver()`. The Built-in Remote Driver can use this interface to register any of the `Dynamic` Drivers/Plugins with LibNetwork's `NetworkController`
8
+When LibNetwork initialises the `Remote` package with the `Init()` function, it passes a `DriverCallback` as a parameter, which implements the `RegisterDriver()`. The Remote Driver package can use this interface to register any of the `Dynamic` Drivers/Plugins with LibNetwork's `NetworkController`.
9 9
 
10
-Please Refer to [Remote Driver Test](https://github.com/docker/libnetwork/blob/master/drivers/remote/driver_test.go) which provides an example of registering a Dynamic driver with LibNetwork.
11
-
12
-This design ensures that the implementation details of Dynamic Driver Registration mechanism is completely owned by the inbuilt-Remote driver and it also doesnt expose any of the driver layer to the North of LibNetwork (none of the LibNetwork client APIs are impacted).
13
-
14
-When the inbuilt `Remote` driver detects a `Dynamic` Driver it can call the `registerRemoteDriver` method. This method will take care of creating a new `Remote` Driver instance with the passed 'NetworkType' and register it with Libnetwork's 'NetworkController
10
+This design ensures that the implementation details (TBD) of Dynamic Driver Registration mechanism is completely owned by the inbuilt-Remote driver, and it doesn't expose any of the driver layer to the North of LibNetwork (none of the LibNetwork client APIs are impacted).
15 11
 
16 12
 ## Implementation
17 13
 
... ...
@@ -10,18 +10,16 @@ import (
10 10
 
11 11
 type driverTable map[string]driverapi.Driver
12 12
 
13
-func enumerateDrivers(dc driverapi.DriverCallback) driverTable {
14
-	drivers := make(driverTable)
15
-
16
-	for _, fn := range [](func(driverapi.DriverCallback) (string, driverapi.Driver)){
17
-		bridge.New,
18
-		host.New,
19
-		null.New,
20
-		remote.New,
13
+func initDrivers(dc driverapi.DriverCallback) error {
14
+	for _, fn := range [](func(driverapi.DriverCallback) error){
15
+		bridge.Init,
16
+		host.Init,
17
+		null.Init,
18
+		remote.Init,
21 19
 	} {
22
-		name, driver := fn(dc)
23
-		drivers[name] = driver
20
+		if err := fn(dc); err != nil {
21
+			return err
22
+		}
24 23
 	}
25
-
26
-	return drivers
24
+	return nil
27 25
 }
... ...
@@ -92,9 +92,14 @@ func init() {
92 92
 	portMapper = portmapper.New()
93 93
 }
94 94
 
95
-// New provides a new instance of bridge driver
96
-func New(dc driverapi.DriverCallback) (string, driverapi.Driver) {
97
-	return networkType, &driver{}
95
+// New constructs a new bridge driver
96
+func newDriver() driverapi.Driver {
97
+	return &driver{}
98
+}
99
+
100
+// Init registers a new instance of bridge driver
101
+func Init(dc driverapi.DriverCallback) error {
102
+	return dc.RegisterDriver(networkType, newDriver())
98 103
 }
99 104
 
100 105
 // Validate performs a static validation on the network configuration parameters.
... ...
@@ -15,7 +15,7 @@ import (
15 15
 
16 16
 func TestCreateFullOptions(t *testing.T) {
17 17
 	defer netutils.SetupTestNetNS(t)()
18
-	_, d := New(nil)
18
+	d := newDriver()
19 19
 
20 20
 	config := &Configuration{
21 21
 		EnableIPForwarding: true,
... ...
@@ -46,7 +46,7 @@ func TestCreateFullOptions(t *testing.T) {
46 46
 
47 47
 func TestCreate(t *testing.T) {
48 48
 	defer netutils.SetupTestNetNS(t)()
49
-	_, d := New(nil)
49
+	d := newDriver()
50 50
 
51 51
 	config := &NetworkConfiguration{BridgeName: DefaultBridgeName}
52 52
 	genericOption := make(map[string]interface{})
... ...
@@ -59,7 +59,7 @@ func TestCreate(t *testing.T) {
59 59
 
60 60
 func TestCreateFail(t *testing.T) {
61 61
 	defer netutils.SetupTestNetNS(t)()
62
-	_, d := New(nil)
62
+	d := newDriver()
63 63
 
64 64
 	config := &NetworkConfiguration{BridgeName: "dummy0"}
65 65
 	genericOption := make(map[string]interface{})
... ...
@@ -72,8 +72,8 @@ func TestCreateFail(t *testing.T) {
72 72
 
73 73
 func TestQueryEndpointInfo(t *testing.T) {
74 74
 	defer netutils.SetupTestNetNS(t)()
75
-
76
-	_, d := New(nil)
75
+	d := newDriver()
76
+	dd, _ := d.(*driver)
77 77
 
78 78
 	config := &NetworkConfiguration{
79 79
 		BridgeName:     DefaultBridgeName,
... ...
@@ -97,7 +97,6 @@ func TestQueryEndpointInfo(t *testing.T) {
97 97
 		t.Fatalf("Failed to create an endpoint : %s", err.Error())
98 98
 	}
99 99
 
100
-	dd := d.(*driver)
101 100
 	ep, _ := dd.network.endpoints["ep1"]
102 101
 	data, err := d.EndpointInfo(dd.network.id, ep.id)
103 102
 	if err != nil {
... ...
@@ -129,8 +128,7 @@ func TestQueryEndpointInfo(t *testing.T) {
129 129
 
130 130
 func TestCreateLinkWithOptions(t *testing.T) {
131 131
 	defer netutils.SetupTestNetNS(t)()
132
-
133
-	_, d := New(nil)
132
+	d := newDriver()
134 133
 
135 134
 	config := &NetworkConfiguration{BridgeName: DefaultBridgeName}
136 135
 	netOptions := make(map[string]interface{})
... ...
@@ -180,7 +178,7 @@ func getPortMapping() []netutils.PortBinding {
180 180
 func TestLinkContainers(t *testing.T) {
181 181
 	defer netutils.SetupTestNetNS(t)()
182 182
 
183
-	_, d := New(nil)
183
+	d := newDriver()
184 184
 
185 185
 	config := &NetworkConfiguration{
186 186
 		BridgeName:     DefaultBridgeName,
... ...
@@ -385,7 +383,7 @@ func TestValidateConfig(t *testing.T) {
385 385
 
386 386
 func TestSetDefaultGw(t *testing.T) {
387 387
 	defer netutils.SetupTestNetNS(t)()
388
-	_, d := New(nil)
388
+	d := newDriver()
389 389
 
390 390
 	_, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80")
391 391
 	gw4 := bridgeNetworks[0].IP.To4()
... ...
@@ -11,7 +11,7 @@ import (
11 11
 
12 12
 func TestLinkCreate(t *testing.T) {
13 13
 	defer netutils.SetupTestNetNS(t)()
14
-	_, d := New(nil)
14
+	d := newDriver()
15 15
 	dr := d.(*driver)
16 16
 
17 17
 	mtu := 1490
... ...
@@ -97,7 +97,7 @@ func TestLinkCreate(t *testing.T) {
97 97
 
98 98
 func TestLinkCreateTwo(t *testing.T) {
99 99
 	defer netutils.SetupTestNetNS(t)()
100
-	_, d := New(nil)
100
+	d := newDriver()
101 101
 
102 102
 	config := &NetworkConfiguration{
103 103
 		BridgeName: DefaultBridgeName,
... ...
@@ -127,7 +127,7 @@ func TestLinkCreateTwo(t *testing.T) {
127 127
 
128 128
 func TestLinkCreateNoEnableIPv6(t *testing.T) {
129 129
 	defer netutils.SetupTestNetNS(t)()
130
-	_, d := New(nil)
130
+	d := newDriver()
131 131
 
132 132
 	config := &NetworkConfiguration{
133 133
 		BridgeName: DefaultBridgeName}
... ...
@@ -156,7 +156,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
156 156
 
157 157
 func TestLinkDelete(t *testing.T) {
158 158
 	defer netutils.SetupTestNetNS(t)()
159
-	_, d := New(nil)
159
+	d := newDriver()
160 160
 
161 161
 	config := &NetworkConfiguration{
162 162
 		BridgeName: DefaultBridgeName,
... ...
@@ -18,7 +18,7 @@ func TestMain(m *testing.M) {
18 18
 
19 19
 func TestPortMappingConfig(t *testing.T) {
20 20
 	defer netutils.SetupTestNetNS(t)()
21
-	_, d := New(nil)
21
+	d := newDriver()
22 22
 
23 23
 	binding1 := netutils.PortBinding{Proto: netutils.UDP, Port: uint16(400), HostPort: uint16(54000)}
24 24
 	binding2 := netutils.PortBinding{Proto: netutils.TCP, Port: uint16(500), HostPort: uint16(65000)}
... ...
@@ -10,9 +10,9 @@ const networkType = "host"
10 10
 
11 11
 type driver struct{}
12 12
 
13
-// New provides a new instance of host driver
14
-func New(dc driverapi.DriverCallback) (string, driverapi.Driver) {
15
-	return networkType, &driver{}
13
+// Init registers a new instance of host driver
14
+func Init(dc driverapi.DriverCallback) error {
15
+	return dc.RegisterDriver(networkType, &driver{})
16 16
 }
17 17
 
18 18
 func (d *driver) Config(option map[string]interface{}) error {
... ...
@@ -10,9 +10,9 @@ const networkType = "null"
10 10
 
11 11
 type driver struct{}
12 12
 
13
-// New provides a new instance of null driver
14
-func New(dc driverapi.DriverCallback) (string, driverapi.Driver) {
15
-	return networkType, &driver{}
13
+// Init registers a new instance of null driver
14
+func Init(dc driverapi.DriverCallback) error {
15
+	return dc.RegisterDriver(networkType, &driver{})
16 16
 }
17 17
 
18 18
 func (d *driver) Config(option map[string]interface{}) error {
... ...
@@ -13,28 +13,11 @@ var errNoCallback = errors.New("No Callback handler registered with Driver")
13 13
 const remoteNetworkType = "remote"
14 14
 
15 15
 type driver struct {
16
-	networkType string
17
-	callback    driverapi.DriverCallback
18 16
 }
19 17
 
20
-// New instance of remote driver returned to LibNetwork
21
-func New(dc driverapi.DriverCallback) (string, driverapi.Driver) {
22
-	d := &driver{networkType: remoteNetworkType}
23
-	d.callback = dc
24
-	return d.networkType, d
25
-}
26
-
27
-// Internal Convenience method to register a remote driver.
28
-// The implementation of this method will change based on the dynamic driver registration design
29
-func (d *driver) registerRemoteDriver(networkType string) (driverapi.Driver, error) {
30
-	newDriver := &driver{networkType: networkType}
31
-	if d.callback == nil {
32
-		return nil, errNoCallback
33
-	}
34
-	if err := d.callback.RegisterDriver(networkType, newDriver); err != nil {
35
-		return nil, err
36
-	}
37
-	return newDriver, nil
18
+// Init does the necessary work to register remote drivers
19
+func Init(dc driverapi.DriverCallback) error {
20
+	return nil
38 21
 }
39 22
 
40 23
 func (d *driver) Config(option map[string]interface{}) error {
... ...
@@ -72,5 +55,5 @@ func (d *driver) Leave(nid, eid types.UUID, options map[string]interface{}) erro
72 72
 }
73 73
 
74 74
 func (d *driver) Type() string {
75
-	return d.networkType
75
+	return remoteNetworkType
76 76
 }
77 77
deleted file mode 100644
... ...
@@ -1,29 +0,0 @@
1
-package remote
2
-
3
-import (
4
-	"testing"
5
-
6
-	"github.com/docker/libnetwork/driverapi"
7
-)
8
-
9
-type testCallbackStruct struct {
10
-	networkType string
11
-}
12
-
13
-func (t *testCallbackStruct) RegisterDriver(networkType string, driver driverapi.Driver) error {
14
-	t.networkType = networkType
15
-	return nil
16
-}
17
-
18
-func TestCallback(t *testing.T) {
19
-	tc := &testCallbackStruct{}
20
-	_, d := New(tc)
21
-	expected := "test-dummy"
22
-	_, err := d.(*driver).registerRemoteDriver(expected)
23
-	if err != nil {
24
-		t.Fatalf("Remote Driver callback registration failed with Error : %v", err)
25
-	}
26
-	if tc.networkType != expected {
27
-		t.Fatal("Remote Driver Callback Registration failed")
28
-	}
29
-}
... ...
@@ -8,8 +8,11 @@ import (
8 8
 
9 9
 func TestDriverRegistration(t *testing.T) {
10 10
 	bridgeNetType := "bridge"
11
-	c := New()
12
-	err := c.(*controller).RegisterDriver(bridgeNetType, nil)
11
+	c, err := New()
12
+	if err != nil {
13
+		t.Fatal(err)
14
+	}
15
+	err = c.(*controller).RegisterDriver(bridgeNetType, nil)
13 16
 	if err == nil {
14 17
 		t.Fatalf("Expecting the RegisterDriver to fail for %s", bridgeNetType)
15 18
 	}
... ...
@@ -34,11 +34,14 @@ func TestMain(m *testing.M) {
34 34
 }
35 35
 
36 36
 func createTestNetwork(networkType, networkName string, option options.Generic, netOption options.Generic) (libnetwork.Network, error) {
37
-	controller := libnetwork.New()
37
+	controller, err := libnetwork.New()
38
+	if err != nil {
39
+		return nil, err
40
+	}
38 41
 	genericOption := make(map[string]interface{})
39 42
 	genericOption[netlabel.GenericData] = option
40 43
 
41
-	err := controller.ConfigureNetworkDriver(networkType, genericOption)
44
+	err = controller.ConfigureNetworkDriver(networkType, genericOption)
42 45
 	if err != nil {
43 46
 		return nil, err
44 47
 	}
... ...
@@ -219,9 +222,12 @@ func TestUnknownDriver(t *testing.T) {
219 219
 }
220 220
 
221 221
 func TestNilDriver(t *testing.T) {
222
-	controller := libnetwork.New()
222
+	controller, err := libnetwork.New()
223
+	if err != nil {
224
+		t.Fatal(err)
225
+	}
223 226
 
224
-	_, err := controller.NewNetwork("framerelay", "dummy",
227
+	_, err = controller.NewNetwork("framerelay", "dummy",
225 228
 		libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
226 229
 	if err == nil {
227 230
 		t.Fatal("Expected to fail. But instead succeeded")
... ...
@@ -233,9 +239,12 @@ func TestNilDriver(t *testing.T) {
233 233
 }
234 234
 
235 235
 func TestNoInitDriver(t *testing.T) {
236
-	controller := libnetwork.New()
236
+	controller, err := libnetwork.New()
237
+	if err != nil {
238
+		t.Fatal(err)
239
+	}
237 240
 
238
-	_, err := controller.NewNetwork("ppp", "dummy",
241
+	_, err = controller.NewNetwork("ppp", "dummy",
239 242
 		libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
240 243
 	if err == nil {
241 244
 		t.Fatal("Expected to fail. But instead succeeded")
... ...
@@ -248,12 +257,15 @@ func TestNoInitDriver(t *testing.T) {
248 248
 
249 249
 func TestDuplicateNetwork(t *testing.T) {
250 250
 	defer netutils.SetupTestNetNS(t)()
251
-	controller := libnetwork.New()
251
+	controller, err := libnetwork.New()
252
+	if err != nil {
253
+		t.Fatal(err)
254
+	}
252 255
 
253 256
 	genericOption := make(map[string]interface{})
254 257
 	genericOption[netlabel.GenericData] = options.Generic{}
255 258
 
256
-	err := controller.ConfigureNetworkDriver(bridgeNetType, genericOption)
259
+	err = controller.ConfigureNetworkDriver(bridgeNetType, genericOption)
257 260
 	if err != nil {
258 261
 		t.Fatal(err)
259 262
 	}
... ...
@@ -435,9 +447,12 @@ func TestUnknownEndpoint(t *testing.T) {
435 435
 
436 436
 func TestNetworkEndpointsWalkers(t *testing.T) {
437 437
 	defer netutils.SetupTestNetNS(t)()
438
-	controller := libnetwork.New()
438
+	controller, err := libnetwork.New()
439
+	if err != nil {
440
+		t.Fatal(err)
441
+	}
439 442
 
440
-	err := controller.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
443
+	err = controller.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
441 444
 	if err != nil {
442 445
 		t.Fatal(err)
443 446
 	}
... ...
@@ -513,9 +528,12 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
513 513
 
514 514
 func TestControllerQuery(t *testing.T) {
515 515
 	defer netutils.SetupTestNetNS(t)()
516
-	controller := libnetwork.New()
516
+	controller, err := libnetwork.New()
517
+	if err != nil {
518
+		t.Fatal(err)
519
+	}
517 520
 
518
-	err := controller.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
521
+	err = controller.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
519 522
 	if err != nil {
520 523
 		t.Fatal(err)
521 524
 	}
... ...
@@ -557,9 +575,12 @@ func TestControllerQuery(t *testing.T) {
557 557
 
558 558
 func TestNetworkQuery(t *testing.T) {
559 559
 	defer netutils.SetupTestNetNS(t)()
560
-	controller := libnetwork.New()
560
+	controller, err := libnetwork.New()
561
+	if err != nil {
562
+		t.Fatal(err)
563
+	}
561 564
 
562
-	err := controller.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
565
+	err = controller.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
563 566
 	if err != nil {
564 567
 		t.Fatal(err)
565 568
 	}
... ...
@@ -1004,7 +1025,10 @@ func createGlobalInstance(t *testing.T) {
1004 1004
 		t.Fatal(err)
1005 1005
 	}
1006 1006
 
1007
-	ctrlr = libnetwork.New()
1007
+	ctrlr, err = libnetwork.New()
1008
+	if err != nil {
1009
+		t.Fatal(err)
1010
+	}
1008 1011
 
1009 1012
 	err = ctrlr.ConfigureNetworkDriver(bridgeNetType, getEmptyGenericOption())
1010 1013
 	if err != nil {