2015-04-30 01:25:01 +00:00
/ *
Package libnetwork provides the basic functionality and extension points to
create network namespaces and allocate interfaces for containers to use .
2015-06-16 02:09:59 +00:00
networkType := "bridge"
2015-09-22 15:27:11 +00:00
// Create a new controller instance
2015-06-16 02:09:59 +00:00
driverOptions := options . Generic { }
genericOption := make ( map [ string ] interface { } )
genericOption [ netlabel . GenericData ] = driverOptions
2015-09-22 15:27:11 +00:00
controller , err := libnetwork . New ( config . OptionDriverConfig ( networkType , genericOption ) )
2015-06-16 02:09:59 +00:00
if err != nil {
return
}
// Create a network for containers to join.
2015-08-25 16:41:32 +00:00
// NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can make use of
2016-02-29 19:49:04 +00:00
network , err := controller . NewNetwork ( networkType , "network1" , "" )
2015-06-16 02:09:59 +00:00
if err != nil {
return
}
// For each new container: allocate IP and interfaces. The returned network
// settings will be used for container infos (inspect and such), as well as
// iptables rules for port publishing. This info is contained or accessible
// from the returned endpoint.
ep , err := network . CreateEndpoint ( "Endpoint1" )
if err != nil {
return
}
2015-09-22 15:27:11 +00:00
// Create the sandbox for the container.
// NewSandbox accepts Variadic optional arguments which libnetwork can use.
sbx , err := controller . NewSandbox ( "container1" ,
libnetwork . OptionHostname ( "test" ) ,
2023-01-10 14:16:51 +00:00
libnetwork . OptionDomainname ( "example.com" ) )
2015-09-22 15:27:11 +00:00
// A sandbox can join the endpoint via the join api.
err = ep . Join ( sbx )
2015-06-16 02:09:59 +00:00
if err != nil {
return
}
2015-04-30 01:25:01 +00:00
* /
package libnetwork
import (
2023-06-23 00:33:17 +00:00
"context"
2015-05-15 22:23:59 +00:00
"fmt"
"net"
2017-03-10 11:28:14 +00:00
"path/filepath"
2017-11-06 23:42:11 +00:00
"runtime"
2015-09-18 19:54:08 +00:00
"strings"
2015-04-30 01:25:01 +00:00
"sync"
2016-09-20 15:59:32 +00:00
"time"
2015-04-30 01:25:01 +00:00
2023-09-13 15:41:45 +00:00
"github.com/containerd/log"
2021-04-06 00:24:47 +00:00
"github.com/docker/docker/libnetwork/cluster"
"github.com/docker/docker/libnetwork/config"
"github.com/docker/docker/libnetwork/datastore"
"github.com/docker/docker/libnetwork/diagnostic"
"github.com/docker/docker/libnetwork/discoverapi"
"github.com/docker/docker/libnetwork/driverapi"
2023-01-24 23:19:26 +00:00
remotedriver "github.com/docker/docker/libnetwork/drivers/remote"
2021-04-06 00:24:47 +00:00
"github.com/docker/docker/libnetwork/drvregistry"
"github.com/docker/docker/libnetwork/ipamapi"
"github.com/docker/docker/libnetwork/netlabel"
"github.com/docker/docker/libnetwork/osl"
2023-07-28 17:11:00 +00:00
"github.com/docker/docker/libnetwork/scope"
2021-04-06 00:24:47 +00:00
"github.com/docker/docker/libnetwork/types"
2021-05-28 00:15:56 +00:00
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/docker/pkg/plugins"
"github.com/docker/docker/pkg/stringid"
2020-09-11 23:22:29 +00:00
"github.com/moby/locker"
2018-06-12 16:26:11 +00:00
"github.com/pkg/errors"
2015-04-30 01:25:01 +00:00
)
// NetworkWalker is a client provided function which will be used to walk the Networks.
// When the function returns true, the walk will stop.
2023-07-21 22:38:57 +00:00
type NetworkWalker func ( nw * Network ) bool
2015-04-30 01:25:01 +00:00
2023-01-11 22:43:32 +00:00
// Controller manages networks.
type Controller struct {
2021-05-28 00:15:56 +00:00
id string
2023-01-24 23:19:26 +00:00
drvRegistry drvregistry . Networks
ipamRegistry drvregistry . IPAMs
2023-08-12 07:55:03 +00:00
sandboxes map [ string ] * Sandbox
2021-05-28 00:15:56 +00:00
cfg * config . Config
2023-07-21 12:24:18 +00:00
store * datastore . Store
2021-05-28 00:15:56 +00:00
extKeyListener net . Listener
2023-03-29 17:31:12 +00:00
svcRecords map [ string ] * svcInfo
2021-05-28 00:15:56 +00:00
serviceBindings map [ serviceKey ] * service
2023-01-12 01:10:09 +00:00
ingressSandbox * Sandbox
2023-08-16 10:12:39 +00:00
agent * nwAgent
2021-05-28 00:15:56 +00:00
networkLocker * locker . Locker
agentInitDone chan struct { }
agentStopDone chan struct { }
keys [ ] * types . EncryptionKey
DiagnosticServer * diagnostic . Server
2023-01-11 20:56:50 +00:00
mu sync . Mutex
2023-08-20 10:48:09 +00:00
// FIXME(thaJeztah): defOsSbox is always nil on non-Linux: move these fields to Linux-only files.
defOsSboxOnce sync . Once
2023-08-20 08:00:29 +00:00
defOsSbox * osl . Namespace
2015-04-30 01:25:01 +00:00
}
// New creates a new instance of network controller.
2023-01-11 22:43:32 +00:00
func New ( cfgOptions ... config . Option ) ( * Controller , error ) {
c := & Controller {
2017-12-06 19:21:51 +00:00
id : stringid . GenerateRandomID ( ) ,
2022-09-26 17:20:55 +00:00
cfg : config . New ( cfgOptions ... ) ,
2023-08-12 07:55:03 +00:00
sandboxes : map [ string ] * Sandbox { } ,
2023-03-29 17:31:12 +00:00
svcRecords : make ( map [ string ] * svcInfo ) ,
2017-12-06 19:21:51 +00:00
serviceBindings : make ( map [ serviceKey ] * service ) ,
agentInitDone : make ( chan struct { } ) ,
networkLocker : locker . New ( ) ,
DiagnosticServer : diagnostic . New ( ) ,
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>
2015-05-11 12:46:29 +00:00
}
2017-12-06 19:21:51 +00:00
c . DiagnosticServer . Init ( )
2015-05-08 13:26:35 +00:00
2015-10-05 11:21:15 +00:00
if err := c . initStores ( ) ; err != nil {
2015-09-22 20:20:55 +00:00
return nil , err
}
2023-08-29 14:32:18 +00:00
c . drvRegistry . Notify = c
2023-01-24 23:19:26 +00:00
// External plugins don't need config passed through daemon. They can
// bootstrap themselves.
if err := remotedriver . Register ( & c . drvRegistry , c . cfg . PluginGetter ) ; err != nil {
2016-03-01 02:17:04 +00:00
return nil , err
}
2023-07-04 17:30:54 +00:00
if err := registerNetworkDrivers ( & c . drvRegistry , c . makeDriverConfig ) ; err != nil {
return nil , err
2016-03-01 02:17:04 +00:00
}
2016-07-05 20:49:31 +00:00
2023-01-24 23:19:26 +00:00
if err := initIPAMDrivers ( & c . ipamRegistry , c . cfg . PluginGetter , c . cfg . DefaultAddressPool ) ; err != nil {
2016-07-05 20:49:31 +00:00
return nil , err
}
2023-08-16 09:51:39 +00:00
c . WalkNetworks ( func ( nw * Network ) bool {
if n := nw ; n . hasSpecialDriver ( ) && ! n . ConfigOnly ( ) {
if err := n . getController ( ) . addNetwork ( n ) ; err != nil {
log . G ( context . TODO ( ) ) . Warnf ( "Failed to populate network %q with driver %q" , nw . Name ( ) , nw . Type ( ) )
}
}
return false
} )
2016-06-15 04:34:44 +00:00
2016-06-11 00:32:19 +00:00
// Reserve pools first before doing cleanup. Otherwise the
// cleanups of endpoint/network and sandbox below will
// generate many unnecessary warnings
2016-06-12 02:19:16 +00:00
c . reservePools ( )
// Cleanup resources
2023-08-16 18:04:00 +00:00
if err := c . sandboxCleanup ( c . cfg . ActiveSandboxes ) ; err != nil {
log . G ( context . TODO ( ) ) . WithError ( err ) . Error ( "error during sandbox cleanup" )
}
2023-08-16 18:12:42 +00:00
if err := c . cleanupLocalEndpoints ( ) ; err != nil {
log . G ( context . TODO ( ) ) . WithError ( err ) . Warnf ( "error during endpoint cleanup" )
}
2016-03-05 10:00:31 +00:00
c . networkCleanup ( )
2015-10-08 03:01:38 +00:00
2015-09-09 21:24:05 +00:00
if err := c . startExternalKeyListener ( ) ; err != nil {
return nil , err
}
2019-10-13 04:54:49 +00:00
setupArrangeUserFilterRule ( c )
2015-05-13 15:41:45 +00:00
return c , nil
}
2023-01-11 22:43:32 +00:00
// SetClusterProvider sets the cluster provider.
func ( c * Controller ) SetClusterProvider ( provider cluster . Provider ) {
2017-05-03 18:18:33 +00:00
var sameProvider bool
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-05-03 18:18:33 +00:00
// Avoids to spawn multiple goroutine for the same cluster provider
2022-09-23 17:40:11 +00:00
if c . cfg . ClusterProvider == provider {
2017-05-03 18:18:33 +00:00
// If the cluster provider is already set, there is already a go routine spawned
// that is listening for events, so nothing to do here
sameProvider = true
2016-06-10 04:38:29 +00:00
} else {
2022-09-23 17:40:11 +00:00
c . cfg . ClusterProvider = provider
2017-05-03 18:18:33 +00:00
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-05-03 18:18:33 +00:00
if provider == nil || sameProvider {
return
2016-06-10 04:38:29 +00:00
}
2017-05-03 18:18:33 +00:00
// We don't want to spawn a new go routine if the previous one did not exit yet
c . AgentStopWait ( )
go c . clusterAgentInit ( )
2016-05-24 23:17:19 +00:00
}
2023-01-11 22:43:32 +00:00
// SetKeys configures the encryption key for gossip and overlay data path.
func ( c * Controller ) SetKeys ( keys [ ] * types . EncryptionKey ) error {
// libnetwork side of agent depends on the keys. On the first receipt of
// keys setup the agent. For subsequent key set handle the key change
2016-08-04 00:58:24 +00:00
subsysKeys := make ( map [ string ] int )
for _ , key := range keys {
if key . Subsystem != subsysGossip &&
key . Subsystem != subsysIPSec {
return fmt . Errorf ( "key received for unrecognized subsystem" )
}
subsysKeys [ key . Subsystem ] ++
}
for s , count := range subsysKeys {
if count != keyringSize {
2016-12-27 11:42:32 +00:00
return fmt . Errorf ( "incorrect number of keys for subsystem %v" , s )
2016-08-04 00:58:24 +00:00
}
}
2022-12-21 15:15:49 +00:00
if c . getAgent ( ) == nil {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2016-06-05 05:48:10 +00:00
c . keys = keys
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-06-05 05:48:10 +00:00
return nil
}
return c . handleKeyChange ( keys )
}
2023-08-16 10:12:39 +00:00
func ( c * Controller ) getAgent ( ) * nwAgent {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
defer c . mu . Unlock ( )
2016-11-22 07:38:03 +00:00
return c . agent
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) clusterAgentInit ( ) {
2022-09-23 17:40:11 +00:00
clusterProvider := c . cfg . ClusterProvider
2017-05-03 18:18:33 +00:00
var keysAvailable bool
2016-05-24 23:17:19 +00:00
for {
2017-05-03 18:18:33 +00:00
eventType := <- clusterProvider . ListenClusterEvents ( )
2017-05-25 17:45:38 +00:00
// The events: EventSocketChange, EventNodeReady and EventNetworkKeysAvailable are not ordered
2017-05-03 18:18:33 +00:00
// when all the condition for the agent initialization are met then proceed with it
switch eventType {
2017-05-25 17:45:38 +00:00
case cluster . EventNetworkKeysAvailable :
2017-05-03 18:18:33 +00:00
// Validates that the keys are actually available before starting the initialization
// This will handle old spurious messages left on the channel
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-05-03 18:18:33 +00:00
keysAvailable = c . keys != nil
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-05-03 18:18:33 +00:00
fallthrough
2017-05-25 17:45:38 +00:00
case cluster . EventSocketChange , cluster . EventNodeReady :
2023-10-17 21:59:19 +00:00
if keysAvailable && c . isSwarmNode ( ) {
2017-05-03 18:18:33 +00:00
c . agentOperationStart ( )
if err := c . agentSetup ( clusterProvider ) ; err != nil {
c . agentStopComplete ( )
} else {
c . agentInitComplete ( )
2016-05-24 23:17:19 +00:00
}
}
2017-05-25 17:45:38 +00:00
case cluster . EventNodeLeave :
2017-05-03 18:18:33 +00:00
c . agentOperationStart ( )
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2016-08-17 00:37:33 +00:00
c . keys = nil
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-08-17 20:48:51 +00:00
2016-08-20 00:50:37 +00:00
// We are leaving the cluster. Make sure we
// close the gossip so that we stop all
// incoming gossip updates before cleaning up
// any remaining service bindings. But before
// deleting the networks since the networks
// should still be present when cleaning up
// service bindings
c . agentClose ( )
2017-10-13 04:41:29 +00:00
c . cleanupServiceDiscovery ( "" )
2016-08-20 00:50:37 +00:00
c . cleanupServiceBindings ( "" )
2017-04-05 17:38:24 +00:00
2017-05-03 18:18:33 +00:00
c . agentStopComplete ( )
2017-04-05 17:38:24 +00:00
2016-06-10 04:38:29 +00:00
return
2016-05-24 23:17:19 +00:00
}
}
}
2017-05-03 18:18:33 +00:00
// AgentInitWait waits for agent initialization to be completed in the controller.
2023-01-11 22:43:32 +00:00
func ( c * Controller ) AgentInitWait ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2016-08-24 16:51:02 +00:00
agentInitDone := c . agentInitDone
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-08-24 16:51:02 +00:00
if agentInitDone != nil {
<- agentInitDone
}
2016-06-06 02:37:13 +00:00
}
2023-01-11 22:43:32 +00:00
// AgentStopWait waits for the Agent stop to be completed in the controller.
func ( c * Controller ) AgentStopWait ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-04-05 17:38:24 +00:00
agentStopDone := c . agentStopDone
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-04-05 17:38:24 +00:00
if agentStopDone != nil {
<- agentStopDone
}
}
2017-05-03 18:18:33 +00:00
// agentOperationStart marks the start of an Agent Init or Agent Stop
2023-01-11 22:43:32 +00:00
func ( c * Controller ) agentOperationStart ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-05-03 18:18:33 +00:00
if c . agentInitDone == nil {
c . agentInitDone = make ( chan struct { } )
}
if c . agentStopDone == nil {
c . agentStopDone = make ( chan struct { } )
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-05-03 18:18:33 +00:00
}
// agentInitComplete notifies the successful completion of the Agent initialization
2023-01-11 22:43:32 +00:00
func ( c * Controller ) agentInitComplete ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-05-03 18:18:33 +00:00
if c . agentInitDone != nil {
close ( c . agentInitDone )
c . agentInitDone = nil
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-05-03 18:18:33 +00:00
}
// agentStopComplete notifies the successful completion of the Agent stop
2023-01-11 22:43:32 +00:00
func ( c * Controller ) agentStopComplete ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-05-03 18:18:33 +00:00
if c . agentStopDone != nil {
close ( c . agentStopDone )
c . agentStopDone = nil
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-05-03 18:18:33 +00:00
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) makeDriverConfig ( ntype string ) map [ string ] interface { } {
2016-03-01 02:17:04 +00:00
if c . cfg == nil {
return nil
}
2022-12-21 15:15:49 +00:00
cfg := map [ string ] interface { } { }
2022-09-23 17:40:11 +00:00
for _ , label := range c . cfg . Labels {
2022-12-21 15:20:34 +00:00
key , val , _ := strings . Cut ( label , "=" )
if ! strings . HasPrefix ( key , netlabel . DriverPrefix + "." + ntype ) {
2016-03-01 02:17:04 +00:00
continue
}
2022-12-21 15:20:34 +00:00
cfg [ key ] = val
2016-03-01 02:17:04 +00:00
}
2023-07-16 17:29:56 +00:00
// Merge in the existing config for this driver.
for k , v := range c . cfg . DriverConfig ( ntype ) {
cfg [ k ] = v
2016-03-01 02:17:04 +00:00
}
2023-01-13 23:38:46 +00:00
if c . cfg . Scope . IsValid ( ) {
// FIXME: every driver instance constructs a new DataStore
// instance against the same database. Yikes!
cfg [ netlabel . LocalKVClient ] = discoverapi . DatastoreConfigData {
2023-07-28 17:11:00 +00:00
Scope : scope . Local ,
2023-01-13 23:38:46 +00:00
Provider : c . cfg . Scope . Client . Provider ,
Address : c . cfg . Scope . Client . Address ,
Config : c . cfg . Scope . Client . Config ,
2016-03-01 02:17:04 +00:00
}
}
2022-12-21 15:15:49 +00:00
return cfg
2016-03-01 02:17:04 +00:00
}
2023-01-11 22:43:32 +00:00
// ID returns the controller's unique identity.
func ( c * Controller ) ID ( ) string {
2015-09-09 21:24:05 +00:00
return c . id
}
2023-01-11 22:43:32 +00:00
// BuiltinDrivers returns the list of builtin network drivers.
func ( c * Controller ) BuiltinDrivers ( ) [ ] string {
2016-06-30 12:48:14 +00:00
drivers := [ ] string { }
2016-12-19 03:56:34 +00:00
c . drvRegistry . WalkDrivers ( func ( name string , driver driverapi . Driver , capability driverapi . Capability ) bool {
if driver . IsBuiltIn ( ) {
drivers = append ( drivers , name )
2016-06-30 12:48:14 +00:00
}
2016-12-19 03:56:34 +00:00
return false
} )
return drivers
}
2023-01-11 22:43:32 +00:00
// BuiltinIPAMDrivers returns the list of builtin ipam drivers.
func ( c * Controller ) BuiltinIPAMDrivers ( ) [ ] string {
2016-12-19 03:56:34 +00:00
drivers := [ ] string { }
2023-08-16 09:28:38 +00:00
c . ipamRegistry . WalkIPAMs ( func ( name string , driver ipamapi . Ipam , _ * ipamapi . Capability ) bool {
2016-12-19 03:56:34 +00:00
if driver . IsBuiltIn ( ) {
drivers = append ( drivers , name )
}
return false
} )
2016-06-30 12:48:14 +00:00
return drivers
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) processNodeDiscovery ( nodes [ ] net . IP , add bool ) {
2016-03-01 02:17:04 +00:00
c . drvRegistry . WalkDrivers ( func ( name string , driver driverapi . Driver , capability driverapi . Capability ) bool {
2023-07-27 10:36:25 +00:00
if d , ok := driver . ( discoverapi . Discover ) ; ok {
c . pushNodeDiscovery ( d , capability , nodes , add )
}
2016-03-01 02:17:04 +00:00
return false
} )
2015-09-18 19:54:08 +00:00
}
2023-08-16 09:28:38 +00:00
func ( c * Controller ) pushNodeDiscovery ( d discoverapi . Discover , capability driverapi . Capability , nodes [ ] net . IP , add bool ) {
2015-09-18 19:54:08 +00:00
var self net . IP
2021-12-22 09:42:13 +00:00
// try swarm-mode config
if agent := c . getAgent ( ) ; agent != nil {
self = net . ParseIP ( agent . advertiseAddr )
2015-09-18 19:54:08 +00:00
}
2016-03-01 02:17:04 +00:00
2023-08-16 09:28:38 +00:00
if d == nil || capability . ConnectivityScope != scope . Global || nodes == nil {
2015-09-18 19:54:08 +00:00
return
}
2016-03-01 02:17:04 +00:00
2015-09-18 19:54:08 +00:00
for _ , node := range nodes {
2016-01-28 19:54:03 +00:00
nodeData := discoverapi . NodeDiscoveryData { Address : node . String ( ) , Self : node . Equal ( self ) }
2015-09-18 19:54:08 +00:00
var err error
if add {
2016-03-01 02:17:04 +00:00
err = d . DiscoverNew ( discoverapi . NodeDiscovery , nodeData )
2015-09-18 19:54:08 +00:00
} else {
2016-03-01 02:17:04 +00:00
err = d . DiscoverDelete ( discoverapi . NodeDiscovery , nodeData )
2015-09-18 19:54:08 +00:00
}
if err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Debugf ( "discovery notification error: %v" , err )
2015-09-18 19:54:08 +00:00
}
}
2015-05-15 22:23:59 +00:00
}
2023-01-11 22:43:32 +00:00
// Config returns the bootup configuration for the controller.
func ( c * Controller ) Config ( ) config . Config {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
defer c . mu . Unlock ( )
2015-06-13 21:28:34 +00:00
if c . cfg == nil {
return config . Config { }
}
2015-06-11 13:52:46 +00:00
return * c . cfg
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) isManager ( ) bool {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
defer c . mu . Unlock ( )
2022-09-23 17:40:11 +00:00
if c . cfg == nil || c . cfg . ClusterProvider == nil {
2016-05-24 23:17:19 +00:00
return false
}
2022-09-23 17:40:11 +00:00
return c . cfg . ClusterProvider . IsManager ( )
2016-05-24 23:17:19 +00:00
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) isAgent ( ) bool {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
defer c . mu . Unlock ( )
2022-09-23 17:40:11 +00:00
if c . cfg == nil || c . cfg . ClusterProvider == nil {
2016-05-24 23:17:19 +00:00
return false
}
2022-09-23 17:40:11 +00:00
return c . cfg . ClusterProvider . IsAgent ( )
2016-05-24 23:17:19 +00:00
}
2023-10-17 21:59:19 +00:00
func ( c * Controller ) isSwarmNode ( ) bool {
return c . isManager ( ) || c . isAgent ( )
2016-05-24 23:17:19 +00:00
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) GetPluginGetter ( ) plugingetter . PluginGetter {
2023-01-24 23:19:26 +00:00
return c . cfg . PluginGetter
2016-09-27 20:54:25 +00:00
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) RegisterDriver ( networkType string , driver driverapi . Driver , capability driverapi . Capability ) error {
2023-07-27 10:36:25 +00:00
if d , ok := driver . ( discoverapi . Discover ) ; ok {
c . agentDriverNotify ( d )
}
2015-09-22 20:20:55 +00:00
return nil
}
2018-10-09 14:04:31 +00:00
// XXX This should be made driver agnostic. See comment below.
const overlayDSROptionString = "dsr"
2015-04-30 01:25:01 +00:00
// NewNetwork creates a new network of the specified network type. The options
// are network specific and modeled in a generic way.
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
func ( c * Controller ) NewNetwork ( networkType , name string , id string , options ... NetworkOption ) ( _ * Network , retErr error ) {
2016-09-12 22:19:22 +00:00
if id != "" {
c . networkLocker . Lock ( id )
2022-07-13 20:30:47 +00:00
defer c . networkLocker . Unlock ( id ) //nolint:errcheck
2016-09-12 22:19:22 +00:00
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if _ , err := c . NetworkByID ( id ) ; err == nil {
2016-09-12 22:19:22 +00:00
return nil , NetworkNameError ( id )
}
}
2023-07-16 16:52:41 +00:00
if strings . TrimSpace ( name ) == "" {
2017-02-02 02:17:29 +00:00
return nil , ErrInvalidName ( name )
2015-05-08 02:59:06 +00:00
}
2015-04-30 01:25:01 +00:00
libnet: Make sure network names are unique
Fixes #18864, #20648, #33561, #40901.
[This GH comment][1] makes clear network name uniqueness has never been
enforced due to the eventually consistent nature of Classic Swarm
datastores:
> there is no guaranteed way to check for duplicates across a cluster of
> docker hosts.
And this is further confirmed by other comments made by @mrjana in that
same issue, eg. [this one][2]:
> we want to adopt a schema which can pave the way in the future for a
> completely decentralized cluster of docker hosts (if scalability is
> needed).
This decentralized model is what Classic Swarm was trying to be. It's
been superseded since then by Docker Swarm, which has a centralized
control plane.
To circumvent this drawback, the `NetworkCreate` endpoint accepts a
`CheckDuplicate` flag. However it's not perfectly reliable as it won't
catch concurrent requests.
Due to this design decision, API clients like Compose have to implement
workarounds to make sure names are really unique (eg.
docker/compose#9585). And the daemon itself has seen a string of issues
due to that decision, including some that aren't fixed to this day (for
instance moby/moby#40901):
> The problem is, that if you specify a network for a container using
> the ID, it will add that network to the container but it will then
> change it to reference the network by using the name.
To summarize, this "feature" is broken, has no practical use and is a
source of pain for Docker users and API consumers. So let's just remove
it for _all_ API versions.
[1]: https://github.com/moby/moby/issues/18864#issuecomment-167201414
[2]: https://github.com/moby/moby/issues/18864#issuecomment-167202589
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2023-08-16 18:11:10 +00:00
// Make sure two concurrent calls to this method won't create conflicting
// networks, otherwise libnetwork will end up in an invalid state.
if name != "" {
c . networkLocker . Lock ( name )
defer c . networkLocker . Unlock ( name )
if _ , err := c . NetworkByName ( name ) ; err == nil {
return nil , NetworkNameError ( name )
}
}
2016-02-29 19:49:04 +00:00
if id == "" {
id = stringid . GenerateRandomID ( )
}
2016-10-12 23:55:20 +00:00
defaultIpam := defaultIpamForNetworkType ( networkType )
2015-04-30 01:25:01 +00:00
// Construct the network object
2023-07-21 22:38:57 +00:00
nw := & Network {
2018-10-09 14:04:31 +00:00
name : name ,
networkType : networkType ,
generic : map [ string ] interface { } { netlabel . GenericData : make ( map [ string ] string ) } ,
ipamType : defaultIpam ,
id : id ,
created : time . Now ( ) ,
ctrlr : c ,
persist : true ,
drvOnce : & sync . Once { } ,
loadBalancerMode : loadBalancerModeDefault ,
2015-04-30 01:25:01 +00:00
}
2022-12-21 15:15:49 +00:00
nw . processOptions ( options ... )
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := nw . validateConfiguration ( ) ; err != nil {
2017-04-07 17:51:39 +00:00
return nil , err
}
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
// These variables must be defined here, as declaration would otherwise
// be skipped by the "goto addToStore"
var (
caps driverapi . Capability
err error
skipCfgEpCount bool
)
2017-04-07 17:51:39 +00:00
// Reset network types, force local scope and skip allocation and
// plumbing for configuration networks. Reset of the config-only
// network drivers is needed so that this special network is not
// usable by old engine versions.
2022-12-21 15:15:49 +00:00
if nw . configOnly {
2023-07-28 17:11:00 +00:00
nw . scope = scope . Local
2022-12-21 15:15:49 +00:00
nw . networkType = "null"
2017-04-07 17:51:39 +00:00
goto addToStore
}
2015-05-31 18:49:11 +00:00
2022-12-21 15:15:49 +00:00
_ , caps , err = nw . resolveDriver ( nw . networkType , true )
2016-05-24 23:17:19 +00:00
if err != nil {
return nil , err
}
2023-07-28 17:11:00 +00:00
if nw . scope == scope . Local && caps . DataScope == scope . Global {
2017-04-07 20:31:44 +00:00
return nil , types . ForbiddenErrorf ( "cannot downgrade network scope for %s networks" , networkType )
}
2023-07-28 17:11:00 +00:00
if nw . ingress && caps . DataScope != scope . Global {
2017-03-02 03:09:39 +00:00
return nil , types . ForbiddenErrorf ( "Ingress network can only be global scope network" )
}
2017-04-07 20:31:44 +00:00
// At this point the network scope is still unknown if not set by user
2023-07-28 17:11:00 +00:00
if ( caps . DataScope == scope . Global || nw . scope == scope . Swarm ) &&
2023-10-17 21:59:19 +00:00
c . isSwarmNode ( ) && ! nw . dynamic {
2016-05-24 23:17:19 +00:00
if c . isManager ( ) {
// For non-distributed controlled environment, globalscoped non-dynamic networks are redirected to Manager
return nil , ManagerRedirectError ( name )
}
return nil , types . ForbiddenErrorf ( "Cannot create a multi-host network from a worker node. Please create the network from a manager node." )
}
2023-10-17 21:59:19 +00:00
if nw . scope == scope . Swarm && ! c . isSwarmNode ( ) {
2017-05-18 15:59:52 +00:00
return nil , types . ForbiddenErrorf ( "cannot create a swarm scoped network when swarm is not active" )
}
2015-10-05 11:21:15 +00:00
// Make sure we have a driver available for this network type
// before we allocate anything.
2022-12-21 15:15:49 +00:00
if _ , err := nw . driver ( true ) ; err != nil {
2015-10-03 23:11:50 +00:00
return nil , err
}
2017-04-07 17:51:39 +00:00
// From this point on, we need the network specific configuration,
// which may come from a configuration-only network
2022-12-21 15:15:49 +00:00
if nw . configFrom != "" {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
configNetwork , err := c . getConfigNetwork ( nw . configFrom )
2017-04-07 17:51:39 +00:00
if err != nil {
2022-12-21 15:15:49 +00:00
return nil , types . NotFoundErrorf ( "configuration network %q does not exist" , nw . configFrom )
2017-04-07 17:51:39 +00:00
}
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := configNetwork . applyConfigurationTo ( nw ) ; err != nil {
2017-04-07 17:51:39 +00:00
return nil , types . InternalErrorf ( "Failed to apply configuration: %v" , err )
}
2022-12-21 15:15:49 +00:00
nw . generic [ netlabel . Internal ] = nw . internal
2017-04-07 17:51:39 +00:00
defer func ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if retErr == nil && ! skipCfgEpCount {
if err := configNetwork . getEpCnt ( ) . IncEndpointCnt ( ) ; err != nil {
log . G ( context . TODO ( ) ) . Warnf ( "Failed to update reference count for configuration network %q on creation of network %q: %v" , configNetwork . Name ( ) , nw . name , err )
2017-04-07 17:51:39 +00:00
}
}
} ( )
}
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := nw . ipamAllocate ( ) ; err != nil {
2015-10-03 23:11:50 +00:00
return nil , err
}
defer func ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if retErr != nil {
2022-12-21 15:15:49 +00:00
nw . ipamRelease ( )
2015-10-03 23:11:50 +00:00
}
} ( )
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
// Note from thaJeztah to future code visitors, or "future self".
//
// This code was previously assigning the error to the global "err"
// variable (before it was renamed to "retErr"), but in case of a
// "MaskableError" did not *return* the error:
// https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
//
// Depending on code paths further down, that meant that this error
// was either overwritten by other errors (and thus not handled in
// defer statements) or handled (if no other code was overwriting it.
//
// I suspect this was a bug (but possible without effect), but it could
// have been intentional. This logic is confusing at least, and even
// more so combined with the handling in defer statements that check for
// both the "err" return AND "skipCfgEpCount":
// https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
//
// To save future visitors some time to dig up history:
//
// - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
// - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
// - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
//
// To cut a long story short: if this broke anything, you know who to blame :)
if err := c . addNetwork ( nw ) ; err != nil {
2022-07-13 20:30:47 +00:00
if _ , ok := err . ( types . MaskableError ) ; ok { //nolint:gosimple
2019-07-08 20:52:31 +00:00
// This error can be ignored and set this boolean
// value to skip a refcount increment for configOnly networks
skipCfgEpCount = true
} else {
return nil , err
}
2015-04-30 01:25:01 +00:00
}
2015-10-12 05:28:26 +00:00
defer func ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if retErr != nil {
if err := nw . deleteNetwork ( ) ; err != nil {
log . G ( context . TODO ( ) ) . Warnf ( "couldn't roll back driver network on network %s creation failure: %v" , nw . name , retErr )
2015-10-12 05:28:26 +00:00
}
}
} ( )
2015-04-30 01:25:01 +00:00
2018-10-09 14:04:31 +00:00
// XXX If the driver type is "overlay" check the options for DSR
// being set. If so, set the network's load balancing mode to DSR.
// This should really be done in a network option, but due to
// time pressure to get this in without adding changes to moby,
// swarm and CLI, it is being implemented as a driver-specific
// option. Unfortunately, drivers can't influence the core
2023-07-21 22:38:57 +00:00
// "libnetwork.Network" data type. Hence we need this hack code
2018-10-09 14:04:31 +00:00
// to implement in this manner.
2022-12-21 15:15:49 +00:00
if gval , ok := nw . generic [ netlabel . GenericData ] ; ok && nw . networkType == "overlay" {
2018-10-09 14:04:31 +00:00
optMap := gval . ( map [ string ] string )
if _ , ok := optMap [ overlayDSROptionString ] ; ok {
2022-12-21 15:15:49 +00:00
nw . loadBalancerMode = loadBalancerModeDSR
2018-10-09 14:04:31 +00:00
}
}
2017-04-07 17:51:39 +00:00
addToStore :
2016-03-05 10:00:31 +00:00
// First store the endpoint count, then the network. To avoid to
// end up with a datastore containing a network and not an epCnt,
// in case of an ungraceful shutdown during this function call.
2022-12-21 15:15:49 +00:00
epCnt := & endpointCnt { n : nw }
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := c . updateToStore ( epCnt ) ; err != nil {
2015-10-12 05:28:26 +00:00
return nil , err
}
defer func ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if retErr != nil {
if err := c . deleteFromStore ( epCnt ) ; err != nil {
log . G ( context . TODO ( ) ) . Warnf ( "could not rollback from store, epCnt %v on failure (%v): %v" , epCnt , retErr , err )
2015-10-12 05:28:26 +00:00
}
2015-06-05 20:31:12 +00:00
}
2015-10-12 05:28:26 +00:00
} ( )
2022-12-21 15:15:49 +00:00
nw . epCnt = epCnt
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := c . updateToStore ( nw ) ; err != nil {
2015-05-30 03:42:23 +00:00
return nil , err
}
2017-11-04 20:58:54 +00:00
defer func ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if retErr != nil {
if err := c . deleteFromStore ( nw ) ; err != nil {
log . G ( context . TODO ( ) ) . Warnf ( "could not rollback from store, network %v on failure (%v): %v" , nw , retErr , err )
2017-11-04 20:58:54 +00:00
}
}
} ( )
2022-12-21 15:15:49 +00:00
if nw . configOnly {
return nw , nil
2017-04-07 17:51:39 +00:00
}
2015-05-30 03:42:23 +00:00
2022-12-21 15:15:49 +00:00
joinCluster ( nw )
2017-11-30 08:22:30 +00:00
defer func ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if retErr != nil {
2022-12-21 15:15:49 +00:00
nw . cancelDriverWatches ( )
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := nw . leaveCluster ( ) ; err != nil {
log . G ( context . TODO ( ) ) . Warnf ( "Failed to leave agent cluster on network %s on failure (%v): %v" , nw . name , retErr , err )
2017-11-30 08:22:30 +00:00
}
}
} ( )
2022-12-21 15:15:49 +00:00
if nw . hasLoadBalancerEndpoint ( ) {
libnetwork: Controller.NewNetwork: use named error-return
It's used in various defers, but was using `err` as name, which can be
confusing, and increases the risk of accidentally shadowing the error.
This patch:
- introduces a `retErr` output variable, to be used in defer statements.
- explicitly changes some `err` uses to locally-scoped variables.
- moves some variable definitions closer to where they're used (where possible).
While working on this change, there was one point in the code where
error handling was ambiguous. I added a note for that, in case this
was not a bug:
> This code was previously assigning the error to the global "err"
> variable (before it was renamed to "retErr"), but in case of a
> "MaskableError" did not *return* the error:
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L566-L573
>
> Depending on code paths further down, that meant that this error
> was either overwritten by other errors (and thus not handled in
> defer statements) or handled (if no other code was overwriting it.
>
> I suspect this was a bug (but possible without effect), but it could
> have been intentional. This logic is confusing at least, and even
> more so combined with the handling in defer statements that check for
> both the "err" return AND "skipCfgEpCount":
> https://github.com/moby/moby/blob/b325dcbff60a04cedbe40eb627465fc7379d05bf/libnetwork/controller.go#L586-L602
>
> To save future visitors some time to dig up history:
>
> - config-only networks were added in 25082206df465d1c11dd1276a65b4a1dc701bd43
> - the special error-handling and "skipCfgEpcoung" was added in ddd22a819867faa0cd7d12b0c3fad1099ac3eb26
> - and updated in 87b082f3659f9ec245ab15d781e6bfffced0af83 to don't use string-matching
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-16 11:17:01 +00:00
if err := nw . createLoadBalancerSandbox ( ) ; err != nil {
2017-11-04 20:58:54 +00:00
return nil , err
}
}
2023-10-17 21:59:19 +00:00
if c . isSwarmNode ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2016-08-15 17:54:18 +00:00
arrangeIngressFilterRule ( )
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-08-15 17:54:18 +00:00
}
libnetwork: Controller.NewNetwork: inline arrangeUserFilterRule()
arrangeUserFilterRule uses the package-level [`ctrl` variable][1], which
holds a reference to a controller instance. This variable is set by
[`setupArrangeUserFilterRule()`][2], which is called when initialization
a controller ([`libnetwork.New`][3]).
In normal circumstances, there would only be one controller, created during
daemon startup, and the instance of the controller would be the same as
the controller that `NewNetwork` is called from, but there's no protection
for the `ctrl` variable, and various integration tests create their own
controller instance.
The global `ctrl` var was introduced in [54e7900fb89b1aeeb188d935f29cf05514fd419b][4],
with the assumption that [only one controller could ever exist][5].
This patch tries to reduce uses of the `ctrl` variable, and as we're calling
this code from inside a method on a specific controller, we inline the code
and use that specific controller instead.
[1]: https://github.com/moby/moby/blob/37b908aa628ccf8f1e10182d2fc049423707422d/libnetwork/firewall_linux.go#L12
[2]: https://github.com/moby/moby/blob/37b908aa628ccf8f1e10182d2fc049423707422d/libnetwork/firewall_linux.go#L14-L17
[3]: https://github.com/moby/moby/blob/37b908aa628ccf8f1e10182d2fc049423707422d/libnetwork/controller.go#L163
[4]: https://github.com/moby/libnetwork/commit/54e7900fb89b1aeeb188d935f29cf05514fd419b
[5]: https://github.com/moby/libnetwork/pull/2471#discussion_r343457183
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-07-16 14:47:15 +00:00
// Sets up the DOCKER-USER chain for each iptables version (IPv4, IPv6)
// that's enabled in the controller's configuration.
for _ , ipVersion := range c . enabledIptablesVersions ( ) {
if err := setupUserChain ( ipVersion ) ; err != nil {
log . G ( context . TODO ( ) ) . WithError ( err ) . Warnf ( "Controller.NewNetwork %s:" , name )
}
}
2017-03-13 07:46:46 +00:00
2022-12-21 15:15:49 +00:00
return nw , nil
2015-04-30 01:25:01 +00:00
}
2023-07-21 22:38:57 +00:00
var joinCluster NetworkWalker = func ( nw * Network ) bool {
if nw . configOnly {
2017-04-07 17:51:39 +00:00
return false
}
2023-07-21 22:38:57 +00:00
if err := nw . joinCluster ( ) ; err != nil {
log . G ( context . TODO ( ) ) . Errorf ( "Failed to join network %s (%s) into agent cluster: %v" , nw . Name ( ) , nw . ID ( ) , err )
2016-07-13 00:35:32 +00:00
}
2023-07-21 22:38:57 +00:00
nw . addDriverWatches ( )
2016-07-13 00:35:32 +00:00
return false
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) reservePools ( ) {
2023-01-14 00:04:43 +00:00
networks , err := c . getNetworks ( )
2016-04-18 22:11:36 +00:00
if err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "Could not retrieve networks from local store during ipam allocation for existing networks: %v" , err )
2016-04-18 22:11:36 +00:00
return
}
for _ , n := range networks {
2017-04-07 17:51:39 +00:00
if n . configOnly {
continue
}
2016-04-18 22:11:36 +00:00
if ! doReplayPoolReserve ( n ) {
continue
}
// Construct pseudo configs for the auto IP case
autoIPv4 := ( len ( n . ipamV4Config ) == 0 || ( len ( n . ipamV4Config ) == 1 && n . ipamV4Config [ 0 ] . PreferredPool == "" ) ) && len ( n . ipamV4Info ) > 0
autoIPv6 := ( len ( n . ipamV6Config ) == 0 || ( len ( n . ipamV6Config ) == 1 && n . ipamV6Config [ 0 ] . PreferredPool == "" ) ) && len ( n . ipamV6Info ) > 0
if autoIPv4 {
n . ipamV4Config = [ ] * IpamConf { { PreferredPool : n . ipamV4Info [ 0 ] . Pool . String ( ) } }
}
if n . enableIPv6 && autoIPv6 {
n . ipamV6Config = [ ] * IpamConf { { PreferredPool : n . ipamV6Info [ 0 ] . Pool . String ( ) } }
}
// Account current network gateways
2022-12-21 15:15:49 +00:00
for i , cfg := range n . ipamV4Config {
if cfg . Gateway == "" && n . ipamV4Info [ i ] . Gateway != nil {
cfg . Gateway = n . ipamV4Info [ i ] . Gateway . IP . String ( )
2016-04-18 22:11:36 +00:00
}
}
2016-09-15 18:21:33 +00:00
if n . enableIPv6 {
2022-12-21 15:15:49 +00:00
for i , cfg := range n . ipamV6Config {
if cfg . Gateway == "" && n . ipamV6Info [ i ] . Gateway != nil {
cfg . Gateway = n . ipamV6Info [ i ] . Gateway . IP . String ( )
2016-09-15 18:21:33 +00:00
}
2016-04-18 22:11:36 +00:00
}
}
2016-06-11 16:30:34 +00:00
// Reserve pools
2016-04-18 22:11:36 +00:00
if err := n . ipamAllocate ( ) ; err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "Failed to allocate ipam pool(s) for network %q (%s): %v" , n . Name ( ) , n . ID ( ) , err )
2016-04-18 22:11:36 +00:00
}
2016-06-11 16:30:34 +00:00
// Reserve existing endpoints' addresses
ipam , _ , err := n . getController ( ) . getIPAMDriver ( n . ipamType )
if err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "Failed to retrieve ipam driver for network %q (%s) during address reservation" , n . Name ( ) , n . ID ( ) )
2016-06-11 16:30:34 +00:00
continue
}
epl , err := n . getEndpointsFromStore ( )
if err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "Failed to retrieve list of current endpoints on network %q (%s)" , n . Name ( ) , n . ID ( ) )
2016-06-11 16:30:34 +00:00
continue
}
for _ , ep := range epl {
2020-04-03 04:21:47 +00:00
if ep . Iface ( ) == nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "endpoint interface is empty for %q (%s)" , ep . Name ( ) , ep . ID ( ) )
2020-04-03 04:21:47 +00:00
continue
}
2016-06-11 16:30:34 +00:00
if err := ep . assignAddress ( ipam , true , ep . Iface ( ) . AddressIPv6 ( ) != nil ) ; err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "Failed to reserve current address for endpoint %q (%s) on network %q (%s)" ,
2016-06-11 16:30:34 +00:00
ep . Name ( ) , ep . ID ( ) , n . Name ( ) , n . ID ( ) )
}
}
2016-04-18 22:11:36 +00:00
}
}
2023-07-21 22:38:57 +00:00
func doReplayPoolReserve ( n * Network ) bool {
2016-04-18 22:11:36 +00:00
_ , caps , err := n . getController ( ) . getIPAMDriver ( n . ipamType )
if err != nil {
2023-06-23 00:33:17 +00:00
log . G ( context . TODO ( ) ) . Warnf ( "Failed to retrieve ipam driver for network %q (%s): %v" , n . Name ( ) , n . ID ( ) , err )
2016-04-18 22:11:36 +00:00
return false
}
return caps . RequiresRequestReplay
}
2023-07-21 22:38:57 +00:00
func ( c * Controller ) addNetwork ( n * Network ) error {
2016-01-16 22:24:44 +00:00
d , err := n . driver ( true )
2015-10-05 11:21:15 +00:00
if err != nil {
2015-10-03 23:11:50 +00:00
return err
2015-05-31 18:49:11 +00:00
}
2015-05-13 21:12:57 +00:00
2015-05-31 18:49:11 +00:00
// Create the network
2016-03-30 21:42:58 +00:00
if err := d . CreateNetwork ( n . id , n . generic , n , n . getIPData ( 4 ) , n . getIPData ( 6 ) ) ; err != nil {
2015-05-31 18:49:11 +00:00
return err
}
2015-05-13 15:41:45 +00:00
2016-09-19 22:48:06 +00:00
n . startResolver ( )
2015-05-30 03:42:23 +00:00
return nil
2015-05-13 15:41:45 +00:00
}
2023-01-11 22:43:32 +00:00
// Networks returns the list of Network(s) managed by this controller.
2023-09-10 00:05:05 +00:00
func ( c * Controller ) Networks ( ctx context . Context ) [ ] * Network {
2023-07-21 22:38:57 +00:00
var list [ ] * Network
2015-04-30 01:25:01 +00:00
2023-09-10 00:05:05 +00:00
for _ , n := range c . getNetworksFromStore ( ctx ) {
2016-03-05 10:00:31 +00:00
if n . inDelete {
continue
}
2015-04-30 01:25:01 +00:00
list = append ( list , n )
}
return list
}
2023-01-11 22:43:32 +00:00
// WalkNetworks uses the provided function to walk the Network(s) managed by this controller.
func ( c * Controller ) WalkNetworks ( walker NetworkWalker ) {
2023-09-10 00:05:05 +00:00
for _ , n := range c . Networks ( context . TODO ( ) ) {
2015-04-30 01:25:01 +00:00
if walker ( n ) {
return
}
}
}
2023-01-11 22:43:32 +00:00
// NetworkByName returns the Network which has the passed name.
// If not found, the error [ErrNoSuchNetwork] is returned.
2023-07-21 22:38:57 +00:00
func ( c * Controller ) NetworkByName ( name string ) ( * Network , error ) {
2015-05-11 23:13:27 +00:00
if name == "" {
2015-05-14 21:56:15 +00:00
return nil , ErrInvalidName ( name )
2015-05-11 23:13:27 +00:00
}
2023-07-21 22:38:57 +00:00
var n * Network
2015-04-30 01:25:01 +00:00
2023-07-21 22:38:57 +00:00
c . WalkNetworks ( func ( current * Network ) bool {
2015-05-11 23:13:27 +00:00
if current . Name ( ) == name {
n = current
return true
2015-04-30 01:25:01 +00:00
}
2015-05-11 23:13:27 +00:00
return false
2023-07-21 22:38:57 +00:00
} )
2015-05-11 23:13:27 +00:00
2015-05-15 23:04:09 +00:00
if n == nil {
2015-05-14 21:56:15 +00:00
return nil , ErrNoSuchNetwork ( name )
2015-05-15 23:04:09 +00:00
}
2015-05-11 23:13:27 +00:00
return n , nil
2015-04-30 01:25:01 +00:00
}
2023-01-11 22:43:32 +00:00
// NetworkByID returns the Network which has the passed id.
// If not found, the error [ErrNoSuchNetwork] is returned.
2023-07-21 22:38:57 +00:00
func ( c * Controller ) NetworkByID ( id string ) ( * Network , error ) {
2015-05-11 23:13:27 +00:00
if id == "" {
2015-05-14 21:56:15 +00:00
return nil , ErrInvalidID ( id )
2015-05-11 23:13:27 +00:00
}
2023-08-16 14:24:09 +00:00
return c . getNetworkFromStore ( id )
2015-04-30 01:25:01 +00:00
}
2023-01-11 22:43:32 +00:00
// NewSandbox creates a new sandbox for containerID.
2023-08-16 11:24:44 +00:00
func ( c * Controller ) NewSandbox ( containerID string , options ... SandboxOption ) ( _ * Sandbox , retErr error ) {
2015-07-02 05:00:48 +00:00
if containerID == "" {
2023-08-08 11:35:05 +00:00
return nil , types . InvalidParameterErrorf ( "invalid container ID" )
2015-07-02 05:00:48 +00:00
}
2023-01-12 01:10:09 +00:00
var sb * Sandbox
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2015-11-02 07:03:26 +00:00
for _ , s := range c . sandboxes {
if s . containerID == containerID {
// If not a stub, then we already have a complete sandbox.
if ! s . isStub {
2016-10-04 22:40:47 +00:00
sbID := s . ID ( )
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-10-04 22:40:47 +00:00
return nil , types . ForbiddenErrorf ( "container %s is already present in sandbox %s" , containerID , sbID )
2015-11-02 07:03:26 +00:00
}
// We already have a stub sandbox from the
// store. Make use of it so that we don't lose
// the endpoints from store but reset the
// isStub flag.
sb = s
sb . isStub = false
break
}
2015-07-02 05:00:48 +00:00
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2015-07-02 05:00:48 +00:00
// Create sandbox and process options first. Key generation depends on an option
2015-11-02 07:03:26 +00:00
if sb == nil {
2023-08-12 12:29:33 +00:00
// TODO(thaJeztah): given that a "containerID" must be unique in the list of sandboxes, is there any reason we're not using containerID as sandbox ID on non-Windows?
sandboxID := containerID
if runtime . GOOS != "windows" {
sandboxID = stringid . GenerateRandomID ( )
}
2023-01-12 01:10:09 +00:00
sb = & Sandbox {
2017-11-06 23:42:11 +00:00
id : sandboxID ,
2016-06-15 21:00:48 +00:00
containerID : containerID ,
2023-01-12 01:42:24 +00:00
endpoints : [ ] * Endpoint { } ,
2016-06-15 21:00:48 +00:00
epPriority : map [ string ] int { } ,
populatedEndpoints : map [ string ] struct { } { } ,
config : containerConfig { } ,
controller : c ,
2016-12-19 02:27:13 +00:00
extDNS : [ ] extDNSEntry { } ,
2015-11-02 07:03:26 +00:00
}
2015-07-02 05:00:48 +00:00
}
sb . processOptions ( options ... )
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2016-05-31 06:55:51 +00:00
if sb . ingress && c . ingressSandbox != nil {
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-07-13 04:02:10 +00:00
return nil , types . ForbiddenErrorf ( "ingress sandbox already present" )
2016-05-31 06:55:51 +00:00
}
2016-06-08 02:49:36 +00:00
if sb . ingress {
c . ingressSandbox = sb
2022-09-23 17:40:11 +00:00
sb . config . hostsPath = filepath . Join ( c . cfg . DataDir , "/network/files/hosts" )
sb . config . resolvConfPath = filepath . Join ( c . cfg . DataDir , "/network/files/resolv.conf" )
2016-09-15 22:22:57 +00:00
sb . id = "ingress_sbox"
2018-07-23 21:18:16 +00:00
} else if sb . loadBalancerNID != "" {
sb . id = "lb_" + sb . loadBalancerNID
2016-06-08 02:49:36 +00:00
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-06-12 18:30:30 +00:00
2016-05-31 06:55:51 +00:00
defer func ( ) {
2023-08-16 11:24:44 +00:00
if retErr != nil {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2016-05-31 06:55:51 +00:00
if sb . ingress {
c . ingressSandbox = nil
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2016-05-31 06:55:51 +00:00
}
} ( )
2023-08-16 11:24:44 +00:00
if err := sb . setupResolutionFiles ( ) ; err != nil {
2015-07-02 05:00:48 +00:00
return nil , err
}
2023-08-20 10:48:09 +00:00
if err := c . setupOSLSandbox ( sb ) ; err != nil {
return nil , err
2018-05-18 21:10:14 +00:00
}
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2015-07-02 05:00:48 +00:00
c . sandboxes [ sb . id ] = sb
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2015-10-08 03:01:38 +00:00
defer func ( ) {
2023-08-16 11:24:44 +00:00
if retErr != nil {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2015-10-08 03:01:38 +00:00
delete ( c . sandboxes , sb . id )
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2015-10-08 03:01:38 +00:00
}
} ( )
2023-08-16 11:24:44 +00:00
if err := sb . storeUpdate ( ) ; err != nil {
2016-12-27 11:42:32 +00:00
return nil , fmt . Errorf ( "failed to update the store state of sandbox: %v" , err )
2015-10-08 03:01:38 +00:00
}
2015-07-02 05:00:48 +00:00
return sb , nil
}
2023-08-12 12:38:43 +00:00
// GetSandbox returns the Sandbox which has the passed id.
//
// It returns an [ErrInvalidID] when passing an invalid ID, or an
// [types.NotFoundError] if no Sandbox was found for the container.
func ( c * Controller ) GetSandbox ( containerID string ) ( * Sandbox , error ) {
if containerID == "" {
return nil , ErrInvalidID ( "id is empty" )
}
c . mu . Lock ( )
defer c . mu . Unlock ( )
if runtime . GOOS == "windows" {
// fast-path for Windows, which uses the container ID as sandbox ID.
if sb := c . sandboxes [ containerID ] ; sb != nil && ! sb . isStub {
return sb , nil
}
} else {
for _ , sb := range c . sandboxes {
if sb . containerID == containerID && ! sb . isStub {
return sb , nil
}
}
}
return nil , types . NotFoundErrorf ( "network sandbox for container %s not found" , containerID )
}
2023-01-11 22:43:32 +00:00
// SandboxByID returns the Sandbox which has the passed id.
// If not found, a [types.NotFoundError] is returned.
2023-01-12 01:10:09 +00:00
func ( c * Controller ) SandboxByID ( id string ) ( * Sandbox , error ) {
2015-07-02 05:00:48 +00:00
if id == "" {
return nil , ErrInvalidID ( id )
}
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2015-07-02 05:00:48 +00:00
s , ok := c . sandboxes [ id ]
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2015-07-02 05:00:48 +00:00
if ! ok {
return nil , types . NotFoundErrorf ( "sandbox %s not found" , id )
}
return s , nil
}
2023-01-11 22:43:32 +00:00
// SandboxDestroy destroys a sandbox given a container ID.
func ( c * Controller ) SandboxDestroy ( id string ) error {
2023-01-12 01:10:09 +00:00
var sb * Sandbox
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2015-11-02 07:03:26 +00:00
for _ , s := range c . sandboxes {
if s . containerID == id {
sb = s
break
}
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2015-11-02 07:03:26 +00:00
// It is not an error if sandbox is not available
if sb == nil {
return nil
}
return sb . Delete ( )
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) loadDriver ( networkType string ) error {
2016-10-17 21:35:38 +00:00
var err error
if pg := c . GetPluginGetter ( ) ; pg != nil {
2017-01-10 21:17:15 +00:00
_ , err = pg . Get ( networkType , driverapi . NetworkPluginEndpointType , plugingetter . Lookup )
2016-10-17 21:35:38 +00:00
} else {
_ , err = plugins . Get ( networkType , driverapi . NetworkPluginEndpointType )
}
2015-05-16 01:14:36 +00:00
if err != nil {
2018-06-12 16:26:11 +00:00
if errors . Cause ( err ) == plugins . ErrNotFound {
2016-03-01 02:17:04 +00:00
return types . NotFoundErrorf ( err . Error ( ) )
2015-05-14 21:56:15 +00:00
}
2016-03-01 02:17:04 +00:00
return err
2015-05-16 01:14:36 +00:00
}
2016-03-01 02:17:04 +00:00
return nil
2015-06-06 17:21:51 +00:00
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) loadIPAMDriver ( name string ) error {
2016-10-17 21:35:38 +00:00
var err error
if pg := c . GetPluginGetter ( ) ; pg != nil {
2017-01-10 21:17:15 +00:00
_ , err = pg . Get ( name , ipamapi . PluginEndpointType , plugingetter . Lookup )
2016-10-17 21:35:38 +00:00
} else {
_ , err = plugins . Get ( name , ipamapi . PluginEndpointType )
}
if err != nil {
2019-04-10 13:20:56 +00:00
if errors . Cause ( err ) == plugins . ErrNotFound {
2016-03-01 02:17:04 +00:00
return types . NotFoundErrorf ( err . Error ( ) )
2015-09-22 20:20:55 +00:00
}
2016-03-01 02:17:04 +00:00
return err
2015-09-18 19:54:08 +00:00
}
2015-09-22 20:20:55 +00:00
2016-03-01 02:17:04 +00:00
return nil
2015-09-22 20:20:55 +00:00
}
2023-01-11 22:43:32 +00:00
func ( c * Controller ) getIPAMDriver ( name string ) ( ipamapi . Ipam , * ipamapi . Capability , error ) {
2023-08-16 09:28:38 +00:00
id , caps := c . ipamRegistry . IPAM ( name )
2016-03-01 02:17:04 +00:00
if id == nil {
// Might be a plugin name. Try loading it
if err := c . loadIPAMDriver ( name ) ; err != nil {
return nil , nil , err
}
2015-09-18 19:54:08 +00:00
2016-03-01 02:17:04 +00:00
// Now that we resolved the plugin, try again looking up the registry
2023-08-16 09:28:38 +00:00
id , caps = c . ipamRegistry . IPAM ( name )
2016-03-01 02:17:04 +00:00
if id == nil {
2023-08-08 11:35:05 +00:00
return nil , nil , types . InvalidParameterErrorf ( "invalid ipam driver: %q" , name )
2016-03-01 02:17:04 +00:00
}
2016-02-16 23:19:18 +00:00
}
2023-08-16 09:28:38 +00:00
return id , caps , nil
2016-02-16 23:19:18 +00:00
}
2023-01-11 22:43:32 +00:00
// Stop stops the network controller.
func ( c * Controller ) Stop ( ) {
2015-10-05 11:21:15 +00:00
c . closeStores ( )
2015-09-09 21:24:05 +00:00
c . stopExternalKeyListener ( )
2015-07-02 05:00:48 +00:00
osl . GC ( )
2015-06-05 18:46:33 +00:00
}
2017-12-01 18:13:01 +00:00
2023-01-11 22:43:32 +00:00
// StartDiagnostic starts the network diagnostic server listening on port.
func ( c * Controller ) StartDiagnostic ( port int ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-12-06 19:21:51 +00:00
if ! c . DiagnosticServer . IsDiagnosticEnabled ( ) {
c . DiagnosticServer . EnableDiagnostic ( "127.0.0.1" , port )
2017-12-01 18:13:01 +00:00
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-12-01 18:13:01 +00:00
}
2023-01-11 22:43:32 +00:00
// StopDiagnostic stops the network diagnostic server.
func ( c * Controller ) StopDiagnostic ( ) {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
2017-12-06 19:21:51 +00:00
if c . DiagnosticServer . IsDiagnosticEnabled ( ) {
c . DiagnosticServer . DisableDiagnostic ( )
2017-12-01 18:13:01 +00:00
}
2023-01-11 20:56:50 +00:00
c . mu . Unlock ( )
2017-12-01 18:13:01 +00:00
}
2023-01-11 22:43:32 +00:00
// IsDiagnosticEnabled returns true if the diagnostic server is running.
func ( c * Controller ) IsDiagnosticEnabled ( ) bool {
2023-01-11 20:56:50 +00:00
c . mu . Lock ( )
defer c . mu . Unlock ( )
2017-12-06 19:21:51 +00:00
return c . DiagnosticServer . IsDiagnosticEnabled ( )
2017-12-01 18:13:01 +00:00
}