endpoint.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  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/netlabel"
  12. "github.com/docker/libnetwork/types"
  13. )
  14. // Endpoint represents a logical connection between a network and a sandbox.
  15. type Endpoint interface {
  16. // A system generated id for this endpoint.
  17. ID() string
  18. // Name returns the name of this endpoint.
  19. Name() string
  20. // Network returns the name of the network to which this endpoint is attached.
  21. Network() string
  22. // Join joins the sandbox to the endpoint and populates into the sandbox
  23. // the network resources allocated for the endpoint.
  24. Join(sandbox Sandbox, options ...EndpointOption) error
  25. // Leave detaches the network resources populated in the sandbox.
  26. Leave(sandbox Sandbox, options ...EndpointOption) error
  27. // Return certain operational data belonging to this endpoint
  28. Info() EndpointInfo
  29. // DriverInfo returns a collection of driver operational data related to this endpoint retrieved from the driver
  30. DriverInfo() (map[string]interface{}, error)
  31. // Delete and detaches this endpoint from the network.
  32. Delete() error
  33. }
  34. // EndpointOption is a option setter function type used to pass varios options to Network
  35. // and Endpoint interfaces methods. The various setter functions of type EndpointOption are
  36. // provided by libnetwork, they look like <Create|Join|Leave>Option[...](...)
  37. type EndpointOption func(ep *endpoint)
  38. type endpoint struct {
  39. name string
  40. id string
  41. network *network
  42. iface *endpointInterface
  43. joinInfo *endpointJoinInfo
  44. sandboxID string
  45. exposedPorts []types.TransportPort
  46. generic map[string]interface{}
  47. joinLeaveDone chan struct{}
  48. dbIndex uint64
  49. dbExists bool
  50. sync.Mutex
  51. }
  52. func (ep *endpoint) MarshalJSON() ([]byte, error) {
  53. ep.Lock()
  54. defer ep.Unlock()
  55. epMap := make(map[string]interface{})
  56. epMap["name"] = ep.name
  57. epMap["id"] = ep.id
  58. epMap["ep_iface"] = ep.iface
  59. epMap["exposed_ports"] = ep.exposedPorts
  60. epMap["generic"] = ep.generic
  61. epMap["sandbox"] = ep.sandboxID
  62. return json.Marshal(epMap)
  63. }
  64. func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
  65. ep.Lock()
  66. defer ep.Unlock()
  67. var epMap map[string]interface{}
  68. if err := json.Unmarshal(b, &epMap); err != nil {
  69. return err
  70. }
  71. ep.name = epMap["name"].(string)
  72. ep.id = epMap["id"].(string)
  73. ib, _ := json.Marshal(epMap["ep_iface"])
  74. json.Unmarshal(ib, &ep.iface)
  75. tb, _ := json.Marshal(epMap["exposed_ports"])
  76. var tPorts []types.TransportPort
  77. json.Unmarshal(tb, &tPorts)
  78. ep.exposedPorts = tPorts
  79. cb, _ := json.Marshal(epMap["sandbox"])
  80. json.Unmarshal(cb, &ep.sandboxID)
  81. if epMap["generic"] != nil {
  82. ep.generic = epMap["generic"].(map[string]interface{})
  83. }
  84. return nil
  85. }
  86. func (ep *endpoint) ID() string {
  87. ep.Lock()
  88. defer ep.Unlock()
  89. return ep.id
  90. }
  91. func (ep *endpoint) Name() string {
  92. ep.Lock()
  93. defer ep.Unlock()
  94. return ep.name
  95. }
  96. func (ep *endpoint) Network() string {
  97. return ep.getNetwork().name
  98. }
  99. // endpoint Key structure : endpoint/network-id/endpoint-id
  100. func (ep *endpoint) Key() []string {
  101. return []string{datastore.EndpointKeyPrefix, ep.getNetwork().id, ep.id}
  102. }
  103. func (ep *endpoint) KeyPrefix() []string {
  104. return []string{datastore.EndpointKeyPrefix, ep.getNetwork().id}
  105. }
  106. func (ep *endpoint) networkIDFromKey(key string) (string, error) {
  107. // endpoint Key structure : docker/libnetwork/endpoint/${network-id}/${endpoint-id}
  108. // it's an invalid key if the key doesn't have all the 5 key elements above
  109. keyElements := strings.Split(key, "/")
  110. if !strings.HasPrefix(key, datastore.Key(datastore.EndpointKeyPrefix)) || len(keyElements) < 5 {
  111. return "", fmt.Errorf("invalid endpoint key : %v", key)
  112. }
  113. // network-id is placed at index=3. pls refer to endpoint.Key() method
  114. return strings.Split(key, "/")[3], nil
  115. }
  116. func (ep *endpoint) Value() []byte {
  117. b, err := json.Marshal(ep)
  118. if err != nil {
  119. return nil
  120. }
  121. return b
  122. }
  123. func (ep *endpoint) SetValue(value []byte) error {
  124. return json.Unmarshal(value, ep)
  125. }
  126. func (ep *endpoint) Index() uint64 {
  127. ep.Lock()
  128. defer ep.Unlock()
  129. return ep.dbIndex
  130. }
  131. func (ep *endpoint) SetIndex(index uint64) {
  132. ep.Lock()
  133. defer ep.Unlock()
  134. ep.dbIndex = index
  135. ep.dbExists = true
  136. }
  137. func (ep *endpoint) Exists() bool {
  138. ep.Lock()
  139. defer ep.Unlock()
  140. return ep.dbExists
  141. }
  142. func (ep *endpoint) Skip() bool {
  143. return ep.getNetwork().Skip()
  144. }
  145. func (ep *endpoint) processOptions(options ...EndpointOption) {
  146. ep.Lock()
  147. defer ep.Unlock()
  148. for _, opt := range options {
  149. if opt != nil {
  150. opt(ep)
  151. }
  152. }
  153. }
  154. func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
  155. if sbox == nil {
  156. return types.BadRequestErrorf("endpoint cannot be joined by nil container")
  157. }
  158. sb, ok := sbox.(*sandbox)
  159. if !ok {
  160. return types.BadRequestErrorf("not a valid Sandbox interface")
  161. }
  162. sb.joinLeaveStart()
  163. defer sb.joinLeaveEnd()
  164. return ep.sbJoin(sbox, options...)
  165. }
  166. func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
  167. var err error
  168. sb, ok := sbox.(*sandbox)
  169. if !ok {
  170. return types.BadRequestErrorf("not a valid Sandbox interface")
  171. }
  172. ep.Lock()
  173. if ep.sandboxID != "" {
  174. ep.Unlock()
  175. return types.ForbiddenErrorf("a sandbox has already joined the endpoint")
  176. }
  177. ep.sandboxID = sbox.ID()
  178. ep.joinInfo = &endpointJoinInfo{}
  179. network := ep.network
  180. epid := ep.id
  181. ep.Unlock()
  182. defer func() {
  183. if err != nil {
  184. ep.Lock()
  185. ep.sandboxID = ""
  186. ep.Unlock()
  187. }
  188. }()
  189. network.Lock()
  190. driver := network.driver
  191. nid := network.id
  192. network.Unlock()
  193. ep.processOptions(options...)
  194. err = driver.Join(nid, epid, sbox.Key(), ep, sbox.Labels())
  195. if err != nil {
  196. return err
  197. }
  198. defer func() {
  199. if err != nil {
  200. // Do not alter global err variable, it's needed by the previous defer
  201. if err := driver.Leave(nid, epid); err != nil {
  202. log.Warnf("driver leave failed while rolling back join: %v", err)
  203. }
  204. }
  205. }()
  206. address := ""
  207. if ip := ep.getFirstInterfaceAddress(); ip != nil {
  208. address = ip.String()
  209. }
  210. if err = sb.updateHostsFile(address, network.getSvcRecords()); err != nil {
  211. return err
  212. }
  213. if err = sb.updateDNS(ep.getNetwork().enableIPv6); err != nil {
  214. return err
  215. }
  216. if !ep.isLocalScoped() {
  217. if err = network.ctrlr.updateToStore(ep); err != nil {
  218. return err
  219. }
  220. }
  221. sb.Lock()
  222. heap.Push(&sb.endpoints, ep)
  223. sb.Unlock()
  224. defer func() {
  225. if err != nil {
  226. for i, e := range sb.getConnectedEndpoints() {
  227. if e == ep {
  228. sb.Lock()
  229. heap.Remove(&sb.endpoints, i)
  230. sb.Unlock()
  231. return
  232. }
  233. }
  234. }
  235. }()
  236. if err = sb.populateNetworkResources(ep); err != nil {
  237. return err
  238. }
  239. if sb.needDefaultGW() {
  240. return sb.setupDefaultGW(ep)
  241. }
  242. return sb.clearDefaultGW()
  243. }
  244. func (ep *endpoint) hasInterface(iName string) bool {
  245. ep.Lock()
  246. defer ep.Unlock()
  247. return ep.iface != nil && ep.iface.srcName == iName
  248. }
  249. func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error {
  250. if sbox == nil || sbox.ID() == "" || sbox.Key() == "" {
  251. return types.BadRequestErrorf("invalid Sandbox passed to enpoint leave: %v", sbox)
  252. }
  253. sb, ok := sbox.(*sandbox)
  254. if !ok {
  255. return types.BadRequestErrorf("not a valid Sandbox interface")
  256. }
  257. sb.joinLeaveStart()
  258. defer sb.joinLeaveEnd()
  259. return ep.sbLeave(sbox, options...)
  260. }
  261. func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
  262. sb, ok := sbox.(*sandbox)
  263. if !ok {
  264. return types.BadRequestErrorf("not a valid Sandbox interface")
  265. }
  266. ep.Lock()
  267. sid := ep.sandboxID
  268. ep.Unlock()
  269. if sid == "" {
  270. return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
  271. }
  272. if sid != sbox.ID() {
  273. return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sbox.ID())
  274. }
  275. ep.processOptions(options...)
  276. ep.Lock()
  277. ep.sandboxID = ""
  278. n := ep.network
  279. ep.Unlock()
  280. n.Lock()
  281. c := n.ctrlr
  282. d := n.driver
  283. n.Unlock()
  284. if !ep.isLocalScoped() {
  285. if err := c.updateToStore(ep); err != nil {
  286. ep.Lock()
  287. ep.sandboxID = sid
  288. ep.Unlock()
  289. return err
  290. }
  291. }
  292. if err := d.Leave(n.id, ep.id); err != nil {
  293. return err
  294. }
  295. if err := sb.clearNetworkResources(ep); err != nil {
  296. return err
  297. }
  298. if sb.needDefaultGW() {
  299. ep := sb.getEPwithoutGateway()
  300. if ep == nil {
  301. return fmt.Errorf("endpoint without GW expected, but not found")
  302. }
  303. return sb.setupDefaultGW(ep)
  304. }
  305. return sb.clearDefaultGW()
  306. }
  307. func (ep *endpoint) Delete() error {
  308. var err error
  309. ep.Lock()
  310. epid := ep.id
  311. name := ep.name
  312. n := ep.network
  313. if ep.sandboxID != "" {
  314. ep.Unlock()
  315. return &ActiveContainerError{name: name, id: epid}
  316. }
  317. n.Lock()
  318. ctrlr := n.ctrlr
  319. n.Unlock()
  320. ep.Unlock()
  321. if !ep.isLocalScoped() {
  322. if err = ctrlr.deleteFromStore(ep); err != nil {
  323. return err
  324. }
  325. }
  326. defer func() {
  327. if err != nil {
  328. ep.dbExists = false
  329. if !ep.isLocalScoped() {
  330. if e := ctrlr.updateToStore(ep); e != nil {
  331. log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
  332. }
  333. }
  334. }
  335. }()
  336. // Update the endpoint count in network and update it in the datastore
  337. n.DecEndpointCnt()
  338. if err = ctrlr.updateToStore(n); err != nil {
  339. return err
  340. }
  341. defer func() {
  342. if err != nil {
  343. n.IncEndpointCnt()
  344. if e := ctrlr.updateToStore(n); e != nil {
  345. log.Warnf("failed to update network %s : %v", n.name, e)
  346. }
  347. }
  348. }()
  349. if err = ep.deleteEndpoint(); err != nil {
  350. return err
  351. }
  352. return nil
  353. }
  354. func (ep *endpoint) deleteEndpoint() error {
  355. ep.Lock()
  356. n := ep.network
  357. name := ep.name
  358. epid := ep.id
  359. ep.Unlock()
  360. n.Lock()
  361. _, ok := n.endpoints[epid]
  362. if !ok {
  363. n.Unlock()
  364. return nil
  365. }
  366. nid := n.id
  367. driver := n.driver
  368. delete(n.endpoints, epid)
  369. n.Unlock()
  370. if err := driver.DeleteEndpoint(nid, epid); err != nil {
  371. if _, ok := err.(types.ForbiddenError); ok {
  372. n.Lock()
  373. n.endpoints[epid] = ep
  374. n.Unlock()
  375. return err
  376. }
  377. log.Warnf("driver error deleting endpoint %s : %v", name, err)
  378. }
  379. n.updateSvcRecord(ep, false)
  380. return nil
  381. }
  382. func (ep *endpoint) getNetwork() *network {
  383. ep.Lock()
  384. defer ep.Unlock()
  385. return ep.network
  386. }
  387. func (ep *endpoint) getSandbox() (*sandbox, bool) {
  388. ep.Lock()
  389. c := ep.network.getController()
  390. sid := ep.sandboxID
  391. ep.Unlock()
  392. c.Lock()
  393. ps, ok := c.sandboxes[sid]
  394. c.Unlock()
  395. return ps, ok
  396. }
  397. func (ep *endpoint) getFirstInterfaceAddress() net.IP {
  398. ep.Lock()
  399. defer ep.Unlock()
  400. if ep.iface != nil {
  401. return ep.iface.addr.IP
  402. }
  403. return nil
  404. }
  405. // EndpointOptionGeneric function returns an option setter for a Generic option defined
  406. // in a Dictionary of Key-Value pair
  407. func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
  408. return func(ep *endpoint) {
  409. for k, v := range generic {
  410. ep.generic[k] = v
  411. }
  412. }
  413. }
  414. // CreateOptionExposedPorts function returns an option setter for the container exposed
  415. // ports option to be passed to network.CreateEndpoint() method.
  416. func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption {
  417. return func(ep *endpoint) {
  418. // Defensive copy
  419. eps := make([]types.TransportPort, len(exposedPorts))
  420. copy(eps, exposedPorts)
  421. // Store endpoint label and in generic because driver needs it
  422. ep.exposedPorts = eps
  423. ep.generic[netlabel.ExposedPorts] = eps
  424. }
  425. }
  426. // CreateOptionPortMapping function returns an option setter for the mapping
  427. // ports option to be passed to network.CreateEndpoint() method.
  428. func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption {
  429. return func(ep *endpoint) {
  430. // Store a copy of the bindings as generic data to pass to the driver
  431. pbs := make([]types.PortBinding, len(portBindings))
  432. copy(pbs, portBindings)
  433. ep.generic[netlabel.PortMap] = pbs
  434. }
  435. }
  436. // JoinOptionPriority function returns an option setter for priority option to
  437. // be passed to the endpoint.Join() method.
  438. func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
  439. return func(ep *endpoint) {
  440. // ep lock already acquired
  441. c := ep.network.getController()
  442. c.Lock()
  443. sb, ok := c.sandboxes[ep.sandboxID]
  444. c.Unlock()
  445. if !ok {
  446. log.Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id)
  447. return
  448. }
  449. sb.epPriority[ep.id] = prio
  450. }
  451. }
  452. func (ep *endpoint) DataScope() datastore.DataScope {
  453. ep.Lock()
  454. defer ep.Unlock()
  455. return ep.network.dataScope
  456. }
  457. func (ep *endpoint) isLocalScoped() bool {
  458. return ep.DataScope() == datastore.LocalScope
  459. }