The eventually-consistent nature of NetworkDB means we cannot depend on events being received in the same order that they were sent. Nor can we depend on receiving events for all intermediate states. It is possible for a series of entry UPDATEs, or a DELETE followed by a CREATE with the same key, to get coalesced into a single UPDATE event on the receiving node. Watchers of NetworkDB tables therefore need to be prepared to gracefully handle arbitrary UPDATEs of a key, including those where the new value may have nothing in common with the previous value. The overlay driver naively handled events for overlay_peer_table assuming that an endpoint leave followed by a rejoin of the same endpoint would always be expressed as a DELETE event followed by a CREATE. It would handle a coalesced UPDATE as a CREATE, inserting a new entry into peerDB without removing the old one. This would have various side effects, such as having the "transient state" of multiple entries in peerDB with the same peer IP never settle. Update driverapi to pass both the previous and new value of a table entry into the driver. Modify the overlay driver to handle an UPDATE by removing the previous peer entry from peerDB then adding the new one. Modify the Windows overlay driver to match. Signed-off-by: Cory Snider <csnider@mirantis.com> (cherry picked from commite1a586a9a7) libn/d/overlay: don't deref nil PeerRecord on error If unmarshaling the peer record fails, there is no need to check if it's a record for a local peer. Attempting to do so anyway will result in a nil-dereference panic. Don't do that. The Windows overlay driver has a typo: prevPeer is being checked twice for whether it was a local-peer record. Check prevPeer once and newPeer once each, as intended. Signed-off-by: Cory Snider <csnider@mirantis.com> (cherry picked from commit12c6345d3a) Signed-off-by: Cory Snider <csnider@mirantis.com>
200 lines
7.9 KiB
Go
200 lines
7.9 KiB
Go
package driverapi
|
|
|
|
import "net"
|
|
|
|
// NetworkPluginEndpointType represents the Endpoint Type used by Plugin system
|
|
const NetworkPluginEndpointType = "NetworkDriver"
|
|
|
|
// Driver is an interface that every plugin driver needs to implement.
|
|
type Driver interface {
|
|
// NetworkAllocate invokes the driver method to allocate network
|
|
// specific resources passing network id and network specific config.
|
|
// It returns a key,value pair of network specific driver allocations
|
|
// to the caller.
|
|
NetworkAllocate(nid string, options map[string]string, ipV4Data, ipV6Data []IPAMData) (map[string]string, error)
|
|
|
|
// NetworkFree invokes the driver method to free network specific resources
|
|
// associated with a given network id.
|
|
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. 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
|
|
// the network id.
|
|
DeleteNetwork(nid string) error
|
|
|
|
// CreateEndpoint invokes the driver method to create an endpoint
|
|
// passing the network id, endpoint id endpoint information and driver
|
|
// specific config. The endpoint information can be either consumed by
|
|
// the driver or populated by the driver. The config mechanism will
|
|
// eventually be replaced with labels which are yet to be introduced.
|
|
CreateEndpoint(nid, eid string, ifInfo InterfaceInfo, options map[string]interface{}) error
|
|
|
|
// DeleteEndpoint invokes the driver method to delete an endpoint
|
|
// passing the network id and endpoint id.
|
|
DeleteEndpoint(nid, eid string) error
|
|
|
|
// EndpointOperInfo retrieves from the driver the operational data related to the specified endpoint
|
|
EndpointOperInfo(nid, eid string) (map[string]interface{}, error)
|
|
|
|
// Join method is invoked when a Sandbox is attached to an endpoint.
|
|
Join(nid, eid string, sboxKey string, jinfo JoinInfo, options map[string]interface{}) error
|
|
|
|
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
|
Leave(nid, eid string) error
|
|
|
|
// ProgramExternalConnectivity invokes the driver method which does the necessary
|
|
// programming to allow the external connectivity dictated by the passed options
|
|
ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error
|
|
|
|
// RevokeExternalConnectivity asks the driver to remove any external connectivity
|
|
// programming that was done so far
|
|
RevokeExternalConnectivity(nid, eid string) error
|
|
|
|
// Type returns the type of this driver, the network type this driver manages
|
|
Type() string
|
|
|
|
// IsBuiltIn returns true if it is a built-in driver
|
|
IsBuiltIn() bool
|
|
}
|
|
|
|
// TableWatcher is an optional interface for a network driver.
|
|
type TableWatcher interface {
|
|
// 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(nid string, tableName string, key string, prev, value []byte)
|
|
|
|
// DecodeTableEntry passes the driver a key, value pair from table it registered
|
|
// with libnetwork. Driver should return {object ID, map[string]string} tuple.
|
|
// If DecodeTableEntry is called for a table associated with NetworkObject or
|
|
// EndpointObject the return object ID should be the network id or endpoint id
|
|
// associated with that entry. map should have information about the object that
|
|
// can be presented to the user.
|
|
// For example: overlay driver returns the VTEP IP of the host that has the endpoint
|
|
// which is shown in 'network inspect --verbose'
|
|
DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]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, objType ObjectType) error
|
|
|
|
// UpdateIPamConfig updates the networks IPAM configuration
|
|
// based on information from the driver. In windows, the OS (HNS) chooses
|
|
// the IP address space if the user does not specify an address space.
|
|
UpdateIpamConfig(ipV4Data []IPAMData)
|
|
}
|
|
|
|
// InterfaceInfo provides a go interface for drivers to retrieve
|
|
// network information to interface resources.
|
|
type InterfaceInfo interface {
|
|
// SetMacAddress allows the driver to set the mac address to the endpoint interface
|
|
// during the call to CreateEndpoint, if the mac address is not already set.
|
|
SetMacAddress(mac net.HardwareAddr) error
|
|
|
|
// SetIPAddress allows the driver to set the ip address to the endpoint interface
|
|
// during the call to CreateEndpoint, if the address is not already set.
|
|
// The API is to be used to assign both the IPv4 and IPv6 address types.
|
|
SetIPAddress(ip *net.IPNet) error
|
|
|
|
// MacAddress returns the MAC address.
|
|
MacAddress() net.HardwareAddr
|
|
|
|
// Address returns the IPv4 address.
|
|
Address() *net.IPNet
|
|
|
|
// AddressIPv6 returns the IPv6 address.
|
|
AddressIPv6() *net.IPNet
|
|
}
|
|
|
|
// InterfaceNameInfo provides a go interface for the drivers to assign names
|
|
// to interfaces.
|
|
type InterfaceNameInfo interface {
|
|
// SetNames method assigns the srcName and dstPrefix for the interface.
|
|
SetNames(srcName, dstPrefix string) error
|
|
}
|
|
|
|
// JoinInfo represents a set of resources that the driver has the ability to provide during
|
|
// join time.
|
|
type JoinInfo interface {
|
|
// InterfaceName returns an InterfaceNameInfo go interface to facilitate
|
|
// setting the names for the interface.
|
|
InterfaceName() InterfaceNameInfo
|
|
|
|
// SetGateway sets the default IPv4 gateway when a container joins the endpoint.
|
|
SetGateway(net.IP) error
|
|
|
|
// SetGatewayIPv6 sets the default IPv6 gateway when a container joins the endpoint.
|
|
SetGatewayIPv6(net.IP) error
|
|
|
|
// AddStaticRoute adds a route to the sandbox.
|
|
// It may be used in addition to or instead of a default gateway (as above).
|
|
AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error
|
|
|
|
// DisableGatewayService tells libnetwork not to provide Default GW for the container
|
|
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
|
|
}
|
|
|
|
// Registerer provides a way for network drivers to be dynamically registered.
|
|
type Registerer interface {
|
|
RegisterDriver(name string, driver Driver, capability Capability) error
|
|
}
|
|
|
|
// Capability represents the high level capabilities of the drivers which libnetwork can make use of
|
|
type Capability struct {
|
|
DataScope string
|
|
ConnectivityScope string
|
|
}
|
|
|
|
// IPAMData represents the per-network ip related
|
|
// operational information libnetwork will send
|
|
// to the network driver during CreateNetwork()
|
|
type IPAMData struct {
|
|
AddressSpace string
|
|
Pool *net.IPNet
|
|
Gateway *net.IPNet
|
|
AuxAddresses map[string]*net.IPNet
|
|
}
|
|
|
|
// ObjectType represents the type of object driver wants to store in libnetwork's networkDB
|
|
type ObjectType int
|
|
|
|
const (
|
|
// EndpointObject should be set for libnetwork endpoint object related data
|
|
EndpointObject ObjectType = 1 + iota
|
|
// NetworkObject should be set for libnetwork network object related data
|
|
NetworkObject
|
|
// OpaqueObject is for driver specific data with no corresponding libnetwork object
|
|
OpaqueObject
|
|
)
|
|
|
|
// IsValidType validates the passed in type against the valid object types
|
|
func IsValidType(objType ObjectType) bool {
|
|
switch objType {
|
|
case EndpointObject:
|
|
fallthrough
|
|
case NetworkObject:
|
|
fallthrough
|
|
case OpaqueObject:
|
|
return true
|
|
}
|
|
return false
|
|
}
|