2015-06-10 14:24:19 -07:00
package overlay
2016-05-18 20:44:50 -07:00
//go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto
2015-06-10 14:24:19 -07:00
import (
2017-07-27 11:43:13 -07:00
"context"
2015-06-10 14:24:19 -07:00
"fmt"
2015-10-26 03:13:34 -07:00
"net"
2015-06-10 14:24:19 -07:00
"sync"
"github.com/docker/libnetwork/datastore"
2016-01-28 11:54:03 -08:00
"github.com/docker/libnetwork/discoverapi"
2015-06-10 14:24:19 -07:00
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/idm"
"github.com/docker/libnetwork/netlabel"
2016-06-07 22:54:28 -07:00
"github.com/docker/libnetwork/osl"
2016-01-27 16:37:47 -08:00
"github.com/docker/libnetwork/types"
2015-06-10 14:24:19 -07:00
"github.com/hashicorp/serf/serf"
2017-07-26 14:18:31 -07:00
"github.com/sirupsen/logrus"
2015-06-10 14:24:19 -07:00
)
const (
networkType = "overlay"
vethPrefix = "veth"
vethLen = 7
vxlanIDStart = 256
2016-06-09 12:47:35 -07:00
vxlanIDEnd = ( 1 << 24 ) - 1
2015-07-03 03:43:02 +01:00
vxlanPort = 4789
2016-07-23 12:29:49 -07:00
vxlanEncap = 50
2016-07-21 15:44:12 -07:00
secureOption = "encrypted"
2015-06-10 14:24:19 -07:00
)
2016-01-27 16:37:47 -08:00
var initVxlanIdm = make ( chan ( bool ) , 1 )
2015-06-10 14:24:19 -07:00
type driver struct {
2016-07-19 18:17:30 -07:00
eventCh chan serf . Event
notifyCh chan ovNotify
exitCh chan chan struct { }
bindAddress string
advertiseAddress string
neighIP string
config map [ string ] interface { }
peerDb peerNetworkMap
secMap * encrMap
serfInstance * serf . Serf
networks networkTable
store datastore . DataStore
localStore datastore . DataStore
vxlanIdm * idm . Idm
2017-05-31 16:46:14 -07:00
initOS sync . Once
2016-07-19 18:17:30 -07:00
joinOnce sync . Once
2017-02-10 14:24:24 -08:00
localJoinOnce sync . Once
2016-07-19 18:17:30 -07:00
keys [ ] * key
2017-07-27 11:43:13 -07:00
peerOpCh chan * peerOperation
peerOpCancel context . CancelFunc
2015-06-10 14:24:19 -07:00
sync . Mutex
}
// Init registers a new instance of overlay driver
2015-09-18 14:00:36 -07:00
func Init ( dc driverapi . DriverCallback , config map [ string ] interface { } ) error {
2015-06-10 14:24:19 -07:00
c := driverapi . Capability {
2017-04-07 13:31:44 -07:00
DataScope : datastore . GlobalScope ,
ConnectivityScope : datastore . GlobalScope ,
2015-06-10 14:24:19 -07:00
}
2015-09-18 14:00:36 -07:00
d := & driver {
2015-06-10 14:24:19 -07:00
networks : networkTable { } ,
peerDb : peerNetworkMap {
2015-12-07 14:20:13 -08:00
mp : map [ string ] * peerMap { } ,
2015-06-10 14:24:19 -07:00
} ,
2017-07-27 11:43:13 -07:00
secMap : & encrMap { nodes : map [ string ] [ ] * spi { } } ,
config : config ,
peerOpCh : make ( chan * peerOperation ) ,
2015-09-18 14:00:36 -07:00
}
2017-07-27 11:43:13 -07:00
// Launch the go routine for processing peer operations
ctx , cancel := context . WithCancel ( context . Background ( ) )
d . peerOpCancel = cancel
go d . peerOpRoutine ( ctx , d . peerOpCh )
2016-01-27 16:37:47 -08:00
if data , ok := config [ netlabel . GlobalKVClient ] ; ok {
var err error
dsc , ok := data . ( discoverapi . DatastoreConfigData )
if ! ok {
return types . InternalErrorf ( "incorrect data in datastore configuration: %v" , data )
}
d . store , err = datastore . NewDataStoreFromConfig ( dsc )
if err != nil {
return types . InternalErrorf ( "failed to initialize data store: %v" , err )
}
}
2016-06-07 22:54:28 -07:00
if data , ok := config [ netlabel . LocalKVClient ] ; ok {
var err error
dsc , ok := data . ( discoverapi . DatastoreConfigData )
if ! ok {
return types . InternalErrorf ( "incorrect data in datastore configuration: %v" , data )
}
d . localStore , err = datastore . NewDataStoreFromConfig ( dsc )
if err != nil {
return types . InternalErrorf ( "failed to initialize local data store: %v" , err )
}
}
2016-08-01 08:06:13 -07:00
if err := d . restoreEndpoints ( ) ; err != nil {
logrus . Warnf ( "Failure during overlay endpoints restore: %v" , err )
}
// If an error happened when the network join the sandbox during the endpoints restore
// we should reset it now along with the once variable, so that subsequent endpoint joins
// outside of the restore path can potentially fix the network join and succeed.
for nid , n := range d . networks {
if n . initErr != nil {
2016-11-28 11:44:45 -07:00
logrus . Infof ( "resetting init error and once variable for network %s after unsuccessful endpoint restore: %v" , nid , n . initErr )
2016-08-01 08:06:13 -07:00
n . initErr = nil
n . once = & sync . Once { }
}
}
2016-06-07 22:54:28 -07:00
2015-09-18 14:00:36 -07:00
return dc . RegisterDriver ( networkType , d , c )
2015-06-10 14:24:19 -07:00
}
2016-06-07 22:54:28 -07:00
// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox
func ( d * driver ) restoreEndpoints ( ) error {
if d . localStore == nil {
2016-10-31 22:26:14 -06:00
logrus . Warn ( "Cannot restore overlay endpoints because local datastore is missing" )
2016-06-07 22:54:28 -07:00
return nil
}
kvol , err := d . localStore . List ( datastore . Key ( overlayEndpointPrefix ) , & endpoint { } )
if err != nil && err != datastore . ErrKeyNotFound {
return fmt . Errorf ( "failed to read overlay endpoint from store: %v" , err )
}
if err == datastore . ErrKeyNotFound {
return nil
}
for _ , kvo := range kvol {
ep := kvo . ( * endpoint )
n := d . network ( ep . nid )
if n == nil {
2016-07-13 10:56:57 -07:00
logrus . Debugf ( "Network (%s) not found for restored endpoint (%s)" , ep . nid [ 0 : 7 ] , ep . id [ 0 : 7 ] )
logrus . Debugf ( "Deleting stale overlay endpoint (%s) from store" , ep . id [ 0 : 7 ] )
if err := d . deleteEndpointFromStore ( ep ) ; err != nil {
logrus . Debugf ( "Failed to delete stale overlay endpoint (%s) from store" , ep . id [ 0 : 7 ] )
}
2016-06-07 22:54:28 -07:00
continue
}
n . addEndpoint ( ep )
s := n . getSubnetforIP ( ep . addr )
if s == nil {
return fmt . Errorf ( "could not find subnet for endpoint %s" , ep . id )
}
if err := n . joinSandbox ( true ) ; err != nil {
return fmt . Errorf ( "restore network sandbox failed: %v" , err )
}
if err := n . joinSubnetSandbox ( s , true ) ; err != nil {
return fmt . Errorf ( "restore subnet sandbox failed for %q: %v" , s . subnetIP . String ( ) , err )
}
Ifaces := make ( map [ string ] [ ] osl . IfaceOption )
vethIfaceOption := make ( [ ] osl . IfaceOption , 1 )
vethIfaceOption = append ( vethIfaceOption , n . sbox . InterfaceOptions ( ) . Master ( s . brName ) )
2017-05-09 16:07:09 -07:00
Ifaces [ "veth+veth" ] = vethIfaceOption
2016-06-07 22:54:28 -07:00
err := n . sbox . Restore ( Ifaces , nil , nil , nil )
if err != nil {
return fmt . Errorf ( "failed to restore overlay sandbox: %v" , err )
}
n . incEndpointCount ( )
2017-08-14 09:20:55 -07:00
d . peerAdd ( ep . nid , ep . id , ep . addr . IP , ep . addr . Mask , ep . mac , net . ParseIP ( d . advertiseAddress ) , false , false , true )
2016-06-07 22:54:28 -07:00
}
return nil
}
2015-06-10 14:24:19 -07:00
// Fini cleans up the driver resources
func Fini ( drv driverapi . Driver ) {
d := drv . ( * driver )
2017-07-27 11:43:13 -07:00
// Notify the peer go routine to return
if d . peerOpCancel != nil {
d . peerOpCancel ( )
}
2015-06-10 14:24:19 -07:00
if d . exitCh != nil {
waitCh := make ( chan struct { } )
d . exitCh <- waitCh
<- waitCh
}
}
2015-09-24 19:01:15 -07:00
func ( d * driver ) configure ( ) error {
2017-06-06 20:30:41 -07:00
// Apply OS specific kernel configs if needed
d . initOS . Do ( applyOStweaks )
2016-01-27 16:37:47 -08:00
if d . store == nil {
2016-04-28 16:54:47 -07:00
return nil
2016-01-27 16:37:47 -08:00
}
2015-06-10 14:24:19 -07:00
2016-01-27 16:37:47 -08:00
if d . vxlanIdm == nil {
return d . initializeVxlanIdm ( )
2015-09-18 14:00:36 -07:00
}
2016-01-27 16:37:47 -08:00
return nil
}
2015-06-10 14:24:19 -07:00
2016-01-27 16:37:47 -08:00
func ( d * driver ) initializeVxlanIdm ( ) error {
var err error
2015-06-10 14:24:19 -07:00
2016-01-27 16:37:47 -08:00
initVxlanIdm <- true
defer func ( ) { <- initVxlanIdm } ( )
if d . vxlanIdm != nil {
return nil
}
d . vxlanIdm , err = idm . New ( d . store , "vxlan-id" , vxlanIDStart , vxlanIDEnd )
if err != nil {
return fmt . Errorf ( "failed to initialize vxlan id manager: %v" , err )
}
2015-06-10 14:24:19 -07:00
2016-01-27 16:37:47 -08:00
return nil
2015-06-10 14:24:19 -07:00
}
func ( d * driver ) Type ( ) string {
return networkType
}
2015-09-18 12:54:08 -07:00
2016-12-18 19:56:34 -08:00
func ( d * driver ) IsBuiltIn ( ) bool {
return true
}
2015-10-26 03:13:34 -07:00
func validateSelf ( node string ) error {
advIP := net . ParseIP ( node )
if advIP == nil {
return fmt . Errorf ( "invalid self address (%s)" , node )
}
addrs , err := net . InterfaceAddrs ( )
if err != nil {
return fmt . Errorf ( "Unable to get interface addresses %v" , err )
}
for _ , addr := range addrs {
ip , _ , err := net . ParseCIDR ( addr . String ( ) )
if err == nil && ip . Equal ( advIP ) {
return nil
}
}
return fmt . Errorf ( "Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster" , advIP . String ( ) )
}
2016-07-19 18:17:30 -07:00
func ( d * driver ) nodeJoin ( advertiseAddress , bindAddress string , self bool ) {
2015-10-01 21:50:54 -07:00
if self && ! d . isSerfAlive ( ) {
2015-09-18 12:54:08 -07:00
d . Lock ( )
2016-07-19 18:17:30 -07:00
d . advertiseAddress = advertiseAddress
d . bindAddress = bindAddress
2015-09-18 12:54:08 -07:00
d . Unlock ( )
2016-03-30 14:42:58 -07:00
2017-02-10 14:24:24 -08:00
// If containers are already running on this network update the
2017-09-05 10:43:20 -07:00
// advertise address in the peerDB
2017-02-10 14:24:24 -08:00
d . localJoinOnce . Do ( func ( ) {
d . peerDBUpdateSelf ( )
} )
2016-03-30 14:42:58 -07:00
// If there is no cluster store there is no need to start serf.
if d . store != nil {
2016-07-19 18:17:30 -07:00
if err := validateSelf ( advertiseAddress ) ; err != nil {
2017-05-09 16:07:09 -07:00
logrus . Warn ( err . Error ( ) )
2016-07-19 18:17:30 -07:00
}
2016-03-30 14:42:58 -07:00
err := d . serfInit ( )
if err != nil {
logrus . Errorf ( "initializing serf instance failed: %v" , err )
2016-07-19 18:17:30 -07:00
d . Lock ( )
d . advertiseAddress = ""
d . bindAddress = ""
d . Unlock ( )
2016-03-30 14:42:58 -07:00
return
}
2015-09-18 12:54:08 -07:00
}
}
2015-10-01 21:50:54 -07:00
d . Lock ( )
if ! self {
2016-07-19 18:17:30 -07:00
d . neighIP = advertiseAddress
2015-10-01 21:50:54 -07:00
}
neighIP := d . neighIP
d . Unlock ( )
if d . serfInstance != nil && neighIP != "" {
2015-09-18 12:54:08 -07:00
var err error
d . joinOnce . Do ( func ( ) {
2015-10-01 21:50:54 -07:00
err = d . serfJoin ( neighIP )
2015-10-02 12:20:29 -07:00
if err == nil {
d . pushLocalDb ( )
}
2015-09-18 12:54:08 -07:00
} )
if err != nil {
2016-07-19 18:17:30 -07:00
logrus . Errorf ( "joining serf neighbor %s failed: %v" , advertiseAddress , err )
2015-09-18 12:54:08 -07:00
d . Lock ( )
d . joinOnce = sync . Once { }
d . Unlock ( )
return
}
}
}
2015-10-02 12:20:29 -07:00
func ( d * driver ) pushLocalEndpointEvent ( action , nid , eid string ) {
2016-03-29 11:19:23 -07:00
n := d . network ( nid )
if n == nil {
logrus . Debugf ( "Error pushing local endpoint event for network %s" , nid )
return
}
ep := n . endpoint ( eid )
if ep == nil {
logrus . Debugf ( "Error pushing local endpoint event for ep %s / %s" , nid , eid )
return
}
2015-10-02 12:20:29 -07:00
if ! d . isSerfAlive ( ) {
return
}
d . notifyCh <- ovNotify {
action : "join" ,
2016-03-29 11:19:23 -07:00
nw : n ,
ep : ep ,
2015-10-02 12:20:29 -07:00
}
}
2015-09-18 12:54:08 -07:00
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
2016-01-28 11:54:03 -08:00
func ( d * driver ) DiscoverNew ( dType discoverapi . DiscoveryType , data interface { } ) error {
2016-06-06 18:17:10 -07:00
var err error
2016-01-27 16:37:47 -08:00
switch dType {
case discoverapi . NodeDiscovery :
2016-01-28 11:54:03 -08:00
nodeData , ok := data . ( discoverapi . NodeDiscoveryData )
2015-10-01 21:50:54 -07:00
if ! ok || nodeData . Address == "" {
2015-09-18 12:54:08 -07:00
return fmt . Errorf ( "invalid discovery data" )
}
2016-07-19 18:17:30 -07:00
d . nodeJoin ( nodeData . Address , nodeData . BindAddress , nodeData . Self )
2016-01-27 16:37:47 -08:00
case discoverapi . DatastoreConfig :
if d . store != nil {
return types . ForbiddenErrorf ( "cannot accept datastore configuration: Overlay driver has a datastore configured already" )
}
dsc , ok := data . ( discoverapi . DatastoreConfigData )
if ! ok {
return types . InternalErrorf ( "incorrect data in datastore configuration: %v" , data )
}
d . store , err = datastore . NewDataStoreFromConfig ( dsc )
if err != nil {
return types . InternalErrorf ( "failed to initialize data store: %v" , err )
}
2016-06-06 18:17:10 -07:00
case discoverapi . EncryptionKeysConfig :
encrData , ok := data . ( discoverapi . DriverEncryptionConfig )
if ! ok {
return fmt . Errorf ( "invalid encryption key notification data" )
}
keys := make ( [ ] * key , 0 , len ( encrData . Keys ) )
for i := 0 ; i < len ( encrData . Keys ) ; i ++ {
2016-06-11 04:50:25 -07:00
k := & key {
value : encrData . Keys [ i ] ,
tag : uint32 ( encrData . Tags [ i ] ) ,
2016-06-06 18:17:10 -07:00
}
keys = append ( keys , k )
}
2016-09-19 11:37:30 -07:00
if err := d . setKeys ( keys ) ; err != nil {
logrus . Warn ( err )
}
2016-06-06 18:17:10 -07:00
case discoverapi . EncryptionKeysUpdate :
var newKey , delKey , priKey * key
encrData , ok := data . ( discoverapi . DriverEncryptionUpdate )
if ! ok {
return fmt . Errorf ( "invalid encryption key notification data" )
}
2016-06-11 04:50:25 -07:00
if encrData . Key != nil {
newKey = & key {
value : encrData . Key ,
tag : uint32 ( encrData . Tag ) ,
}
2016-06-06 18:17:10 -07:00
}
2016-06-11 04:50:25 -07:00
if encrData . Primary != nil {
priKey = & key {
value : encrData . Primary ,
tag : uint32 ( encrData . PrimaryTag ) ,
}
2016-06-06 18:17:10 -07:00
}
2016-06-11 04:50:25 -07:00
if encrData . Prune != nil {
delKey = & key {
value : encrData . Prune ,
tag : uint32 ( encrData . PruneTag ) ,
}
2016-06-06 18:17:10 -07:00
}
2016-09-19 11:37:30 -07:00
if err := d . updateKeys ( newKey , priKey , delKey ) ; err != nil {
logrus . Warn ( err )
}
2016-01-27 16:37:47 -08:00
default :
2015-09-18 12:54:08 -07:00
}
return nil
}
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
2016-01-28 11:54:03 -08:00
func ( d * driver ) DiscoverDelete ( dType discoverapi . DiscoveryType , data interface { } ) error {
2015-09-18 12:54:08 -07:00
return nil
}