container_operations.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. package daemon
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "os"
  7. "path"
  8. "strings"
  9. "github.com/Sirupsen/logrus"
  10. "github.com/docker/docker/container"
  11. "github.com/docker/docker/daemon/network"
  12. derr "github.com/docker/docker/errors"
  13. "github.com/docker/docker/pkg/stringid"
  14. "github.com/docker/docker/runconfig"
  15. containertypes "github.com/docker/engine-api/types/container"
  16. networktypes "github.com/docker/engine-api/types/network"
  17. "github.com/docker/go-connections/nat"
  18. "github.com/docker/libnetwork"
  19. "github.com/docker/libnetwork/netlabel"
  20. "github.com/docker/libnetwork/options"
  21. "github.com/docker/libnetwork/types"
  22. )
  23. var (
  24. // ErrRootFSReadOnly is returned when a container
  25. // rootfs is marked readonly.
  26. ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
  27. getPortMapInfo = container.GetSandboxPortMapInfo
  28. )
  29. func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]libnetwork.SandboxOption, error) {
  30. var (
  31. sboxOptions []libnetwork.SandboxOption
  32. err error
  33. dns []string
  34. dnsSearch []string
  35. dnsOptions []string
  36. bindings = make(nat.PortMap)
  37. pbList []types.PortBinding
  38. exposeList []types.TransportPort
  39. )
  40. defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
  41. sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
  42. libnetwork.OptionDomainname(container.Config.Domainname))
  43. if container.HostConfig.NetworkMode.IsHost() {
  44. sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
  45. if len(container.HostConfig.ExtraHosts) == 0 {
  46. sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
  47. }
  48. if len(container.HostConfig.DNS) == 0 && len(daemon.configStore.DNS) == 0 &&
  49. len(container.HostConfig.DNSSearch) == 0 && len(daemon.configStore.DNSSearch) == 0 &&
  50. len(container.HostConfig.DNSOptions) == 0 && len(daemon.configStore.DNSOptions) == 0 {
  51. sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
  52. }
  53. } else {
  54. // OptionUseExternalKey is mandatory for userns support.
  55. // But optional for non-userns support
  56. sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
  57. }
  58. container.HostsPath, err = container.GetRootResourcePath("hosts")
  59. if err != nil {
  60. return nil, err
  61. }
  62. sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath))
  63. container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
  64. if err != nil {
  65. return nil, err
  66. }
  67. sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath))
  68. if len(container.HostConfig.DNS) > 0 {
  69. dns = container.HostConfig.DNS
  70. } else if len(daemon.configStore.DNS) > 0 {
  71. dns = daemon.configStore.DNS
  72. }
  73. for _, d := range dns {
  74. sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d))
  75. }
  76. if len(container.HostConfig.DNSSearch) > 0 {
  77. dnsSearch = container.HostConfig.DNSSearch
  78. } else if len(daemon.configStore.DNSSearch) > 0 {
  79. dnsSearch = daemon.configStore.DNSSearch
  80. }
  81. for _, ds := range dnsSearch {
  82. sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
  83. }
  84. if len(container.HostConfig.DNSOptions) > 0 {
  85. dnsOptions = container.HostConfig.DNSOptions
  86. } else if len(daemon.configStore.DNSOptions) > 0 {
  87. dnsOptions = daemon.configStore.DNSOptions
  88. }
  89. for _, ds := range dnsOptions {
  90. sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds))
  91. }
  92. if container.NetworkSettings.SecondaryIPAddresses != nil {
  93. name := container.Config.Hostname
  94. if container.Config.Domainname != "" {
  95. name = name + "." + container.Config.Domainname
  96. }
  97. for _, a := range container.NetworkSettings.SecondaryIPAddresses {
  98. sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr))
  99. }
  100. }
  101. for _, extraHost := range container.HostConfig.ExtraHosts {
  102. // allow IPv6 addresses in extra hosts; only split on first ":"
  103. parts := strings.SplitN(extraHost, ":", 2)
  104. sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
  105. }
  106. if container.HostConfig.PortBindings != nil {
  107. for p, b := range container.HostConfig.PortBindings {
  108. bindings[p] = []nat.PortBinding{}
  109. for _, bb := range b {
  110. bindings[p] = append(bindings[p], nat.PortBinding{
  111. HostIP: bb.HostIP,
  112. HostPort: bb.HostPort,
  113. })
  114. }
  115. }
  116. }
  117. portSpecs := container.Config.ExposedPorts
  118. ports := make([]nat.Port, len(portSpecs))
  119. var i int
  120. for p := range portSpecs {
  121. ports[i] = p
  122. i++
  123. }
  124. nat.SortPortMap(ports, bindings)
  125. for _, port := range ports {
  126. expose := types.TransportPort{}
  127. expose.Proto = types.ParseProtocol(port.Proto())
  128. expose.Port = uint16(port.Int())
  129. exposeList = append(exposeList, expose)
  130. pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
  131. binding := bindings[port]
  132. for i := 0; i < len(binding); i++ {
  133. pbCopy := pb.GetCopy()
  134. newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
  135. var portStart, portEnd int
  136. if err == nil {
  137. portStart, portEnd, err = newP.Range()
  138. }
  139. if err != nil {
  140. return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
  141. }
  142. pbCopy.HostPort = uint16(portStart)
  143. pbCopy.HostPortEnd = uint16(portEnd)
  144. pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
  145. pbList = append(pbList, pbCopy)
  146. }
  147. if container.HostConfig.PublishAllPorts && len(binding) == 0 {
  148. pbList = append(pbList, pb)
  149. }
  150. }
  151. sboxOptions = append(sboxOptions,
  152. libnetwork.OptionPortMapping(pbList),
  153. libnetwork.OptionExposedPorts(exposeList))
  154. // Legacy Link feature is supported only for the default bridge network.
  155. // return if this call to build join options is not for default bridge network
  156. // Legacy Link is only supported by docker run --link
  157. bridgeSettings, ok := container.NetworkSettings.Networks[defaultNetName]
  158. if !ok {
  159. return sboxOptions, nil
  160. }
  161. if bridgeSettings.EndpointID == "" {
  162. return sboxOptions, nil
  163. }
  164. var (
  165. childEndpoints, parentEndpoints []string
  166. cEndpointID string
  167. )
  168. children := daemon.children(container)
  169. for linkAlias, child := range children {
  170. if !isLinkable(child) {
  171. return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name)
  172. }
  173. _, alias := path.Split(linkAlias)
  174. // allow access to the linked container via the alias, real name, and container hostname
  175. aliasList := alias + " " + child.Config.Hostname
  176. // only add the name if alias isn't equal to the name
  177. if alias != child.Name[1:] {
  178. aliasList = aliasList + " " + child.Name[1:]
  179. }
  180. sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
  181. cEndpointID = child.NetworkSettings.Networks[defaultNetName].EndpointID
  182. if cEndpointID != "" {
  183. childEndpoints = append(childEndpoints, cEndpointID)
  184. }
  185. }
  186. for alias, parent := range daemon.parents(container) {
  187. if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() {
  188. continue
  189. }
  190. _, alias = path.Split(alias)
  191. logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress)
  192. sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(
  193. parent.ID,
  194. alias,
  195. bridgeSettings.IPAddress,
  196. ))
  197. if cEndpointID != "" {
  198. parentEndpoints = append(parentEndpoints, cEndpointID)
  199. }
  200. }
  201. linkOptions := options.Generic{
  202. netlabel.GenericData: options.Generic{
  203. "ParentEndpoints": parentEndpoints,
  204. "ChildEndpoints": childEndpoints,
  205. },
  206. }
  207. sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions))
  208. return sboxOptions, nil
  209. }
  210. func (daemon *Daemon) updateNetworkSettings(container *container.Container, n libnetwork.Network) error {
  211. if container.NetworkSettings == nil {
  212. container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)}
  213. }
  214. if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
  215. return runconfig.ErrConflictHostNetwork
  216. }
  217. for s := range container.NetworkSettings.Networks {
  218. sn, err := daemon.FindNetwork(s)
  219. if err != nil {
  220. continue
  221. }
  222. if sn.Name() == n.Name() {
  223. // Avoid duplicate config
  224. return nil
  225. }
  226. if !containertypes.NetworkMode(sn.Type()).IsPrivate() ||
  227. !containertypes.NetworkMode(n.Type()).IsPrivate() {
  228. return runconfig.ErrConflictSharedNetwork
  229. }
  230. if containertypes.NetworkMode(sn.Name()).IsNone() ||
  231. containertypes.NetworkMode(n.Name()).IsNone() {
  232. return runconfig.ErrConflictNoNetwork
  233. }
  234. }
  235. if _, ok := container.NetworkSettings.Networks[n.Name()]; !ok {
  236. container.NetworkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings)
  237. }
  238. return nil
  239. }
  240. func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error {
  241. if err := container.BuildEndpointInfo(n, ep); err != nil {
  242. return err
  243. }
  244. if container.HostConfig.NetworkMode == runconfig.DefaultDaemonNetworkMode() {
  245. container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface
  246. }
  247. return nil
  248. }
  249. // UpdateNetwork is used to update the container's network (e.g. when linked containers
  250. // get removed/unlinked).
  251. func (daemon *Daemon) updateNetwork(container *container.Container) error {
  252. ctrl := daemon.netController
  253. sid := container.NetworkSettings.SandboxID
  254. sb, err := ctrl.SandboxByID(sid)
  255. if err != nil {
  256. return fmt.Errorf("error locating sandbox id %s: %v", sid, err)
  257. }
  258. // Find if container is connected to the default bridge network
  259. var n libnetwork.Network
  260. for name := range container.NetworkSettings.Networks {
  261. sn, err := daemon.FindNetwork(name)
  262. if err != nil {
  263. continue
  264. }
  265. if sn.Name() == runconfig.DefaultDaemonNetworkMode().NetworkName() {
  266. n = sn
  267. break
  268. }
  269. }
  270. if n == nil {
  271. // Not connected to the default bridge network; Nothing to do
  272. return nil
  273. }
  274. options, err := daemon.buildSandboxOptions(container)
  275. if err != nil {
  276. return fmt.Errorf("Update network failed: %v", err)
  277. }
  278. if err := sb.Refresh(options...); err != nil {
  279. return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err)
  280. }
  281. return nil
  282. }
  283. func errClusterNetworkOnRun(n string) error {
  284. return fmt.Errorf("swarm-scoped network (%s) is not compatible with `docker create` or `docker run`. This network can only be used by a docker service", n)
  285. }
  286. // updateContainerNetworkSettings update the network settings
  287. func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error {
  288. var (
  289. n libnetwork.Network
  290. err error
  291. )
  292. mode := container.HostConfig.NetworkMode
  293. if container.Config.NetworkDisabled || mode.IsContainer() {
  294. return nil
  295. }
  296. networkName := mode.NetworkName()
  297. if mode.IsDefault() {
  298. networkName = daemon.netController.Config().Daemon.DefaultNetwork
  299. }
  300. if mode.IsUserDefined() {
  301. n, err = daemon.FindNetwork(networkName)
  302. if err != nil {
  303. return err
  304. }
  305. if !container.Managed && n.Info().Dynamic() {
  306. return errClusterNetworkOnRun(networkName)
  307. }
  308. networkName = n.Name()
  309. }
  310. if container.NetworkSettings == nil {
  311. container.NetworkSettings = &network.Settings{}
  312. }
  313. if len(endpointsConfig) > 0 {
  314. container.NetworkSettings.Networks = endpointsConfig
  315. }
  316. if container.NetworkSettings.Networks == nil {
  317. container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings)
  318. container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings)
  319. }
  320. if !mode.IsUserDefined() {
  321. return nil
  322. }
  323. // Make sure to internally store the per network endpoint config by network name
  324. if _, ok := container.NetworkSettings.Networks[networkName]; ok {
  325. return nil
  326. }
  327. if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok {
  328. container.NetworkSettings.Networks[networkName] = nwConfig
  329. delete(container.NetworkSettings.Networks, n.ID())
  330. return nil
  331. }
  332. return nil
  333. }
  334. func (daemon *Daemon) allocateNetwork(container *container.Container) error {
  335. controller := daemon.netController
  336. if daemon.netController == nil {
  337. return nil
  338. }
  339. // Cleanup any stale sandbox left over due to ungraceful daemon shutdown
  340. if err := controller.SandboxDestroy(container.ID); err != nil {
  341. logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID)
  342. }
  343. updateSettings := false
  344. if len(container.NetworkSettings.Networks) == 0 {
  345. if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() {
  346. return nil
  347. }
  348. err := daemon.updateContainerNetworkSettings(container, nil)
  349. if err != nil {
  350. return err
  351. }
  352. updateSettings = true
  353. }
  354. // always connect default network first since only default
  355. // network mode support link and we need do some setting
  356. // on sandbox initialize for link, but the sandbox only be initialized
  357. // on first network connecting.
  358. defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
  359. if nConf, ok := container.NetworkSettings.Networks[defaultNetName]; ok {
  360. if err := daemon.connectToNetwork(container, defaultNetName, nConf, updateSettings); err != nil {
  361. return err
  362. }
  363. }
  364. for n, nConf := range container.NetworkSettings.Networks {
  365. if n == defaultNetName {
  366. continue
  367. }
  368. if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil {
  369. return err
  370. }
  371. }
  372. return container.WriteHostConfig()
  373. }
  374. func (daemon *Daemon) getNetworkSandbox(container *container.Container) libnetwork.Sandbox {
  375. var sb libnetwork.Sandbox
  376. daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool {
  377. if s.ContainerID() == container.ID {
  378. sb = s
  379. return true
  380. }
  381. return false
  382. })
  383. return sb
  384. }
  385. // hasUserDefinedIPAddress returns whether the passed endpoint configuration contains IP address configuration
  386. func hasUserDefinedIPAddress(epConfig *networktypes.EndpointSettings) bool {
  387. return epConfig != nil && epConfig.IPAMConfig != nil && (len(epConfig.IPAMConfig.IPv4Address) > 0 || len(epConfig.IPAMConfig.IPv6Address) > 0)
  388. }
  389. // User specified ip address is acceptable only for networks with user specified subnets.
  390. func validateNetworkingConfig(n libnetwork.Network, epConfig *networktypes.EndpointSettings) error {
  391. if n == nil || epConfig == nil {
  392. return nil
  393. }
  394. if !hasUserDefinedIPAddress(epConfig) {
  395. return nil
  396. }
  397. _, _, nwIPv4Configs, nwIPv6Configs := n.Info().IpamConfig()
  398. for _, s := range []struct {
  399. ipConfigured bool
  400. subnetConfigs []*libnetwork.IpamConf
  401. }{
  402. {
  403. ipConfigured: len(epConfig.IPAMConfig.IPv4Address) > 0,
  404. subnetConfigs: nwIPv4Configs,
  405. },
  406. {
  407. ipConfigured: len(epConfig.IPAMConfig.IPv6Address) > 0,
  408. subnetConfigs: nwIPv6Configs,
  409. },
  410. } {
  411. if s.ipConfigured {
  412. foundSubnet := false
  413. for _, cfg := range s.subnetConfigs {
  414. if len(cfg.PreferredPool) > 0 {
  415. foundSubnet = true
  416. break
  417. }
  418. }
  419. if !foundSubnet {
  420. return runconfig.ErrUnsupportedNetworkNoSubnetAndIP
  421. }
  422. }
  423. }
  424. return nil
  425. }
  426. // cleanOperationalData resets the operational data from the passed endpoint settings
  427. func cleanOperationalData(es *networktypes.EndpointSettings) {
  428. es.EndpointID = ""
  429. es.Gateway = ""
  430. es.IPAddress = ""
  431. es.IPPrefixLen = 0
  432. es.IPv6Gateway = ""
  433. es.GlobalIPv6Address = ""
  434. es.GlobalIPv6PrefixLen = 0
  435. es.MacAddress = ""
  436. }
  437. func (daemon *Daemon) updateNetworkConfig(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (libnetwork.Network, error) {
  438. if container.HostConfig.NetworkMode.IsContainer() {
  439. return nil, runconfig.ErrConflictSharedNetwork
  440. }
  441. if containertypes.NetworkMode(idOrName).IsBridge() &&
  442. daemon.configStore.DisableBridge {
  443. container.Config.NetworkDisabled = true
  444. return nil, nil
  445. }
  446. if !containertypes.NetworkMode(idOrName).IsUserDefined() {
  447. if hasUserDefinedIPAddress(endpointConfig) {
  448. return nil, runconfig.ErrUnsupportedNetworkAndIP
  449. }
  450. if endpointConfig != nil && len(endpointConfig.Aliases) > 0 {
  451. return nil, runconfig.ErrUnsupportedNetworkAndAlias
  452. }
  453. } else {
  454. addShortID := true
  455. shortID := stringid.TruncateID(container.ID)
  456. for _, alias := range endpointConfig.Aliases {
  457. if alias == shortID {
  458. addShortID = false
  459. break
  460. }
  461. }
  462. if addShortID {
  463. endpointConfig.Aliases = append(endpointConfig.Aliases, shortID)
  464. }
  465. }
  466. n, err := daemon.FindNetwork(idOrName)
  467. if err != nil {
  468. return nil, err
  469. }
  470. if err := validateNetworkingConfig(n, endpointConfig); err != nil {
  471. return nil, err
  472. }
  473. if updateSettings {
  474. if err := daemon.updateNetworkSettings(container, n); err != nil {
  475. return nil, err
  476. }
  477. }
  478. return n, nil
  479. }
  480. func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) {
  481. if endpointConfig == nil {
  482. endpointConfig = &networktypes.EndpointSettings{}
  483. }
  484. n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings)
  485. if err != nil {
  486. return err
  487. }
  488. if n == nil {
  489. return nil
  490. }
  491. controller := daemon.netController
  492. sb := daemon.getNetworkSandbox(container)
  493. createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb)
  494. if err != nil {
  495. return err
  496. }
  497. endpointName := strings.TrimPrefix(container.Name, "/")
  498. ep, err := n.CreateEndpoint(endpointName, createOptions...)
  499. if err != nil {
  500. return err
  501. }
  502. defer func() {
  503. if err != nil {
  504. if e := ep.Delete(false); e != nil {
  505. logrus.Warnf("Could not rollback container connection to network %s", idOrName)
  506. }
  507. }
  508. }()
  509. container.NetworkSettings.Networks[n.Name()] = endpointConfig
  510. if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil {
  511. return err
  512. }
  513. if sb == nil {
  514. options, err := daemon.buildSandboxOptions(container)
  515. if err != nil {
  516. return err
  517. }
  518. sb, err = controller.NewSandbox(container.ID, options...)
  519. if err != nil {
  520. return err
  521. }
  522. container.UpdateSandboxNetworkSettings(sb)
  523. }
  524. joinOptions, err := container.BuildJoinOptions(n)
  525. if err != nil {
  526. return err
  527. }
  528. if err := ep.Join(sb, joinOptions...); err != nil {
  529. return err
  530. }
  531. if err := container.UpdateJoinInfo(n, ep); err != nil {
  532. return fmt.Errorf("Updating join info failed: %v", err)
  533. }
  534. container.NetworkSettings.Ports = getPortMapInfo(sb)
  535. daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
  536. return nil
  537. }
  538. // ForceEndpointDelete deletes an endpoing from a network forcefully
  539. func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
  540. ep, err := n.EndpointByName(name)
  541. if err != nil {
  542. return err
  543. }
  544. return ep.Delete(true)
  545. }
  546. func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
  547. var (
  548. ep libnetwork.Endpoint
  549. sbox libnetwork.Sandbox
  550. )
  551. s := func(current libnetwork.Endpoint) bool {
  552. epInfo := current.Info()
  553. if epInfo == nil {
  554. return false
  555. }
  556. if sb := epInfo.Sandbox(); sb != nil {
  557. if sb.ContainerID() == container.ID {
  558. ep = current
  559. sbox = sb
  560. return true
  561. }
  562. }
  563. return false
  564. }
  565. n.WalkEndpoints(s)
  566. if ep == nil && force {
  567. epName := strings.TrimPrefix(container.Name, "/")
  568. ep, err := n.EndpointByName(epName)
  569. if err != nil {
  570. return err
  571. }
  572. return ep.Delete(force)
  573. }
  574. if ep == nil {
  575. return fmt.Errorf("container %s is not connected to the network", container.ID)
  576. }
  577. if err := ep.Leave(sbox); err != nil {
  578. return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
  579. }
  580. container.NetworkSettings.Ports = getPortMapInfo(sbox)
  581. if err := ep.Delete(false); err != nil {
  582. return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
  583. }
  584. delete(container.NetworkSettings.Networks, n.Name())
  585. return nil
  586. }
  587. func (daemon *Daemon) initializeNetworking(container *container.Container) error {
  588. var err error
  589. if container.HostConfig.NetworkMode.IsContainer() {
  590. // we need to get the hosts files from the container to join
  591. nc, err := daemon.getNetworkedContainer(container.ID, container.HostConfig.NetworkMode.ConnectedContainer())
  592. if err != nil {
  593. return err
  594. }
  595. container.HostnamePath = nc.HostnamePath
  596. container.HostsPath = nc.HostsPath
  597. container.ResolvConfPath = nc.ResolvConfPath
  598. container.Config.Hostname = nc.Config.Hostname
  599. container.Config.Domainname = nc.Config.Domainname
  600. return nil
  601. }
  602. if container.HostConfig.NetworkMode.IsHost() {
  603. container.Config.Hostname, err = os.Hostname()
  604. if err != nil {
  605. return err
  606. }
  607. }
  608. if err := daemon.allocateNetwork(container); err != nil {
  609. return err
  610. }
  611. return container.BuildHostnameFile()
  612. }
  613. func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*container.Container, error) {
  614. nc, err := daemon.GetContainer(connectedContainerID)
  615. if err != nil {
  616. return nil, err
  617. }
  618. if containerID == nc.ID {
  619. return nil, fmt.Errorf("cannot join own network")
  620. }
  621. if !nc.IsRunning() {
  622. err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID)
  623. return nil, derr.NewRequestConflictError(err)
  624. }
  625. if nc.IsRestarting() {
  626. return nil, errContainerIsRestarting(connectedContainerID)
  627. }
  628. return nc, nil
  629. }
  630. func (daemon *Daemon) releaseNetwork(container *container.Container) {
  631. if daemon.netController == nil {
  632. return
  633. }
  634. if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
  635. return
  636. }
  637. sid := container.NetworkSettings.SandboxID
  638. settings := container.NetworkSettings.Networks
  639. container.NetworkSettings.Ports = nil
  640. if sid == "" || len(settings) == 0 {
  641. return
  642. }
  643. var networks []libnetwork.Network
  644. for n, epSettings := range settings {
  645. if nw, err := daemon.FindNetwork(n); err == nil {
  646. networks = append(networks, nw)
  647. }
  648. cleanOperationalData(epSettings)
  649. }
  650. sb, err := daemon.netController.SandboxByID(sid)
  651. if err != nil {
  652. logrus.Warnf("error locating sandbox id %s: %v", sid, err)
  653. return
  654. }
  655. if err := sb.Delete(); err != nil {
  656. logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err)
  657. }
  658. for _, nw := range networks {
  659. attributes := map[string]string{
  660. "container": container.ID,
  661. }
  662. daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes)
  663. }
  664. }