endpoint.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. package libnetwork
  2. import (
  3. "container/heap"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "strings"
  8. "sync"
  9. log "github.com/Sirupsen/logrus"
  10. "github.com/docker/libnetwork/datastore"
  11. "github.com/docker/libnetwork/ipamapi"
  12. "github.com/docker/libnetwork/netlabel"
  13. "github.com/docker/libnetwork/options"
  14. "github.com/docker/libnetwork/types"
  15. )
  16. // Endpoint represents a logical connection between a network and a sandbox.
  17. type Endpoint interface {
  18. // A system generated id for this endpoint.
  19. ID() string
  20. // Name returns the name of this endpoint.
  21. Name() string
  22. // Network returns the name of the network to which this endpoint is attached.
  23. Network() string
  24. // Join joins the sandbox to the endpoint and populates into the sandbox
  25. // the network resources allocated for the endpoint.
  26. Join(sandbox Sandbox, options ...EndpointOption) error
  27. // Leave detaches the network resources populated in the sandbox.
  28. Leave(sandbox Sandbox, options ...EndpointOption) error
  29. // Return certain operational data belonging to this endpoint
  30. Info() EndpointInfo
  31. // DriverInfo returns a collection of driver operational data related to this endpoint retrieved from the driver
  32. DriverInfo() (map[string]interface{}, error)
  33. // Delete and detaches this endpoint from the network.
  34. Delete() error
  35. }
  36. // EndpointOption is a option setter function type used to pass varios options to Network
  37. // and Endpoint interfaces methods. The various setter functions of type EndpointOption are
  38. // provided by libnetwork, they look like <Create|Join|Leave>Option[...](...)
  39. type EndpointOption func(ep *endpoint)
  40. type endpoint struct {
  41. name string
  42. id string
  43. network *network
  44. iface *endpointInterface
  45. joinInfo *endpointJoinInfo
  46. sandboxID string
  47. exposedPorts []types.TransportPort
  48. generic map[string]interface{}
  49. joinLeaveDone chan struct{}
  50. dbIndex uint64
  51. dbExists bool
  52. sync.Mutex
  53. }
  54. func (ep *endpoint) MarshalJSON() ([]byte, error) {
  55. ep.Lock()
  56. defer ep.Unlock()
  57. epMap := make(map[string]interface{})
  58. epMap["name"] = ep.name
  59. epMap["id"] = ep.id
  60. epMap["ep_iface"] = ep.iface
  61. epMap["exposed_ports"] = ep.exposedPorts
  62. if ep.generic != nil {
  63. epMap["generic"] = ep.generic
  64. }
  65. epMap["sandbox"] = ep.sandboxID
  66. return json.Marshal(epMap)
  67. }
  68. func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
  69. ep.Lock()
  70. defer ep.Unlock()
  71. var epMap map[string]interface{}
  72. if err := json.Unmarshal(b, &epMap); err != nil {
  73. return err
  74. }
  75. ep.name = epMap["name"].(string)
  76. ep.id = epMap["id"].(string)
  77. ib, _ := json.Marshal(epMap["ep_iface"])
  78. json.Unmarshal(ib, &ep.iface)
  79. tb, _ := json.Marshal(epMap["exposed_ports"])
  80. var tPorts []types.TransportPort
  81. json.Unmarshal(tb, &tPorts)
  82. ep.exposedPorts = tPorts
  83. cb, _ := json.Marshal(epMap["sandbox"])
  84. json.Unmarshal(cb, &ep.sandboxID)
  85. if v, ok := epMap["generic"]; ok {
  86. ep.generic = v.(map[string]interface{})
  87. }
  88. return nil
  89. }
  90. func (ep *endpoint) New() datastore.KVObject {
  91. return &endpoint{network: ep.getNetwork()}
  92. }
  93. func (ep *endpoint) CopyTo(o datastore.KVObject) error {
  94. ep.Lock()
  95. defer ep.Unlock()
  96. dstEp := o.(*endpoint)
  97. dstEp.name = ep.name
  98. dstEp.id = ep.id
  99. dstEp.sandboxID = ep.sandboxID
  100. dstEp.dbIndex = ep.dbIndex
  101. dstEp.dbExists = ep.dbExists
  102. if ep.iface != nil {
  103. dstEp.iface = &endpointInterface{}
  104. ep.iface.CopyTo(dstEp.iface)
  105. }
  106. dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
  107. copy(dstEp.exposedPorts, ep.exposedPorts)
  108. dstEp.generic = options.Generic{}
  109. for k, v := range ep.generic {
  110. dstEp.generic[k] = v
  111. }
  112. return nil
  113. }
  114. func (ep *endpoint) ID() string {
  115. ep.Lock()
  116. defer ep.Unlock()
  117. return ep.id
  118. }
  119. func (ep *endpoint) Name() string {
  120. ep.Lock()
  121. defer ep.Unlock()
  122. return ep.name
  123. }
  124. func (ep *endpoint) Network() string {
  125. if ep.network == nil {
  126. return ""
  127. }
  128. return ep.network.name
  129. }
  130. // endpoint Key structure : endpoint/network-id/endpoint-id
  131. func (ep *endpoint) Key() []string {
  132. if ep.network == nil {
  133. return nil
  134. }
  135. return []string{datastore.EndpointKeyPrefix, ep.network.id, ep.id}
  136. }
  137. func (ep *endpoint) KeyPrefix() []string {
  138. if ep.network == nil {
  139. return nil
  140. }
  141. return []string{datastore.EndpointKeyPrefix, ep.network.id}
  142. }
  143. func (ep *endpoint) networkIDFromKey(key string) (string, error) {
  144. // endpoint Key structure : docker/libnetwork/endpoint/${network-id}/${endpoint-id}
  145. // it's an invalid key if the key doesn't have all the 5 key elements above
  146. keyElements := strings.Split(key, "/")
  147. if !strings.HasPrefix(key, datastore.Key(datastore.EndpointKeyPrefix)) || len(keyElements) < 5 {
  148. return "", fmt.Errorf("invalid endpoint key : %v", key)
  149. }
  150. // network-id is placed at index=3. pls refer to endpoint.Key() method
  151. return strings.Split(key, "/")[3], nil
  152. }
  153. func (ep *endpoint) Value() []byte {
  154. b, err := json.Marshal(ep)
  155. if err != nil {
  156. return nil
  157. }
  158. return b
  159. }
  160. func (ep *endpoint) SetValue(value []byte) error {
  161. return json.Unmarshal(value, ep)
  162. }
  163. func (ep *endpoint) Index() uint64 {
  164. ep.Lock()
  165. defer ep.Unlock()
  166. return ep.dbIndex
  167. }
  168. func (ep *endpoint) SetIndex(index uint64) {
  169. ep.Lock()
  170. defer ep.Unlock()
  171. ep.dbIndex = index
  172. ep.dbExists = true
  173. }
  174. func (ep *endpoint) Exists() bool {
  175. ep.Lock()
  176. defer ep.Unlock()
  177. return ep.dbExists
  178. }
  179. func (ep *endpoint) Skip() bool {
  180. return ep.getNetwork().Skip()
  181. }
  182. func (ep *endpoint) processOptions(options ...EndpointOption) {
  183. ep.Lock()
  184. defer ep.Unlock()
  185. for _, opt := range options {
  186. if opt != nil {
  187. opt(ep)
  188. }
  189. }
  190. }
  191. func (ep *endpoint) getNetwork() *network {
  192. ep.Lock()
  193. defer ep.Unlock()
  194. return ep.network
  195. }
  196. func (ep *endpoint) getNetworkFromStore() (*network, error) {
  197. if ep.network == nil {
  198. return nil, fmt.Errorf("invalid network object in endpoint %s", ep.Name())
  199. }
  200. return ep.network.ctrlr.getNetworkFromStore(ep.network.id)
  201. }
  202. func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
  203. if sbox == nil {
  204. return types.BadRequestErrorf("endpoint cannot be joined by nil container")
  205. }
  206. sb, ok := sbox.(*sandbox)
  207. if !ok {
  208. return types.BadRequestErrorf("not a valid Sandbox interface")
  209. }
  210. sb.joinLeaveStart()
  211. defer sb.joinLeaveEnd()
  212. return ep.sbJoin(sbox, options...)
  213. }
  214. func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
  215. var err error
  216. sb, ok := sbox.(*sandbox)
  217. if !ok {
  218. return types.BadRequestErrorf("not a valid Sandbox interface")
  219. }
  220. network, err := ep.getNetworkFromStore()
  221. if err != nil {
  222. return fmt.Errorf("failed to get network from store during join: %v", err)
  223. }
  224. ep, err = network.getEndpointFromStore(ep.ID())
  225. if err != nil {
  226. return fmt.Errorf("failed to get endpoint from store during join: %v", err)
  227. }
  228. ep.Lock()
  229. if ep.sandboxID != "" {
  230. ep.Unlock()
  231. return types.ForbiddenErrorf("another container is attached to the same network endpoint")
  232. }
  233. ep.Unlock()
  234. ep.Lock()
  235. ep.network = network
  236. ep.sandboxID = sbox.ID()
  237. ep.joinInfo = &endpointJoinInfo{}
  238. epid := ep.id
  239. ep.Unlock()
  240. defer func() {
  241. if err != nil {
  242. ep.Lock()
  243. ep.sandboxID = ""
  244. ep.Unlock()
  245. }
  246. }()
  247. network.Lock()
  248. nid := network.id
  249. network.Unlock()
  250. ep.processOptions(options...)
  251. driver, err := network.driver()
  252. if err != nil {
  253. return fmt.Errorf("failed to join endpoint: %v", err)
  254. }
  255. err = driver.Join(nid, epid, sbox.Key(), ep, sbox.Labels())
  256. if err != nil {
  257. return err
  258. }
  259. defer func() {
  260. if err != nil {
  261. // Do not alter global err variable, it's needed by the previous defer
  262. if err := driver.Leave(nid, epid); err != nil {
  263. log.Warnf("driver leave failed while rolling back join: %v", err)
  264. }
  265. }
  266. }()
  267. address := ""
  268. if ip := ep.getFirstInterfaceAddress(); ip != nil {
  269. address = ip.String()
  270. }
  271. if err = sb.updateHostsFile(address, network.getSvcRecords()); err != nil {
  272. return err
  273. }
  274. // Watch for service records
  275. network.getController().watchSvcRecord(ep)
  276. if err = sb.updateDNS(network.enableIPv6); err != nil {
  277. return err
  278. }
  279. if err = network.getController().updateToStore(ep); err != nil {
  280. return err
  281. }
  282. sb.Lock()
  283. heap.Push(&sb.endpoints, ep)
  284. sb.Unlock()
  285. defer func() {
  286. if err != nil {
  287. for i, e := range sb.getConnectedEndpoints() {
  288. if e == ep {
  289. sb.Lock()
  290. heap.Remove(&sb.endpoints, i)
  291. sb.Unlock()
  292. return
  293. }
  294. }
  295. }
  296. }()
  297. if err = sb.populateNetworkResources(ep); err != nil {
  298. return err
  299. }
  300. if sb.needDefaultGW() {
  301. return sb.setupDefaultGW(ep)
  302. }
  303. return sb.clearDefaultGW()
  304. }
  305. func (ep *endpoint) hasInterface(iName string) bool {
  306. ep.Lock()
  307. defer ep.Unlock()
  308. return ep.iface != nil && ep.iface.srcName == iName
  309. }
  310. func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error {
  311. if sbox == nil || sbox.ID() == "" || sbox.Key() == "" {
  312. return types.BadRequestErrorf("invalid Sandbox passed to enpoint leave: %v", sbox)
  313. }
  314. sb, ok := sbox.(*sandbox)
  315. if !ok {
  316. return types.BadRequestErrorf("not a valid Sandbox interface")
  317. }
  318. sb.joinLeaveStart()
  319. defer sb.joinLeaveEnd()
  320. return ep.sbLeave(sbox, options...)
  321. }
  322. func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
  323. sb, ok := sbox.(*sandbox)
  324. if !ok {
  325. return types.BadRequestErrorf("not a valid Sandbox interface")
  326. }
  327. n, err := ep.getNetworkFromStore()
  328. if err != nil {
  329. return fmt.Errorf("failed to get network from store during leave: %v", err)
  330. }
  331. ep, err = n.getEndpointFromStore(ep.ID())
  332. if err != nil {
  333. return fmt.Errorf("failed to get endpoint from store during leave: %v", err)
  334. }
  335. ep.Lock()
  336. sid := ep.sandboxID
  337. ep.Unlock()
  338. if sid == "" {
  339. return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
  340. }
  341. if sid != sbox.ID() {
  342. return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sbox.ID())
  343. }
  344. ep.processOptions(options...)
  345. ep.Lock()
  346. ep.sandboxID = ""
  347. ep.network = n
  348. ep.Unlock()
  349. if err := n.getController().updateToStore(ep); err != nil {
  350. ep.Lock()
  351. ep.sandboxID = sid
  352. ep.Unlock()
  353. return err
  354. }
  355. d, err := n.driver()
  356. if err != nil {
  357. return fmt.Errorf("failed to leave endpoint: %v", err)
  358. }
  359. if err := d.Leave(n.id, ep.id); err != nil {
  360. return err
  361. }
  362. if err := sb.clearNetworkResources(ep); err != nil {
  363. return err
  364. }
  365. // unwatch for service records
  366. n.getController().unWatchSvcRecord(ep)
  367. if sb.needDefaultGW() {
  368. ep := sb.getEPwithoutGateway()
  369. if ep == nil {
  370. return fmt.Errorf("endpoint without GW expected, but not found")
  371. }
  372. return sb.setupDefaultGW(ep)
  373. }
  374. return sb.clearDefaultGW()
  375. }
  376. func (ep *endpoint) Delete() error {
  377. var err error
  378. n, err := ep.getNetworkFromStore()
  379. if err != nil {
  380. return fmt.Errorf("failed to get network during Delete: %v", err)
  381. }
  382. ep, err = n.getEndpointFromStore(ep.ID())
  383. if err != nil {
  384. return fmt.Errorf("failed to get endpoint from store during Delete: %v", err)
  385. }
  386. ep.Lock()
  387. epid := ep.id
  388. name := ep.name
  389. if ep.sandboxID != "" {
  390. ep.Unlock()
  391. return &ActiveContainerError{name: name, id: epid}
  392. }
  393. ep.Unlock()
  394. if err = n.getEpCnt().DecEndpointCnt(); err != nil {
  395. return err
  396. }
  397. defer func() {
  398. if err != nil {
  399. if e := n.getEpCnt().IncEndpointCnt(); e != nil {
  400. log.Warnf("failed to update network %s : %v", n.name, e)
  401. }
  402. }
  403. }()
  404. if err = n.getController().deleteFromStore(ep); err != nil {
  405. return err
  406. }
  407. defer func() {
  408. if err != nil {
  409. ep.dbExists = false
  410. if e := n.getController().updateToStore(ep); e != nil {
  411. log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
  412. }
  413. }
  414. }()
  415. if err = ep.deleteEndpoint(); err != nil {
  416. return err
  417. }
  418. ep.releaseAddress()
  419. return nil
  420. }
  421. func (ep *endpoint) deleteEndpoint() error {
  422. ep.Lock()
  423. n := ep.network
  424. name := ep.name
  425. epid := ep.id
  426. ep.Unlock()
  427. driver, err := n.driver()
  428. if err != nil {
  429. return fmt.Errorf("failed to delete endpoint: %v", err)
  430. }
  431. if err := driver.DeleteEndpoint(n.id, epid); err != nil {
  432. if _, ok := err.(types.ForbiddenError); ok {
  433. return err
  434. }
  435. log.Warnf("driver error deleting endpoint %s : %v", name, err)
  436. }
  437. return nil
  438. }
  439. func (ep *endpoint) getSandbox() (*sandbox, bool) {
  440. ep.Lock()
  441. c := ep.network.getController()
  442. sid := ep.sandboxID
  443. ep.Unlock()
  444. c.Lock()
  445. ps, ok := c.sandboxes[sid]
  446. c.Unlock()
  447. return ps, ok
  448. }
  449. func (ep *endpoint) getFirstInterfaceAddress() net.IP {
  450. ep.Lock()
  451. defer ep.Unlock()
  452. if ep.iface.addr != nil {
  453. return ep.iface.addr.IP
  454. }
  455. return nil
  456. }
  457. // EndpointOptionGeneric function returns an option setter for a Generic option defined
  458. // in a Dictionary of Key-Value pair
  459. func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
  460. return func(ep *endpoint) {
  461. for k, v := range generic {
  462. ep.generic[k] = v
  463. }
  464. }
  465. }
  466. // CreateOptionExposedPorts function returns an option setter for the container exposed
  467. // ports option to be passed to network.CreateEndpoint() method.
  468. func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption {
  469. return func(ep *endpoint) {
  470. // Defensive copy
  471. eps := make([]types.TransportPort, len(exposedPorts))
  472. copy(eps, exposedPorts)
  473. // Store endpoint label and in generic because driver needs it
  474. ep.exposedPorts = eps
  475. ep.generic[netlabel.ExposedPorts] = eps
  476. }
  477. }
  478. // CreateOptionPortMapping function returns an option setter for the mapping
  479. // ports option to be passed to network.CreateEndpoint() method.
  480. func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption {
  481. return func(ep *endpoint) {
  482. // Store a copy of the bindings as generic data to pass to the driver
  483. pbs := make([]types.PortBinding, len(portBindings))
  484. copy(pbs, portBindings)
  485. ep.generic[netlabel.PortMap] = pbs
  486. }
  487. }
  488. // JoinOptionPriority function returns an option setter for priority option to
  489. // be passed to the endpoint.Join() method.
  490. func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
  491. return func(ep *endpoint) {
  492. // ep lock already acquired
  493. c := ep.network.getController()
  494. c.Lock()
  495. sb, ok := c.sandboxes[ep.sandboxID]
  496. c.Unlock()
  497. if !ok {
  498. log.Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id)
  499. return
  500. }
  501. sb.epPriority[ep.id] = prio
  502. }
  503. }
  504. func (ep *endpoint) DataScope() string {
  505. return ep.getNetwork().DataScope()
  506. }
  507. func (ep *endpoint) assignAddress() error {
  508. var (
  509. ipam ipamapi.Ipam
  510. err error
  511. )
  512. n := ep.getNetwork()
  513. if n.Type() == "host" || n.Type() == "null" {
  514. return nil
  515. }
  516. log.Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
  517. ipam, err = n.getController().getIpamDriver(n.ipamType)
  518. if err != nil {
  519. return err
  520. }
  521. err = ep.assignAddressVersion(4, ipam)
  522. if err != nil {
  523. return err
  524. }
  525. return ep.assignAddressVersion(6, ipam)
  526. }
  527. func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
  528. var (
  529. poolID *string
  530. address **net.IPNet
  531. )
  532. n := ep.getNetwork()
  533. switch ipVer {
  534. case 4:
  535. poolID = &ep.iface.v4PoolID
  536. address = &ep.iface.addr
  537. case 6:
  538. poolID = &ep.iface.v6PoolID
  539. address = &ep.iface.addrv6
  540. default:
  541. return types.InternalErrorf("incorrect ip version number passed: %d", ipVer)
  542. }
  543. ipInfo := n.getIPInfo(ipVer)
  544. // ipv6 address is not mandatory
  545. if len(ipInfo) == 0 && ipVer == 6 {
  546. return nil
  547. }
  548. for _, d := range ipInfo {
  549. addr, _, err := ipam.RequestAddress(d.PoolID, nil, nil)
  550. if err == nil {
  551. ep.Lock()
  552. *address = addr
  553. *poolID = d.PoolID
  554. ep.Unlock()
  555. return nil
  556. }
  557. if err != ipamapi.ErrNoAvailableIPs {
  558. return err
  559. }
  560. }
  561. return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID())
  562. }
  563. func (ep *endpoint) releaseAddress() {
  564. n := ep.getNetwork()
  565. if n.Type() == "host" || n.Type() == "null" {
  566. return
  567. }
  568. log.Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
  569. ipam, err := n.getController().getIpamDriver(n.ipamType)
  570. if err != nil {
  571. log.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
  572. return
  573. }
  574. if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
  575. log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
  576. }
  577. if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() {
  578. if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
  579. log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
  580. }
  581. }
  582. }