Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / docker / libnetwork / default_gateway.go
1 package libnetwork
2
3 import (
4         "fmt"
5         "strings"
6
7         "github.com/Sirupsen/logrus"
8         "github.com/docker/libnetwork/netlabel"
9         "github.com/docker/libnetwork/types"
10 )
11
12 const (
13         gwEPlen = 12
14 )
15
16 var procGwNetwork = make(chan (bool), 1)
17
18 /*
19    libnetwork creates a bridge network "docker_gw_bridge" for providing
20    default gateway for the containers if none of the container's endpoints
21    have GW set by the driver. ICC is set to false for the GW_bridge network.
22
23    If a driver can't provide external connectivity it can choose to not set
24    the GW IP for the endpoint.
25
26    endpoint on the GW_bridge network is managed dynamically by libnetwork.
27    ie:
28    - its created when an endpoint without GW joins the container
29    - its deleted when an endpoint with GW joins the container
30 */
31
32 func (sb *sandbox) setupDefaultGW() error {
33
34         // check if the container already has a GW endpoint
35         if ep := sb.getEndpointInGWNetwork(); ep != nil {
36                 return nil
37         }
38
39         c := sb.controller
40
41         // Look for default gw network. In case of error (includes not found),
42         // retry and create it if needed in a serialized execution.
43         n, err := c.NetworkByName(libnGWNetwork)
44         if err != nil {
45                 if n, err = c.defaultGwNetwork(); err != nil {
46                         return err
47                 }
48         }
49
50         createOptions := []EndpointOption{CreateOptionAnonymous()}
51
52         eplen := gwEPlen
53         if len(sb.containerID) < gwEPlen {
54                 eplen = len(sb.containerID)
55         }
56
57         sbLabels := sb.Labels()
58
59         if sbLabels[netlabel.PortMap] != nil {
60                 createOptions = append(createOptions, CreateOptionPortMapping(sbLabels[netlabel.PortMap].([]types.PortBinding)))
61         }
62
63         if sbLabels[netlabel.ExposedPorts] != nil {
64                 createOptions = append(createOptions, CreateOptionExposedPorts(sbLabels[netlabel.ExposedPorts].([]types.TransportPort)))
65         }
66
67         epOption := getPlatformOption()
68         if epOption != nil {
69                 createOptions = append(createOptions, epOption)
70         }
71
72         newEp, err := n.CreateEndpoint("gateway_"+sb.containerID[0:eplen], createOptions...)
73         if err != nil {
74                 return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err)
75         }
76
77         defer func() {
78                 if err != nil {
79                         if err2 := newEp.Delete(true); err2 != nil {
80                                 logrus.Warnf("Failed to remove gw endpoint for container %s after failing to join the gateway network: %v",
81                                         sb.containerID, err2)
82                         }
83                 }
84         }()
85
86         epLocal := newEp.(*endpoint)
87
88         if err = epLocal.sbJoin(sb); err != nil {
89                 return fmt.Errorf("container %s: endpoint join on GW Network failed: %v", sb.containerID, err)
90         }
91
92         return nil
93 }
94
95 // If present, detach and remove the endpoint connecting the sandbox to the default gw network.
96 func (sb *sandbox) clearDefaultGW() error {
97         var ep *endpoint
98
99         if ep = sb.getEndpointInGWNetwork(); ep == nil {
100                 return nil
101         }
102         if err := ep.sbLeave(sb, false); err != nil {
103                 return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err)
104         }
105         if err := ep.Delete(false); err != nil {
106                 return fmt.Errorf("container %s: deleting endpoint on GW Network failed: %v", sb.containerID, err)
107         }
108         return nil
109 }
110
111 // Evaluate whether the sandbox requires a default gateway based
112 // on the endpoints to which it is connected. It does not account
113 // for the default gateway network endpoint.
114
115 func (sb *sandbox) needDefaultGW() bool {
116         var needGW bool
117
118         for _, ep := range sb.getConnectedEndpoints() {
119                 if ep.endpointInGWNetwork() {
120                         continue
121                 }
122                 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
123                         continue
124                 }
125                 if ep.getNetwork().Internal() {
126                         continue
127                 }
128                 // During stale sandbox cleanup, joinInfo may be nil
129                 if ep.joinInfo != nil && ep.joinInfo.disableGatewayService {
130                         continue
131                 }
132                 // TODO v6 needs to be handled.
133                 if len(ep.Gateway()) > 0 {
134                         return false
135                 }
136                 for _, r := range ep.StaticRoutes() {
137                         if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" {
138                                 return false
139                         }
140                 }
141                 needGW = true
142         }
143
144         return needGW
145 }
146
147 func (sb *sandbox) getEndpointInGWNetwork() *endpoint {
148         for _, ep := range sb.getConnectedEndpoints() {
149                 if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
150                         return ep
151                 }
152         }
153         return nil
154 }
155
156 func (ep *endpoint) endpointInGWNetwork() bool {
157         if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
158                 return true
159         }
160         return false
161 }
162
163 func (sb *sandbox) getEPwithoutGateway() *endpoint {
164         for _, ep := range sb.getConnectedEndpoints() {
165                 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
166                         continue
167                 }
168                 if len(ep.Gateway()) == 0 {
169                         return ep
170                 }
171         }
172         return nil
173 }
174
175 // Looks for the default gw network and creates it if not there.
176 // Parallel executions are serialized.
177 func (c *controller) defaultGwNetwork() (Network, error) {
178         procGwNetwork <- true
179         defer func() { <-procGwNetwork }()
180
181         n, err := c.NetworkByName(libnGWNetwork)
182         if err != nil {
183                 if _, ok := err.(types.NotFoundError); ok {
184                         n, err = c.createGWNetwork()
185                 }
186         }
187         return n, err
188 }
189
190 // Returns the endpoint which is providing external connectivity to the sandbox
191 func (sb *sandbox) getGatewayEndpoint() *endpoint {
192         for _, ep := range sb.getConnectedEndpoints() {
193                 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
194                         continue
195                 }
196                 if len(ep.Gateway()) != 0 {
197                         return ep
198                 }
199         }
200         return nil
201 }