瀏覽代碼

Add driver api enhancements for gossip

With the introduction of a driver generic gossip in libnetwork it is not
necessary for drivers to run their own gossip protocol (like what
overlay driver is doing currently) but instead rely on the gossip
instance run centrally in libnetwork. In order to achieve this, certain
enhancements to driver api are needed. This api aims to provide these
enhancements.

The new api provides a way for drivers to register interest on table
names of their choice by returning a list of table names of interest as
a response to CreateNetwork. By doing that they will get notified if a
CRUD operation happened on the tables of their interest, via the newly
added EventNotify call.

Drivers themselves can add entries to any table during a Join call by
invoking AddTableEntry method any number of times during the Join
call. These entries lifetime is the same as the endpoint itself. As soon
as the container leaves the endpoint, those entries added by driver
during that endpoint's Join call will be automatically removed by
libnetwork. This action may trigger notification of such deletion to all
driver instances in the cluster who have registered interest in that
table's notification.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 9 年之前
父節點
當前提交
6fb69f0816

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

@@ -92,6 +92,10 @@ func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int,
 	return nil
 	return nil
 }
 }
 
 
+func (ep *endpoint) AddTableEntry(tableName string, key string, value []byte) error {
+	return nil
+}
+
 func (ep *endpoint) DisableGatewayService() {}
 func (ep *endpoint) DisableGatewayService() {}
 
 
 func main() {
 func main() {
@@ -120,7 +124,7 @@ func main() {
 	}
 	}
 
 
 	if err := r.d.CreateNetwork("testnetwork",
 	if err := r.d.CreateNetwork("testnetwork",
-		map[string]interface{}{}, nil, nil); err != nil {
+		map[string]interface{}{}, nil, nil, nil); err != nil {
 		fmt.Printf("Failed to create network in the driver: %v\n", err)
 		fmt.Printf("Failed to create network in the driver: %v\n", err)
 		os.Exit(1)
 		os.Exit(1)
 	}
 	}

+ 1 - 1
libnetwork/controller.go

@@ -506,7 +506,7 @@ func (c *controller) addNetwork(n *network) error {
 	}
 	}
 
 
 	// Create the network
 	// Create the network
-	if err := d.CreateNetwork(n.id, n.generic, n.getIPData(4), n.getIPData(6)); err != nil {
+	if err := d.CreateNetwork(n.id, n.generic, nil, n.getIPData(4), n.getIPData(6)); err != nil {
 		return err
 		return err
 	}
 	}
 
 

+ 39 - 4
libnetwork/driverapi/driverapi.go

@@ -23,10 +23,15 @@ type Driver interface {
 	// associated with a given network id.
 	// associated with a given network id.
 	NetworkFree(nid string) error
 	NetworkFree(nid string) 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.
-	CreateNetwork(nid string, options map[string]interface{}, ipV4Data, ipV6Data []IPAMData) 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. The driver can return a
+	// list of table names for which it is interested in receiving
+	// notification when a CRUD operation is performed on any
+	// entry in that table. This will be ignored for local scope
+	// drivers.
+	CreateNetwork(nid string, options map[string]interface{}, nInfo NetworkInfo, ipV4Data, ipV6Data []IPAMData) error
 
 
 	// DeleteNetwork invokes the driver method to delete network passing
 	// DeleteNetwork invokes the driver method to delete network passing
 	// the network id.
 	// the network id.
@@ -60,10 +65,24 @@ type Driver interface {
 	// programming that was done so far
 	// programming that was done so far
 	RevokeExternalConnectivity(nid, eid string) error
 	RevokeExternalConnectivity(nid, eid string) error
 
 
+	// EventNotify notifies the driver when a CRUD operation has
+	// happened on a table of its interest as soon as this node
+	// receives such an event in the gossip layer. This method is
+	// only invoked for the global scope driver.
+	EventNotify(event EventType, nid string, tableName string, key string, value []byte)
+
 	// Type returns the the type of this driver, the network type this driver manages
 	// Type returns the the type of this driver, the network type this driver manages
 	Type() string
 	Type() string
 }
 }
 
 
+// NetworkInfo provides a go interface for drivers to provide network
+// specific information to libnetwork.
+type NetworkInfo interface {
+	// TableEventRegister registers driver interest in a given
+	// table name.
+	TableEventRegister(tableName string) error
+}
+
 // InterfaceInfo provides a go interface for drivers to retrive
 // InterfaceInfo provides a go interface for drivers to retrive
 // network information to interface resources.
 // network information to interface resources.
 type InterfaceInfo interface {
 type InterfaceInfo interface {
@@ -112,6 +131,10 @@ type JoinInfo interface {
 
 
 	// DisableGatewayService tells libnetwork not to provide Default GW for the container
 	// DisableGatewayService tells libnetwork not to provide Default GW for the container
 	DisableGatewayService()
 	DisableGatewayService()
+
+	// AddTableEntry adds a table entry to the gossip layer
+	// passing the table name, key and an opaque value.
+	AddTableEntry(tableName string, key string, value []byte) error
 }
 }
 
 
 // DriverCallback provides a Callback interface for Drivers into LibNetwork
 // DriverCallback provides a Callback interface for Drivers into LibNetwork
@@ -134,3 +157,15 @@ type IPAMData struct {
 	Gateway      *net.IPNet
 	Gateway      *net.IPNet
 	AuxAddresses map[string]*net.IPNet
 	AuxAddresses map[string]*net.IPNet
 }
 }
+
+// EventType defines a type for the CRUD event
+type EventType uint8
+
+const (
+	// Create event is generated when a table entry is created,
+	Create EventType = 1 + iota
+	// Update event is generated when a table entry is updated.
+	Update
+	// Delete event is generated when a table entry is deleted.
+	Delete
+)

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

@@ -543,8 +543,11 @@ func (d *driver) NetworkFree(id string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
 
 
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
 // Create a new network using bridge plugin
 // Create a new network using bridge plugin
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
 	if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
 		return types.BadRequestErrorf("ipv4 pool is empty")
 		return types.BadRequestErrorf("ipv4 pool is empty")
 	}
 	}

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

@@ -69,7 +69,7 @@ func TestCreateFullOptions(t *testing.T) {
 			AuxAddresses: map[string]*net.IPNet{DefaultGatewayV4AuxKey: defgw},
 			AuxAddresses: map[string]*net.IPNet{DefaultGatewayV4AuxKey: defgw},
 		},
 		},
 	}
 	}
-	err := d.CreateNetwork("dummy", netOption, ipdList, nil)
+	err := d.CreateNetwork("dummy", netOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -95,7 +95,7 @@ func TestCreateNoConfig(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = netconfig
 	genericOption[netlabel.GenericData] = netconfig
 
 
-	if err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil); err != nil {
+	if err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t), nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 }
 }
@@ -142,7 +142,7 @@ func TestCreateFullOptionsLabels(t *testing.T) {
 		},
 		},
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", netOption, ipdList, ipd6List)
+	err := d.CreateNetwork("dummy", netOption, nil, ipdList, ipd6List)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -211,11 +211,11 @@ func TestCreate(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = netconfig
 	genericOption[netlabel.GenericData] = netconfig
 
 
-	if err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil); err != nil {
+	if err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t), nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
-	err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil)
+	err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t), nil)
 	if err == nil {
 	if err == nil {
 		t.Fatalf("Expected bridge driver to refuse creation of second network with default name")
 		t.Fatalf("Expected bridge driver to refuse creation of second network with default name")
 	}
 	}
@@ -236,7 +236,7 @@ func TestCreateFail(t *testing.T) {
 	genericOption := make(map[string]interface{})
 	genericOption := make(map[string]interface{})
 	genericOption[netlabel.GenericData] = netconfig
 	genericOption[netlabel.GenericData] = netconfig
 
 
-	if err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil); err == nil {
+	if err := d.CreateNetwork("dummy", genericOption, nil, getIPv4Data(t), nil); err == nil {
 		t.Fatal("Bridge creation was expected to fail")
 		t.Fatal("Bridge creation was expected to fail")
 	}
 	}
 }
 }
@@ -258,13 +258,13 @@ func TestCreateMultipleNetworks(t *testing.T) {
 	config1 := &networkConfiguration{BridgeName: "net_test_1"}
 	config1 := &networkConfiguration{BridgeName: "net_test_1"}
 	genericOption = make(map[string]interface{})
 	genericOption = make(map[string]interface{})
 	genericOption[netlabel.GenericData] = config1
 	genericOption[netlabel.GenericData] = config1
-	if err := d.CreateNetwork("1", genericOption, getIPv4Data(t), nil); err != nil {
+	if err := d.CreateNetwork("1", genericOption, nil, getIPv4Data(t), nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
 	config2 := &networkConfiguration{BridgeName: "net_test_2"}
 	config2 := &networkConfiguration{BridgeName: "net_test_2"}
 	genericOption[netlabel.GenericData] = config2
 	genericOption[netlabel.GenericData] = config2
-	if err := d.CreateNetwork("2", genericOption, getIPv4Data(t), nil); err != nil {
+	if err := d.CreateNetwork("2", genericOption, nil, getIPv4Data(t), nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
@@ -273,7 +273,7 @@ func TestCreateMultipleNetworks(t *testing.T) {
 
 
 	config3 := &networkConfiguration{BridgeName: "net_test_3"}
 	config3 := &networkConfiguration{BridgeName: "net_test_3"}
 	genericOption[netlabel.GenericData] = config3
 	genericOption[netlabel.GenericData] = config3
-	if err := d.CreateNetwork("3", genericOption, getIPv4Data(t), nil); err != nil {
+	if err := d.CreateNetwork("3", genericOption, nil, getIPv4Data(t), nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
@@ -282,7 +282,7 @@ func TestCreateMultipleNetworks(t *testing.T) {
 
 
 	config4 := &networkConfiguration{BridgeName: "net_test_4"}
 	config4 := &networkConfiguration{BridgeName: "net_test_4"}
 	genericOption[netlabel.GenericData] = config4
 	genericOption[netlabel.GenericData] = config4
-	if err := d.CreateNetwork("4", genericOption, getIPv4Data(t), nil); err != nil {
+	if err := d.CreateNetwork("4", genericOption, nil, getIPv4Data(t), nil); err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
 
 
@@ -429,6 +429,10 @@ func (te *testEndpoint) AddStaticRoute(destination *net.IPNet, routeType int, ne
 	return nil
 	return nil
 }
 }
 
 
+func (te *testEndpoint) AddTableEntry(tableName string, key string, value []byte) error {
+	return nil
+}
+
 func (te *testEndpoint) DisableGatewayService() {}
 func (te *testEndpoint) DisableGatewayService() {}
 
 
 func TestQueryEndpointInfo(t *testing.T) {
 func TestQueryEndpointInfo(t *testing.T) {
@@ -462,7 +466,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
 	genericOption[netlabel.GenericData] = netconfig
 	genericOption[netlabel.GenericData] = netconfig
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("net1", genericOption, ipdList, nil)
+	err := d.CreateNetwork("net1", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -563,7 +567,7 @@ func TestLinkContainers(t *testing.T) {
 	genericOption[netlabel.GenericData] = netconfig
 	genericOption[netlabel.GenericData] = netconfig
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("net1", genericOption, ipdList, nil)
+	err := d.CreateNetwork("net1", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -789,7 +793,7 @@ func TestSetDefaultGw(t *testing.T) {
 	genericOption[netlabel.EnableIPv6] = true
 	genericOption[netlabel.EnableIPv6] = true
 	genericOption[netlabel.GenericData] = config
 	genericOption[netlabel.GenericData] = config
 
 
-	err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
+	err := d.CreateNetwork("dummy", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}

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

@@ -27,7 +27,7 @@ func TestLinkCreate(t *testing.T) {
 	genericOption[netlabel.GenericData] = config
 	genericOption[netlabel.GenericData] = config
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
+	err := d.CreateNetwork("dummy", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -119,7 +119,7 @@ func TestLinkCreateTwo(t *testing.T) {
 	genericOption[netlabel.GenericData] = config
 	genericOption[netlabel.GenericData] = config
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
+	err := d.CreateNetwork("dummy", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -155,7 +155,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
 	genericOption[netlabel.GenericData] = config
 	genericOption[netlabel.GenericData] = config
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
+	err := d.CreateNetwork("dummy", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}
@@ -190,7 +190,7 @@ func TestLinkDelete(t *testing.T) {
 	genericOption[netlabel.GenericData] = config
 	genericOption[netlabel.GenericData] = config
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
+	err := d.CreateNetwork("dummy", genericOption, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}

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

@@ -45,7 +45,7 @@ func TestPortMappingConfig(t *testing.T) {
 	netOptions[netlabel.GenericData] = netConfig
 	netOptions[netlabel.GenericData] = netConfig
 
 
 	ipdList := getIPv4Data(t)
 	ipdList := getIPv4Data(t)
-	err := d.CreateNetwork("dummy", netOptions, ipdList, nil)
+	err := d.CreateNetwork("dummy", netOptions, nil, ipdList, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatalf("Failed to create bridge: %v", err)
 		t.Fatalf("Failed to create bridge: %v", err)
 	}
 	}

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

@@ -32,7 +32,10 @@ func (d *driver) NetworkFree(id string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
 
 
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	d.Lock()
 	d.Lock()
 	defer d.Unlock()
 	defer d.Unlock()
 
 

+ 2 - 2
libnetwork/drivers/host/host_test.go

@@ -14,7 +14,7 @@ func TestDriver(t *testing.T) {
 		t.Fatalf("Unexpected network type returned by driver")
 		t.Fatalf("Unexpected network type returned by driver")
 	}
 	}
 
 
-	err := d.CreateNetwork("first", nil, nil, nil)
+	err := d.CreateNetwork("first", nil, nil, nil, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -23,7 +23,7 @@ func TestDriver(t *testing.T) {
 		t.Fatalf("Unexpected network id stored")
 		t.Fatalf("Unexpected network id stored")
 	}
 	}
 
 
-	err = d.CreateNetwork("second", nil, nil, nil)
+	err = d.CreateNetwork("second", nil, nil, nil, nil)
 	if err == nil {
 	if err == nil {
 		t.Fatalf("Second network creation should fail on this driver")
 		t.Fatalf("Second network creation should fail on this driver")
 	}
 	}

+ 3 - 0
libnetwork/drivers/ipvlan/ipvlan.go

@@ -98,3 +98,6 @@ func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{})
 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
 	return nil
 	return nil
 }
 }
+
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}

+ 1 - 1
libnetwork/drivers/ipvlan/ipvlan_network.go

@@ -14,7 +14,7 @@ import (
 )
 )
 
 
 // CreateNetwork the network for the specified driver type
 // CreateNetwork the network for the specified driver type
-func (d *driver) CreateNetwork(nid string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	defer osl.InitOSContext()()
 	defer osl.InitOSContext()()
 	kv, err := kernel.GetKernelVersion()
 	kv, err := kernel.GetKernelVersion()
 	if err != nil {
 	if err != nil {

+ 3 - 0
libnetwork/drivers/macvlan/macvlan.go

@@ -100,3 +100,6 @@ func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{})
 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
 	return nil
 	return nil
 }
 }
+
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}

+ 1 - 1
libnetwork/drivers/macvlan/macvlan_network.go

@@ -14,7 +14,7 @@ import (
 )
 )
 
 
 // CreateNetwork the network for the specified driver type
 // CreateNetwork the network for the specified driver type
-func (d *driver) CreateNetwork(nid string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	defer osl.InitOSContext()()
 	defer osl.InitOSContext()()
 	kv, err := kernel.GetKernelVersion()
 	kv, err := kernel.GetKernelVersion()
 	if err != nil {
 	if err != nil {

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

@@ -32,7 +32,10 @@ func (d *driver) NetworkFree(id string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
 
 
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	d.Lock()
 	d.Lock()
 	defer d.Unlock()
 	defer d.Unlock()
 
 

+ 2 - 2
libnetwork/drivers/null/null_test.go

@@ -14,7 +14,7 @@ func TestDriver(t *testing.T) {
 		t.Fatalf("Unexpected network type returned by driver")
 		t.Fatalf("Unexpected network type returned by driver")
 	}
 	}
 
 
-	err := d.CreateNetwork("first", nil, nil, nil)
+	err := d.CreateNetwork("first", nil, nil, nil, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -23,7 +23,7 @@ func TestDriver(t *testing.T) {
 		t.Fatalf("Unexpected network id stored")
 		t.Fatalf("Unexpected network id stored")
 	}
 	}
 
 
-	err = d.CreateNetwork("second", nil, nil, nil)
+	err = d.CreateNetwork("second", nil, nil, nil, nil)
 	if err == nil {
 	if err == nil {
 		t.Fatalf("Second network creation should fail on this driver")
 		t.Fatalf("Second network creation should fail on this driver")
 	}
 	}

+ 4 - 1
libnetwork/drivers/overlay/ov_network.go

@@ -67,7 +67,10 @@ func (d *driver) NetworkFree(id string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
 
 
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	if id == "" {
 	if id == "" {
 		return fmt.Errorf("invalid network id")
 		return fmt.Errorf("invalid network id")
 	}
 	}

+ 4 - 1
libnetwork/drivers/overlay/ovmanager/ovmanager.go

@@ -187,10 +187,13 @@ func (n *network) releaseVxlanID() {
 	}
 	}
 }
 }
 
 
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
 
 
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
 func (d *driver) DeleteNetwork(nid string) error {
 func (d *driver) DeleteNetwork(nid string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }

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

@@ -91,7 +91,10 @@ func (d *driver) NetworkFree(id string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
 
 
-func (d *driver) CreateNetwork(id string, options map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
+func (d *driver) CreateNetwork(id string, options map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	create := &api.CreateNetworkRequest{
 	create := &api.CreateNetworkRequest{
 		NetworkID: id,
 		NetworkID: id,
 		Options:   options,
 		Options:   options,

+ 5 - 1
libnetwork/drivers/remote/driver_test.go

@@ -199,6 +199,10 @@ func (test *testEndpoint) DisableGatewayService() {
 	test.disableGatewayService = true
 	test.disableGatewayService = true
 }
 }
 
 
+func (test *testEndpoint) AddTableEntry(tableName string, key string, value []byte) error {
+	return nil
+}
+
 func TestGetEmptyCapabilities(t *testing.T) {
 func TestGetEmptyCapabilities(t *testing.T) {
 	var plugin = "test-net-driver-empty-cap"
 	var plugin = "test-net-driver-empty-cap"
 
 
@@ -400,7 +404,7 @@ func TestRemoteDriver(t *testing.T) {
 	}
 	}
 
 
 	netID := "dummy-network"
 	netID := "dummy-network"
-	err = d.CreateNetwork(netID, map[string]interface{}{}, nil, nil)
+	err = d.CreateNetwork(netID, map[string]interface{}{}, nil, nil, nil)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}

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

@@ -149,8 +149,11 @@ func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []d
 	return nil
 	return nil
 }
 }
 
 
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
 // Create a new network
 // Create a new network
-func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	if _, err := d.getNetwork(id); err == nil {
 	if _, err := d.getNetwork(id); err == nil {
 		return types.ForbiddenErrorf("network %s exists", id)
 		return types.ForbiddenErrorf("network %s exists", id)
 	}
 	}

+ 4 - 1
libnetwork/drvregistry/drvregistry_test.go

@@ -25,7 +25,7 @@ func mockDriverInit(reg driverapi.DriverCallback, opt map[string]interface{}) er
 	return reg.RegisterDriver(mockDriverName, &md, driverapi.Capability{DataScope: datastore.LocalScope})
 	return reg.RegisterDriver(mockDriverName, &md, driverapi.Capability{DataScope: datastore.LocalScope})
 }
 }
 
 
-func (m *mockDriver) CreateNetwork(nid string, options map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (m *mockDriver) CreateNetwork(nid string, options map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	return nil
 	return nil
 }
 }
 
 
@@ -81,6 +81,9 @@ func (m *mockDriver) NetworkFree(id string) error {
 	return nil
 	return nil
 }
 }
 
 
+func (m *mockDriver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}
+
 func getNew(t *testing.T) *DrvRegistry {
 func getNew(t *testing.T) *DrvRegistry {
 	reg, err := New(nil, nil, nil, nil)
 	reg, err := New(nil, nil, nil, nil)
 	if err != nil {
 	if err != nil {

+ 4 - 0
libnetwork/endpoint_info.go

@@ -292,6 +292,10 @@ func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHo
 	return nil
 	return nil
 }
 }
 
 
+func (ep *endpoint) AddTableEntry(tableName, key string, value []byte) error {
+	return nil
+}
+
 func (ep *endpoint) Sandbox() Sandbox {
 func (ep *endpoint) Sandbox() Sandbox {
 	cnt, ok := ep.getSandbox()
 	cnt, ok := ep.getSandbox()
 	if !ok {
 	if !ok {

+ 4 - 1
libnetwork/libnetwork_internal_test.go

@@ -393,7 +393,7 @@ func badDriverInit(reg driverapi.DriverCallback, opt map[string]interface{}) err
 	return reg.RegisterDriver(badDriverName, &bd, driverapi.Capability{DataScope: datastore.LocalScope})
 	return reg.RegisterDriver(badDriverName, &bd, driverapi.Capability{DataScope: datastore.LocalScope})
 }
 }
 
 
-func (b *badDriver) CreateNetwork(nid string, options map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
+func (b *badDriver) CreateNetwork(nid string, options map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
 	if b.failNetworkCreation {
 	if b.failNetworkCreation {
 		return fmt.Errorf("I will not create any network")
 		return fmt.Errorf("I will not create any network")
 	}
 	}
@@ -440,3 +440,6 @@ func (b *badDriver) NetworkAllocate(id string, option map[string]string, ipV4Dat
 func (b *badDriver) NetworkFree(id string) error {
 func (b *badDriver) NetworkFree(id string) error {
 	return types.NotImplementedErrorf("not implemented")
 	return types.NotImplementedErrorf("not implemented")
 }
 }
+
+func (b *badDriver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
+}