network.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. package daemon // import "github.com/docker/docker/daemon"
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "github.com/containerd/containerd/log"
  12. "github.com/docker/docker/api/types"
  13. containertypes "github.com/docker/docker/api/types/container"
  14. "github.com/docker/docker/api/types/filters"
  15. "github.com/docker/docker/api/types/network"
  16. "github.com/docker/docker/container"
  17. clustertypes "github.com/docker/docker/daemon/cluster/provider"
  18. "github.com/docker/docker/daemon/config"
  19. internalnetwork "github.com/docker/docker/daemon/network"
  20. "github.com/docker/docker/errdefs"
  21. "github.com/docker/docker/libnetwork"
  22. lncluster "github.com/docker/docker/libnetwork/cluster"
  23. "github.com/docker/docker/libnetwork/driverapi"
  24. "github.com/docker/docker/libnetwork/ipamapi"
  25. "github.com/docker/docker/libnetwork/netlabel"
  26. "github.com/docker/docker/libnetwork/networkdb"
  27. "github.com/docker/docker/libnetwork/options"
  28. networktypes "github.com/docker/docker/libnetwork/types"
  29. "github.com/docker/docker/opts"
  30. "github.com/docker/docker/pkg/plugingetter"
  31. "github.com/docker/docker/runconfig"
  32. "github.com/docker/go-connections/nat"
  33. )
  34. // PredefinedNetworkError is returned when user tries to create predefined network that already exists.
  35. type PredefinedNetworkError string
  36. func (pnr PredefinedNetworkError) Error() string {
  37. return fmt.Sprintf("operation is not permitted on predefined %s network ", string(pnr))
  38. }
  39. // Forbidden denotes the type of this error
  40. func (pnr PredefinedNetworkError) Forbidden() {}
  41. // NetworkControllerEnabled checks if the networking stack is enabled.
  42. // This feature depends on OS primitives and it's disabled in systems like Windows.
  43. func (daemon *Daemon) NetworkControllerEnabled() bool {
  44. return daemon.netController != nil
  45. }
  46. // NetworkController returns the network controller created by the daemon.
  47. func (daemon *Daemon) NetworkController() *libnetwork.Controller {
  48. return daemon.netController
  49. }
  50. // FindNetwork returns a network based on:
  51. // 1. Full ID
  52. // 2. Full Name
  53. // 3. Partial ID
  54. // as long as there is no ambiguity
  55. func (daemon *Daemon) FindNetwork(term string) (*libnetwork.Network, error) {
  56. var listByFullName, listByPartialID []*libnetwork.Network
  57. for _, nw := range daemon.getAllNetworks() {
  58. nwID := nw.ID()
  59. if nwID == term {
  60. return nw, nil
  61. }
  62. if strings.HasPrefix(nw.ID(), term) {
  63. listByPartialID = append(listByPartialID, nw)
  64. }
  65. if nw.Name() == term {
  66. listByFullName = append(listByFullName, nw)
  67. }
  68. }
  69. switch {
  70. case len(listByFullName) == 1:
  71. return listByFullName[0], nil
  72. case len(listByFullName) > 1:
  73. return nil, errdefs.InvalidParameter(fmt.Errorf("network %s is ambiguous (%d matches found on name)", term, len(listByFullName)))
  74. case len(listByPartialID) == 1:
  75. return listByPartialID[0], nil
  76. case len(listByPartialID) > 1:
  77. return nil, errdefs.InvalidParameter(fmt.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID)))
  78. }
  79. // Be very careful to change the error type here, the
  80. // libnetwork.ErrNoSuchNetwork error is used by the controller
  81. // to retry the creation of the network as managed through the swarm manager
  82. return nil, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term))
  83. }
  84. // GetNetworkByID function returns a network whose ID matches the given ID.
  85. // It fails with an error if no matching network is found.
  86. func (daemon *Daemon) GetNetworkByID(id string) (*libnetwork.Network, error) {
  87. c := daemon.netController
  88. if c == nil {
  89. return nil, fmt.Errorf("netcontroller is nil: %w", libnetwork.ErrNoSuchNetwork(id))
  90. }
  91. return c.NetworkByID(id)
  92. }
  93. // GetNetworkByName function returns a network for a given network name.
  94. // If no network name is given, the default network is returned.
  95. func (daemon *Daemon) GetNetworkByName(name string) (*libnetwork.Network, error) {
  96. c := daemon.netController
  97. if c == nil {
  98. return nil, libnetwork.ErrNoSuchNetwork(name)
  99. }
  100. if name == "" {
  101. name = c.Config().DefaultNetwork
  102. }
  103. return c.NetworkByName(name)
  104. }
  105. // GetNetworksByIDPrefix returns a list of networks whose ID partially matches zero or more networks
  106. func (daemon *Daemon) GetNetworksByIDPrefix(partialID string) []*libnetwork.Network {
  107. c := daemon.netController
  108. if c == nil {
  109. return nil
  110. }
  111. list := []*libnetwork.Network{}
  112. l := func(nw *libnetwork.Network) bool {
  113. if strings.HasPrefix(nw.ID(), partialID) {
  114. list = append(list, nw)
  115. }
  116. return false
  117. }
  118. c.WalkNetworks(l)
  119. return list
  120. }
  121. // getAllNetworks returns a list containing all networks
  122. func (daemon *Daemon) getAllNetworks() []*libnetwork.Network {
  123. c := daemon.netController
  124. if c == nil {
  125. return nil
  126. }
  127. return c.Networks()
  128. }
  129. type ingressJob struct {
  130. create *clustertypes.NetworkCreateRequest
  131. ip net.IP
  132. jobDone chan struct{}
  133. }
  134. var (
  135. ingressWorkerOnce sync.Once
  136. ingressJobsChannel chan *ingressJob
  137. ingressID string
  138. )
  139. func (daemon *Daemon) startIngressWorker() {
  140. ingressJobsChannel = make(chan *ingressJob, 100)
  141. go func() {
  142. //nolint: gosimple
  143. for {
  144. select {
  145. case r := <-ingressJobsChannel:
  146. if r.create != nil {
  147. daemon.setupIngress(&daemon.config().Config, r.create, r.ip, ingressID)
  148. ingressID = r.create.ID
  149. } else {
  150. daemon.releaseIngress(ingressID)
  151. ingressID = ""
  152. }
  153. close(r.jobDone)
  154. }
  155. }
  156. }()
  157. }
  158. // enqueueIngressJob adds a ingress add/rm request to the worker queue.
  159. // It guarantees the worker is started.
  160. func (daemon *Daemon) enqueueIngressJob(job *ingressJob) {
  161. ingressWorkerOnce.Do(daemon.startIngressWorker)
  162. ingressJobsChannel <- job
  163. }
  164. // SetupIngress setups ingress networking.
  165. // The function returns a channel which will signal the caller when the programming is completed.
  166. func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) (<-chan struct{}, error) {
  167. ip, _, err := net.ParseCIDR(nodeIP)
  168. if err != nil {
  169. return nil, err
  170. }
  171. done := make(chan struct{})
  172. daemon.enqueueIngressJob(&ingressJob{&create, ip, done})
  173. return done, nil
  174. }
  175. // ReleaseIngress releases the ingress networking.
  176. // The function returns a channel which will signal the caller when the programming is completed.
  177. func (daemon *Daemon) ReleaseIngress() (<-chan struct{}, error) {
  178. done := make(chan struct{})
  179. daemon.enqueueIngressJob(&ingressJob{nil, nil, done})
  180. return done, nil
  181. }
  182. func (daemon *Daemon) setupIngress(cfg *config.Config, create *clustertypes.NetworkCreateRequest, ip net.IP, staleID string) {
  183. controller := daemon.netController
  184. controller.AgentInitWait()
  185. if staleID != "" && staleID != create.ID {
  186. daemon.releaseIngress(staleID)
  187. }
  188. if _, err := daemon.createNetwork(cfg, create.NetworkCreateRequest, create.ID, true); err != nil {
  189. // If it is any other error other than already
  190. // exists error log error and return.
  191. if _, ok := err.(libnetwork.NetworkNameError); !ok {
  192. log.G(context.TODO()).Errorf("Failed creating ingress network: %v", err)
  193. return
  194. }
  195. // Otherwise continue down the call to create or recreate sandbox.
  196. }
  197. _, err := daemon.GetNetworkByID(create.ID)
  198. if err != nil {
  199. log.G(context.TODO()).Errorf("Failed getting ingress network by id after creating: %v", err)
  200. }
  201. }
  202. func (daemon *Daemon) releaseIngress(id string) {
  203. controller := daemon.netController
  204. if id == "" {
  205. return
  206. }
  207. n, err := controller.NetworkByID(id)
  208. if err != nil {
  209. log.G(context.TODO()).Errorf("failed to retrieve ingress network %s: %v", id, err)
  210. return
  211. }
  212. if err := n.Delete(libnetwork.NetworkDeleteOptionRemoveLB); err != nil {
  213. log.G(context.TODO()).Errorf("Failed to delete ingress network %s: %v", n.ID(), err)
  214. return
  215. }
  216. }
  217. // SetNetworkBootstrapKeys sets the bootstrap keys.
  218. func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
  219. err := daemon.netController.SetKeys(keys)
  220. if err == nil {
  221. // Upon successful key setting dispatch the keys available event
  222. daemon.cluster.SendClusterEvent(lncluster.EventNetworkKeysAvailable)
  223. }
  224. return err
  225. }
  226. // UpdateAttachment notifies the attacher about the attachment config.
  227. func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error {
  228. if daemon.clusterProvider == nil {
  229. return fmt.Errorf("cluster provider is not initialized")
  230. }
  231. if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil {
  232. return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config)
  233. }
  234. return nil
  235. }
  236. // WaitForDetachment makes the cluster manager wait for detachment of
  237. // the container from the network.
  238. func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
  239. if daemon.clusterProvider == nil {
  240. return fmt.Errorf("cluster provider is not initialized")
  241. }
  242. return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID)
  243. }
  244. // CreateManagedNetwork creates an agent network.
  245. func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
  246. _, err := daemon.createNetwork(&daemon.config().Config, create.NetworkCreateRequest, create.ID, true)
  247. return err
  248. }
  249. // CreateNetwork creates a network with the given name, driver and other optional parameters
  250. func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
  251. return daemon.createNetwork(&daemon.config().Config, create, "", false)
  252. }
  253. func (daemon *Daemon) createNetwork(cfg *config.Config, create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
  254. if runconfig.IsPreDefinedNetwork(create.Name) {
  255. return nil, PredefinedNetworkError(create.Name)
  256. }
  257. c := daemon.netController
  258. driver := create.Driver
  259. if driver == "" {
  260. driver = c.Config().DefaultDriver
  261. }
  262. if driver == "overlay" && !daemon.cluster.IsManager() && !agent {
  263. return nil, errdefs.Forbidden(errors.New(`This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.`))
  264. }
  265. var warning string
  266. nw, err := daemon.GetNetworkByName(create.Name)
  267. if err != nil {
  268. if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
  269. return nil, err
  270. }
  271. }
  272. if nw != nil {
  273. // check if user defined CheckDuplicate, if set true, return err
  274. // otherwise prepare a warning message
  275. if create.CheckDuplicate {
  276. if !agent || nw.Dynamic() {
  277. return nil, libnetwork.NetworkNameError(create.Name)
  278. }
  279. }
  280. warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
  281. }
  282. networkOptions := make(map[string]string)
  283. for k, v := range create.Options {
  284. networkOptions[k] = v
  285. }
  286. if defaultOpts, ok := cfg.DefaultNetworkOpts[driver]; create.ConfigFrom == nil && ok {
  287. for k, v := range defaultOpts {
  288. if _, ok := networkOptions[k]; !ok {
  289. log.G(context.TODO()).WithFields(log.Fields{"driver": driver, "network": id, k: v}).Debug("Applying network default option")
  290. networkOptions[k] = v
  291. }
  292. }
  293. }
  294. nwOptions := []libnetwork.NetworkOption{
  295. libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
  296. libnetwork.NetworkOptionDriverOpts(networkOptions),
  297. libnetwork.NetworkOptionLabels(create.Labels),
  298. libnetwork.NetworkOptionAttachable(create.Attachable),
  299. libnetwork.NetworkOptionIngress(create.Ingress),
  300. libnetwork.NetworkOptionScope(create.Scope),
  301. }
  302. if create.ConfigOnly {
  303. nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly())
  304. }
  305. if create.IPAM != nil {
  306. ipam := create.IPAM
  307. v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
  308. if err != nil {
  309. return nil, err
  310. }
  311. nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
  312. }
  313. if create.Internal {
  314. nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
  315. }
  316. if agent {
  317. nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
  318. nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
  319. }
  320. if create.ConfigFrom != nil {
  321. nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network))
  322. }
  323. if agent && driver == "overlay" {
  324. nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id)
  325. if !exists {
  326. return nil, fmt.Errorf("failed to find a load balancer IP to use for network: %v", id)
  327. }
  328. nwOptions = append(nwOptions, libnetwork.NetworkOptionLBEndpoint(nodeIP))
  329. }
  330. n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
  331. if err != nil {
  332. return nil, err
  333. }
  334. daemon.pluginRefCount(driver, driverapi.NetworkPluginEndpointType, plugingetter.Acquire)
  335. if create.IPAM != nil {
  336. daemon.pluginRefCount(create.IPAM.Driver, ipamapi.PluginEndpointType, plugingetter.Acquire)
  337. }
  338. daemon.LogNetworkEvent(n, "create")
  339. return &types.NetworkCreateResponse{
  340. ID: n.ID(),
  341. Warning: warning,
  342. }, nil
  343. }
  344. func (daemon *Daemon) pluginRefCount(driver, capability string, mode int) {
  345. var builtinDrivers []string
  346. if capability == driverapi.NetworkPluginEndpointType {
  347. builtinDrivers = daemon.netController.BuiltinDrivers()
  348. } else if capability == ipamapi.PluginEndpointType {
  349. builtinDrivers = daemon.netController.BuiltinIPAMDrivers()
  350. }
  351. for _, d := range builtinDrivers {
  352. if d == driver {
  353. return
  354. }
  355. }
  356. if daemon.PluginStore != nil {
  357. _, err := daemon.PluginStore.Get(driver, capability, mode)
  358. if err != nil {
  359. log.G(context.TODO()).WithError(err).WithFields(log.Fields{"mode": mode, "driver": driver}).Error("Error handling plugin refcount operation")
  360. }
  361. }
  362. }
  363. func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
  364. ipamV4Cfg := []*libnetwork.IpamConf{}
  365. ipamV6Cfg := []*libnetwork.IpamConf{}
  366. for _, d := range data {
  367. iCfg := libnetwork.IpamConf{}
  368. iCfg.PreferredPool = d.Subnet
  369. iCfg.SubPool = d.IPRange
  370. iCfg.Gateway = d.Gateway
  371. iCfg.AuxAddresses = d.AuxAddress
  372. ip, _, err := net.ParseCIDR(d.Subnet)
  373. if err != nil {
  374. return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
  375. }
  376. if ip.To4() != nil {
  377. ipamV4Cfg = append(ipamV4Cfg, &iCfg)
  378. } else {
  379. ipamV6Cfg = append(ipamV6Cfg, &iCfg)
  380. }
  381. }
  382. return ipamV4Cfg, ipamV6Cfg, nil
  383. }
  384. // UpdateContainerServiceConfig updates a service configuration.
  385. func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
  386. ctr, err := daemon.GetContainer(containerName)
  387. if err != nil {
  388. return err
  389. }
  390. ctr.NetworkSettings.Service = serviceConfig
  391. return nil
  392. }
  393. // ConnectContainerToNetwork connects the given container to the given
  394. // network. If either cannot be found, an err is returned. If the
  395. // network cannot be set up, an err is returned.
  396. func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
  397. ctr, err := daemon.GetContainer(containerName)
  398. if err != nil {
  399. return err
  400. }
  401. return daemon.ConnectToNetwork(ctr, networkName, endpointConfig)
  402. }
  403. // DisconnectContainerFromNetwork disconnects the given container from
  404. // the given network. If either cannot be found, an err is returned.
  405. func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
  406. ctr, err := daemon.GetContainer(containerName)
  407. if err != nil {
  408. if force {
  409. return daemon.ForceEndpointDelete(containerName, networkName)
  410. }
  411. return err
  412. }
  413. return daemon.DisconnectFromNetwork(ctr, networkName, force)
  414. }
  415. // GetNetworkDriverList returns the list of plugins drivers
  416. // registered for network.
  417. func (daemon *Daemon) GetNetworkDriverList() []string {
  418. if !daemon.NetworkControllerEnabled() {
  419. return nil
  420. }
  421. pluginList := daemon.netController.BuiltinDrivers()
  422. managedPlugins := daemon.PluginStore.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
  423. for _, plugin := range managedPlugins {
  424. pluginList = append(pluginList, plugin.Name())
  425. }
  426. pluginMap := make(map[string]bool)
  427. for _, plugin := range pluginList {
  428. pluginMap[plugin] = true
  429. }
  430. networks := daemon.netController.Networks()
  431. for _, nw := range networks {
  432. if !pluginMap[nw.Type()] {
  433. pluginList = append(pluginList, nw.Type())
  434. pluginMap[nw.Type()] = true
  435. }
  436. }
  437. sort.Strings(pluginList)
  438. return pluginList
  439. }
  440. // DeleteManagedNetwork deletes an agent network.
  441. // The requirement of networkID is enforced.
  442. func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
  443. n, err := daemon.GetNetworkByID(networkID)
  444. if err != nil {
  445. return err
  446. }
  447. return daemon.deleteNetwork(n, true)
  448. }
  449. // DeleteNetwork destroys a network unless it's one of docker's predefined networks.
  450. func (daemon *Daemon) DeleteNetwork(networkID string) error {
  451. n, err := daemon.GetNetworkByID(networkID)
  452. if err != nil {
  453. return fmt.Errorf("could not find network by ID: %w", err)
  454. }
  455. return daemon.deleteNetwork(n, false)
  456. }
  457. func (daemon *Daemon) deleteNetwork(nw *libnetwork.Network, dynamic bool) error {
  458. if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
  459. err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
  460. return errdefs.Forbidden(err)
  461. }
  462. if dynamic && !nw.Dynamic() {
  463. if runconfig.IsPreDefinedNetwork(nw.Name()) {
  464. // Predefined networks now support swarm services. Make this
  465. // a no-op when cluster requests to remove the predefined network.
  466. return nil
  467. }
  468. err := fmt.Errorf("%s is not a dynamic network", nw.Name())
  469. return errdefs.Forbidden(err)
  470. }
  471. if err := nw.Delete(); err != nil {
  472. return fmt.Errorf("error while removing network: %w", err)
  473. }
  474. // If this is not a configuration only network, we need to
  475. // update the corresponding remote drivers' reference counts
  476. if !nw.ConfigOnly() {
  477. daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release)
  478. ipamType, _, _, _ := nw.IpamConfig()
  479. daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release)
  480. daemon.LogNetworkEvent(nw, "destroy")
  481. }
  482. return nil
  483. }
  484. // GetNetworks returns a list of all networks
  485. func (daemon *Daemon) GetNetworks(filter filters.Args, config types.NetworkListConfig) (networks []types.NetworkResource, err error) {
  486. var idx map[string]*libnetwork.Network
  487. if config.Detailed {
  488. idx = make(map[string]*libnetwork.Network)
  489. }
  490. allNetworks := daemon.getAllNetworks()
  491. networks = make([]types.NetworkResource, 0, len(allNetworks))
  492. for _, n := range allNetworks {
  493. nr := buildNetworkResource(n)
  494. networks = append(networks, nr)
  495. if config.Detailed {
  496. idx[nr.ID] = n
  497. }
  498. }
  499. networks, err = internalnetwork.FilterNetworks(networks, filter)
  500. if err != nil {
  501. return nil, err
  502. }
  503. if config.Detailed {
  504. for i, nw := range networks {
  505. networks[i].Containers = buildContainerAttachments(idx[nw.ID])
  506. if config.Verbose {
  507. networks[i].Services = buildServiceAttachments(idx[nw.ID])
  508. }
  509. }
  510. }
  511. return networks, nil
  512. }
  513. // buildNetworkResource builds a [types.NetworkResource] from the given
  514. // [libnetwork.Network], to be returned by the API.
  515. func buildNetworkResource(nw *libnetwork.Network) types.NetworkResource {
  516. if nw == nil {
  517. return types.NetworkResource{}
  518. }
  519. return types.NetworkResource{
  520. Name: nw.Name(),
  521. ID: nw.ID(),
  522. Created: nw.Created(),
  523. Scope: nw.Scope(),
  524. Driver: nw.Type(),
  525. EnableIPv6: nw.IPv6Enabled(),
  526. IPAM: buildIPAMResources(nw),
  527. Internal: nw.Internal(),
  528. Attachable: nw.Attachable(),
  529. Ingress: nw.Ingress(),
  530. ConfigFrom: network.ConfigReference{Network: nw.ConfigFrom()},
  531. ConfigOnly: nw.ConfigOnly(),
  532. Containers: map[string]types.EndpointResource{},
  533. Options: nw.DriverOptions(),
  534. Labels: nw.Labels(),
  535. Peers: buildPeerInfoResources(nw.Peers()),
  536. }
  537. }
  538. // buildContainerAttachments creates a [types.EndpointResource] map of all
  539. // containers attached to the network. It is used when listing networks in
  540. // detailed mode.
  541. func buildContainerAttachments(nw *libnetwork.Network) map[string]types.EndpointResource {
  542. containers := make(map[string]types.EndpointResource)
  543. for _, e := range nw.Endpoints() {
  544. ei := e.Info()
  545. if ei == nil {
  546. continue
  547. }
  548. if sb := ei.Sandbox(); sb != nil {
  549. containers[sb.ContainerID()] = buildEndpointResource(e, ei)
  550. } else {
  551. containers["ep-"+e.ID()] = buildEndpointResource(e, ei)
  552. }
  553. }
  554. return containers
  555. }
  556. // buildServiceAttachments creates a [network.ServiceInfo] map of all services
  557. // attached to the network. It is used when listing networks in "verbose" mode.
  558. func buildServiceAttachments(nw *libnetwork.Network) map[string]network.ServiceInfo {
  559. services := make(map[string]network.ServiceInfo)
  560. for name, service := range nw.Services() {
  561. tasks := make([]network.Task, 0, len(service.Tasks))
  562. for _, t := range service.Tasks {
  563. tasks = append(tasks, network.Task{
  564. Name: t.Name,
  565. EndpointID: t.EndpointID,
  566. EndpointIP: t.EndpointIP,
  567. Info: t.Info,
  568. })
  569. }
  570. services[name] = network.ServiceInfo{
  571. VIP: service.VIP,
  572. Ports: service.Ports,
  573. Tasks: tasks,
  574. LocalLBIndex: service.LocalLBIndex,
  575. }
  576. }
  577. return services
  578. }
  579. // buildPeerInfoResources converts a list of [networkdb.PeerInfo] to a
  580. // [network.PeerInfo] for inclusion in API responses. It returns nil if
  581. // the list of peers is empty.
  582. func buildPeerInfoResources(peers []networkdb.PeerInfo) []network.PeerInfo {
  583. if len(peers) == 0 {
  584. return nil
  585. }
  586. peerInfo := make([]network.PeerInfo, 0, len(peers))
  587. for _, peer := range peers {
  588. peerInfo = append(peerInfo, network.PeerInfo(peer))
  589. }
  590. return peerInfo
  591. }
  592. // buildIPAMResources constructs a [network.IPAM] from the network's
  593. // IPAM information for inclusion in API responses.
  594. func buildIPAMResources(nw *libnetwork.Network) network.IPAM {
  595. var ipamConfig []network.IPAMConfig
  596. ipamDriver, ipamOptions, ipv4Conf, ipv6Conf := nw.IpamConfig()
  597. hasIPv4Config := false
  598. for _, cfg := range ipv4Conf {
  599. if cfg.PreferredPool == "" {
  600. continue
  601. }
  602. hasIPv4Config = true
  603. ipamConfig = append(ipamConfig, network.IPAMConfig{
  604. Subnet: cfg.PreferredPool,
  605. IPRange: cfg.SubPool,
  606. Gateway: cfg.Gateway,
  607. AuxAddress: cfg.AuxAddresses,
  608. })
  609. }
  610. hasIPv6Config := false
  611. for _, cfg := range ipv6Conf {
  612. if cfg.PreferredPool == "" {
  613. continue
  614. }
  615. hasIPv6Config = true
  616. ipamConfig = append(ipamConfig, network.IPAMConfig{
  617. Subnet: cfg.PreferredPool,
  618. IPRange: cfg.SubPool,
  619. Gateway: cfg.Gateway,
  620. AuxAddress: cfg.AuxAddresses,
  621. })
  622. }
  623. if !hasIPv4Config || !hasIPv6Config {
  624. ipv4Info, ipv6Info := nw.IpamInfo()
  625. if !hasIPv4Config {
  626. for _, info := range ipv4Info {
  627. var gw string
  628. if info.IPAMData.Gateway != nil {
  629. gw = info.IPAMData.Gateway.IP.String()
  630. }
  631. ipamConfig = append(ipamConfig, network.IPAMConfig{
  632. Subnet: info.IPAMData.Pool.String(),
  633. Gateway: gw,
  634. })
  635. }
  636. }
  637. if !hasIPv6Config {
  638. for _, info := range ipv6Info {
  639. if info.IPAMData.Pool == nil {
  640. continue
  641. }
  642. ipamConfig = append(ipamConfig, network.IPAMConfig{
  643. Subnet: info.IPAMData.Pool.String(),
  644. Gateway: info.IPAMData.Gateway.String(),
  645. })
  646. }
  647. }
  648. }
  649. return network.IPAM{
  650. Driver: ipamDriver,
  651. Options: ipamOptions,
  652. Config: ipamConfig,
  653. }
  654. }
  655. // buildEndpointResource combines information from the endpoint and additional
  656. // endpoint-info into a [types.EndpointResource].
  657. func buildEndpointResource(ep *libnetwork.Endpoint, info libnetwork.EndpointInfo) types.EndpointResource {
  658. er := types.EndpointResource{
  659. EndpointID: ep.ID(),
  660. Name: ep.Name(),
  661. }
  662. if iface := info.Iface(); iface != nil {
  663. if mac := iface.MacAddress(); mac != nil {
  664. er.MacAddress = mac.String()
  665. }
  666. if ip := iface.Address(); ip != nil && len(ip.IP) > 0 {
  667. er.IPv4Address = ip.String()
  668. }
  669. if ip := iface.AddressIPv6(); ip != nil && len(ip.IP) > 0 {
  670. er.IPv6Address = ip.String()
  671. }
  672. }
  673. return er
  674. }
  675. // clearAttachableNetworks removes the attachable networks
  676. // after disconnecting any connected container
  677. func (daemon *Daemon) clearAttachableNetworks() {
  678. for _, n := range daemon.getAllNetworks() {
  679. if !n.Attachable() {
  680. continue
  681. }
  682. for _, ep := range n.Endpoints() {
  683. epInfo := ep.Info()
  684. if epInfo == nil {
  685. continue
  686. }
  687. sb := epInfo.Sandbox()
  688. if sb == nil {
  689. continue
  690. }
  691. containerID := sb.ContainerID()
  692. if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil {
  693. log.G(context.TODO()).Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v",
  694. containerID, n.Name(), err)
  695. }
  696. }
  697. if err := daemon.DeleteManagedNetwork(n.ID()); err != nil {
  698. log.G(context.TODO()).Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err)
  699. }
  700. }
  701. }
  702. // buildCreateEndpointOptions builds endpoint options from a given network.
  703. func buildCreateEndpointOptions(c *container.Container, n *libnetwork.Network, epConfig *network.EndpointSettings, sb *libnetwork.Sandbox, daemonDNS []string) ([]libnetwork.EndpointOption, error) {
  704. var createOptions []libnetwork.EndpointOption
  705. nwName := n.Name()
  706. defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
  707. if c.NetworkSettings.IsAnonymousEndpoint || (nwName == defaultNetName && !serviceDiscoveryOnDefaultNetwork()) {
  708. createOptions = append(createOptions, libnetwork.CreateOptionAnonymous())
  709. }
  710. if epConfig != nil {
  711. if ipam := epConfig.IPAMConfig; ipam != nil {
  712. var ipList []net.IP
  713. for _, ips := range ipam.LinkLocalIPs {
  714. linkIP := net.ParseIP(ips)
  715. if linkIP == nil && ips != "" {
  716. return nil, fmt.Errorf("invalid link-local IP address: %s", ipam.LinkLocalIPs)
  717. }
  718. ipList = append(ipList, linkIP)
  719. }
  720. ip := net.ParseIP(ipam.IPv4Address)
  721. if ip == nil && ipam.IPv4Address != "" {
  722. return nil, fmt.Errorf("invalid IPv4 address: %s", ipam.IPv4Address)
  723. }
  724. ip6 := net.ParseIP(ipam.IPv6Address)
  725. if ip6 == nil && ipam.IPv6Address != "" {
  726. return nil, fmt.Errorf("invalid IPv6 address: %s", ipam.IPv6Address)
  727. }
  728. createOptions = append(createOptions, libnetwork.CreateOptionIpam(ip, ip6, ipList, nil))
  729. }
  730. for _, alias := range epConfig.Aliases {
  731. createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias))
  732. }
  733. for k, v := range epConfig.DriverOpts {
  734. createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v}))
  735. }
  736. }
  737. if svcCfg := c.NetworkSettings.Service; svcCfg != nil {
  738. nwID := n.ID()
  739. var vip net.IP
  740. if virtualAddress := svcCfg.VirtualAddresses[nwID]; virtualAddress != nil {
  741. vip = net.ParseIP(virtualAddress.IPv4)
  742. }
  743. var portConfigs []*libnetwork.PortConfig
  744. for _, portConfig := range svcCfg.ExposedPorts {
  745. portConfigs = append(portConfigs, &libnetwork.PortConfig{
  746. Name: portConfig.Name,
  747. Protocol: libnetwork.PortConfig_Protocol(portConfig.Protocol),
  748. TargetPort: portConfig.TargetPort,
  749. PublishedPort: portConfig.PublishedPort,
  750. })
  751. }
  752. createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, vip, portConfigs, svcCfg.Aliases[nwID]))
  753. }
  754. if !containertypes.NetworkMode(nwName).IsUserDefined() {
  755. createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution())
  756. }
  757. // configs that are applicable only for the endpoint in the network
  758. // to which container was connected to on docker run.
  759. // Ideally all these network-specific endpoint configurations must be moved under
  760. // container.NetworkSettings.Networks[n.Name()]
  761. if nwName == c.HostConfig.NetworkMode.NetworkName() || (nwName == defaultNetName && c.HostConfig.NetworkMode.IsDefault()) {
  762. if c.Config.MacAddress != "" {
  763. mac, err := net.ParseMAC(c.Config.MacAddress)
  764. if err != nil {
  765. return nil, err
  766. }
  767. createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(options.Generic{
  768. netlabel.MacAddress: mac,
  769. }))
  770. }
  771. }
  772. // Port-mapping rules belong to the container & applicable only to non-internal networks.
  773. //
  774. // TODO(thaJeztah): Look if we can provide a more minimal function for getPortMapInfo, as it does a lot, and we only need the "length".
  775. if n.Internal() || len(getPortMapInfo(sb)) > 0 {
  776. return createOptions, nil
  777. }
  778. bindings := make(nat.PortMap)
  779. if c.HostConfig.PortBindings != nil {
  780. for p, b := range c.HostConfig.PortBindings {
  781. bindings[p] = []nat.PortBinding{}
  782. for _, bb := range b {
  783. bindings[p] = append(bindings[p], nat.PortBinding{
  784. HostIP: bb.HostIP,
  785. HostPort: bb.HostPort,
  786. })
  787. }
  788. }
  789. }
  790. // TODO(thaJeztah): Move this code to a method on nat.PortSet.
  791. ports := make([]nat.Port, 0, len(c.Config.ExposedPorts))
  792. for p := range c.Config.ExposedPorts {
  793. ports = append(ports, p)
  794. }
  795. nat.SortPortMap(ports, bindings)
  796. var (
  797. exposedPorts []networktypes.TransportPort
  798. publishedPorts []networktypes.PortBinding
  799. )
  800. for _, port := range ports {
  801. portProto := networktypes.ParseProtocol(port.Proto())
  802. portNum := uint16(port.Int())
  803. exposedPorts = append(exposedPorts, networktypes.TransportPort{
  804. Proto: portProto,
  805. Port: portNum,
  806. })
  807. for _, binding := range bindings[port] {
  808. newP, err := nat.NewPort(nat.SplitProtoPort(binding.HostPort))
  809. var portStart, portEnd int
  810. if err == nil {
  811. portStart, portEnd, err = newP.Range()
  812. }
  813. if err != nil {
  814. return nil, fmt.Errorf("error parsing HostPort value (%s): %w", binding.HostPort, err)
  815. }
  816. publishedPorts = append(publishedPorts, networktypes.PortBinding{
  817. Proto: portProto,
  818. Port: portNum,
  819. HostIP: net.ParseIP(binding.HostIP),
  820. HostPort: uint16(portStart),
  821. HostPortEnd: uint16(portEnd),
  822. })
  823. }
  824. if c.HostConfig.PublishAllPorts && len(bindings[port]) == 0 {
  825. publishedPorts = append(publishedPorts, networktypes.PortBinding{
  826. Proto: portProto,
  827. Port: portNum,
  828. })
  829. }
  830. }
  831. if len(c.HostConfig.DNS) > 0 {
  832. createOptions = append(createOptions, libnetwork.CreateOptionDNS(c.HostConfig.DNS))
  833. } else if len(daemonDNS) > 0 {
  834. createOptions = append(createOptions, libnetwork.CreateOptionDNS(daemonDNS))
  835. }
  836. createOptions = append(createOptions, libnetwork.CreateOptionPortMapping(publishedPorts), libnetwork.CreateOptionExposedPorts(exposedPorts))
  837. return createOptions, nil
  838. }
  839. // getPortMapInfo retrieves the current port-mapping programmed for the given sandbox
  840. func getPortMapInfo(sb *libnetwork.Sandbox) nat.PortMap {
  841. pm := nat.PortMap{}
  842. if sb == nil {
  843. return pm
  844. }
  845. for _, ep := range sb.Endpoints() {
  846. pm, _ = getEndpointPortMapInfo(ep)
  847. if len(pm) > 0 {
  848. break
  849. }
  850. }
  851. return pm
  852. }
  853. func getEndpointPortMapInfo(ep *libnetwork.Endpoint) (nat.PortMap, error) {
  854. pm := nat.PortMap{}
  855. driverInfo, err := ep.DriverInfo()
  856. if err != nil {
  857. return pm, err
  858. }
  859. if driverInfo == nil {
  860. // It is not an error for epInfo to be nil
  861. return pm, nil
  862. }
  863. if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
  864. if exposedPorts, ok := expData.([]networktypes.TransportPort); ok {
  865. for _, tp := range exposedPorts {
  866. natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
  867. if err != nil {
  868. return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err)
  869. }
  870. pm[natPort] = nil
  871. }
  872. }
  873. }
  874. mapData, ok := driverInfo[netlabel.PortMap]
  875. if !ok {
  876. return pm, nil
  877. }
  878. if portMapping, ok := mapData.([]networktypes.PortBinding); ok {
  879. for _, pp := range portMapping {
  880. natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
  881. if err != nil {
  882. return pm, err
  883. }
  884. natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
  885. pm[natPort] = append(pm[natPort], natBndg)
  886. }
  887. }
  888. return pm, nil
  889. }
  890. // buildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint.
  891. func buildEndpointInfo(networkSettings *internalnetwork.Settings, n *libnetwork.Network, ep *libnetwork.Endpoint) error {
  892. if ep == nil {
  893. return errors.New("endpoint cannot be nil")
  894. }
  895. if networkSettings == nil {
  896. return errors.New("network cannot be nil")
  897. }
  898. epInfo := ep.Info()
  899. if epInfo == nil {
  900. // It is not an error to get an empty endpoint info
  901. return nil
  902. }
  903. nwName := n.Name()
  904. if _, ok := networkSettings.Networks[nwName]; !ok {
  905. networkSettings.Networks[nwName] = &internalnetwork.EndpointSettings{
  906. EndpointSettings: &network.EndpointSettings{},
  907. }
  908. }
  909. networkSettings.Networks[nwName].NetworkID = n.ID()
  910. networkSettings.Networks[nwName].EndpointID = ep.ID()
  911. iface := epInfo.Iface()
  912. if iface == nil {
  913. return nil
  914. }
  915. if iface.MacAddress() != nil {
  916. networkSettings.Networks[nwName].MacAddress = iface.MacAddress().String()
  917. }
  918. if iface.Address() != nil {
  919. ones, _ := iface.Address().Mask.Size()
  920. networkSettings.Networks[nwName].IPAddress = iface.Address().IP.String()
  921. networkSettings.Networks[nwName].IPPrefixLen = ones
  922. }
  923. if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil {
  924. onesv6, _ := iface.AddressIPv6().Mask.Size()
  925. networkSettings.Networks[nwName].GlobalIPv6Address = iface.AddressIPv6().IP.String()
  926. networkSettings.Networks[nwName].GlobalIPv6PrefixLen = onesv6
  927. }
  928. return nil
  929. }
  930. // buildJoinOptions builds endpoint Join options from a given network.
  931. func buildJoinOptions(networkSettings *internalnetwork.Settings, n interface{ Name() string }) ([]libnetwork.EndpointOption, error) {
  932. var joinOptions []libnetwork.EndpointOption
  933. if epConfig, ok := networkSettings.Networks[n.Name()]; ok {
  934. for _, str := range epConfig.Links {
  935. name, alias, err := opts.ParseLink(str)
  936. if err != nil {
  937. return nil, err
  938. }
  939. joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias))
  940. }
  941. for k, v := range epConfig.DriverOpts {
  942. joinOptions = append(joinOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v}))
  943. }
  944. }
  945. return joinOptions, nil
  946. }