github.com/noxiouz/docker@v0.7.3-0.20160629055221-3d231c78e8c5/daemon/network.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 8 "github.com/Sirupsen/logrus" 9 clustertypes "github.com/docker/docker/daemon/cluster/provider" 10 "github.com/docker/docker/errors" 11 "github.com/docker/docker/runconfig" 12 "github.com/docker/engine-api/types" 13 "github.com/docker/engine-api/types/network" 14 "github.com/docker/libnetwork" 15 networktypes "github.com/docker/libnetwork/types" 16 ) 17 18 // NetworkControllerEnabled checks if the networking stack is enabled. 19 // This feature depends on OS primitives and it's disabled in systems like Windows. 20 func (daemon *Daemon) NetworkControllerEnabled() bool { 21 return daemon.netController != nil 22 } 23 24 // FindNetwork function finds a network for a given string that can represent network name or id 25 func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) { 26 // Find by Name 27 n, err := daemon.GetNetworkByName(idName) 28 if err != nil && !isNoSuchNetworkError(err) { 29 return nil, err 30 } 31 32 if n != nil { 33 return n, nil 34 } 35 36 // Find by id 37 return daemon.GetNetworkByID(idName) 38 } 39 40 func isNoSuchNetworkError(err error) bool { 41 _, ok := err.(libnetwork.ErrNoSuchNetwork) 42 return ok 43 } 44 45 // GetNetworkByID function returns a network whose ID begins with the given prefix. 46 // It fails with an error if no matching, or more than one matching, networks are found. 47 func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) { 48 list := daemon.GetNetworksByID(partialID) 49 50 if len(list) == 0 { 51 return nil, libnetwork.ErrNoSuchNetwork(partialID) 52 } 53 if len(list) > 1 { 54 return nil, libnetwork.ErrInvalidID(partialID) 55 } 56 return list[0], nil 57 } 58 59 // GetNetworkByName function returns a network for a given network name. 60 func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) { 61 c := daemon.netController 62 if c == nil { 63 return nil, libnetwork.ErrNoSuchNetwork(name) 64 } 65 if name == "" { 66 name = c.Config().Daemon.DefaultNetwork 67 } 68 return c.NetworkByName(name) 69 } 70 71 // GetNetworksByID returns a list of networks whose ID partially matches zero or more networks 72 func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network { 73 c := daemon.netController 74 if c == nil { 75 return nil 76 } 77 list := []libnetwork.Network{} 78 l := func(nw libnetwork.Network) bool { 79 if strings.HasPrefix(nw.ID(), partialID) { 80 list = append(list, nw) 81 } 82 return false 83 } 84 c.WalkNetworks(l) 85 86 return list 87 } 88 89 // getAllNetworks returns a list containing all networks 90 func (daemon *Daemon) getAllNetworks() []libnetwork.Network { 91 c := daemon.netController 92 list := []libnetwork.Network{} 93 l := func(nw libnetwork.Network) bool { 94 list = append(list, nw) 95 return false 96 } 97 c.WalkNetworks(l) 98 99 return list 100 } 101 102 func isIngressNetwork(name string) bool { 103 return name == "ingress" 104 } 105 106 var ingressChan = make(chan struct{}, 1) 107 108 func ingressWait() func() { 109 ingressChan <- struct{}{} 110 return func() { <-ingressChan } 111 } 112 113 // SetupIngress setups ingress networking. 114 func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) error { 115 ip, _, err := net.ParseCIDR(nodeIP) 116 if err != nil { 117 return err 118 } 119 120 go func() { 121 controller := daemon.netController 122 controller.AgentInitWait() 123 124 if n, err := daemon.GetNetworkByName(create.Name); err == nil && n != nil && n.ID() != create.ID { 125 if err := controller.SandboxDestroy("ingress-sbox"); err != nil { 126 logrus.Errorf("Failed to delete stale ingress sandbox: %v", err) 127 return 128 } 129 130 if err := n.Delete(); err != nil { 131 logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err) 132 return 133 } 134 } 135 136 if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil { 137 // If it is any other error other than already 138 // exists error log error and return. 139 if _, ok := err.(libnetwork.NetworkNameError); !ok { 140 logrus.Errorf("Failed creating ingress network: %v", err) 141 return 142 } 143 144 // Otherwise continue down the call to create or recreate sandbox. 145 } 146 147 n, err := daemon.GetNetworkByID(create.ID) 148 if err != nil { 149 logrus.Errorf("Failed getting ingress network by id after creating: %v", err) 150 return 151 } 152 153 sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress()) 154 if err != nil { 155 logrus.Errorf("Failed creating ingress sandbox: %v", err) 156 return 157 } 158 159 ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil)) 160 if err != nil { 161 logrus.Errorf("Failed creating ingress endpoint: %v", err) 162 return 163 } 164 165 if err := ep.Join(sb, nil); err != nil { 166 logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err) 167 } 168 }() 169 170 return nil 171 } 172 173 // SetNetworkBootstrapKeys sets the bootstrap keys. 174 func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error { 175 return daemon.netController.SetKeys(keys) 176 } 177 178 // CreateManagedNetwork creates an agent network. 179 func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error { 180 _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true) 181 return err 182 } 183 184 // CreateNetwork creates a network with the given name, driver and other optional parameters 185 func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) { 186 resp, err := daemon.createNetwork(create, "", false) 187 if err != nil { 188 return nil, err 189 } 190 return resp, err 191 } 192 193 func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) { 194 // If there is a pending ingress network creation wait here 195 // since ingress network creation can happen via node download 196 // from manager or task download. 197 if isIngressNetwork(create.Name) { 198 defer ingressWait()() 199 } 200 201 if runconfig.IsPreDefinedNetwork(create.Name) && !agent { 202 err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name) 203 return nil, errors.NewRequestForbiddenError(err) 204 } 205 206 var warning string 207 nw, err := daemon.GetNetworkByName(create.Name) 208 if err != nil { 209 if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { 210 return nil, err 211 } 212 } 213 if nw != nil { 214 if create.CheckDuplicate { 215 return nil, libnetwork.NetworkNameError(create.Name) 216 } 217 warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID()) 218 } 219 220 c := daemon.netController 221 driver := create.Driver 222 if driver == "" { 223 driver = c.Config().Daemon.DefaultDriver 224 } 225 226 ipam := create.IPAM 227 v4Conf, v6Conf, err := getIpamConfig(ipam.Config) 228 if err != nil { 229 return nil, err 230 } 231 232 nwOptions := []libnetwork.NetworkOption{ 233 libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options), 234 libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6), 235 libnetwork.NetworkOptionDriverOpts(create.Options), 236 libnetwork.NetworkOptionLabels(create.Labels), 237 } 238 if create.Internal { 239 nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork()) 240 } 241 if agent { 242 nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic()) 243 nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false)) 244 } 245 246 if isIngressNetwork(create.Name) { 247 nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress()) 248 } 249 250 n, err := c.NewNetwork(driver, create.Name, id, nwOptions...) 251 if err != nil { 252 return nil, err 253 } 254 255 daemon.LogNetworkEvent(n, "create") 256 return &types.NetworkCreateResponse{ 257 ID: n.ID(), 258 Warning: warning, 259 }, nil 260 } 261 262 func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) { 263 ipamV4Cfg := []*libnetwork.IpamConf{} 264 ipamV6Cfg := []*libnetwork.IpamConf{} 265 for _, d := range data { 266 iCfg := libnetwork.IpamConf{} 267 iCfg.PreferredPool = d.Subnet 268 iCfg.SubPool = d.IPRange 269 iCfg.Gateway = d.Gateway 270 iCfg.AuxAddresses = d.AuxAddress 271 ip, _, err := net.ParseCIDR(d.Subnet) 272 if err != nil { 273 return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err) 274 } 275 if ip.To4() != nil { 276 ipamV4Cfg = append(ipamV4Cfg, &iCfg) 277 } else { 278 ipamV6Cfg = append(ipamV6Cfg, &iCfg) 279 } 280 } 281 return ipamV4Cfg, ipamV6Cfg, nil 282 } 283 284 // UpdateContainerServiceConfig updates a service configuration. 285 func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error { 286 container, err := daemon.GetContainer(containerName) 287 if err != nil { 288 return err 289 } 290 291 container.NetworkSettings.Service = serviceConfig 292 return nil 293 } 294 295 // ConnectContainerToNetwork connects the given container to the given 296 // network. If either cannot be found, an err is returned. If the 297 // network cannot be set up, an err is returned. 298 func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error { 299 container, err := daemon.GetContainer(containerName) 300 if err != nil { 301 return err 302 } 303 return daemon.ConnectToNetwork(container, networkName, endpointConfig) 304 } 305 306 // DisconnectContainerFromNetwork disconnects the given container from 307 // the given network. If either cannot be found, an err is returned. 308 func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error { 309 container, err := daemon.GetContainer(containerName) 310 if err != nil { 311 if force { 312 return daemon.ForceEndpointDelete(containerName, network) 313 } 314 return err 315 } 316 return daemon.DisconnectFromNetwork(container, network, force) 317 } 318 319 // GetNetworkDriverList returns the list of plugins drivers 320 // registered for network. 321 func (daemon *Daemon) GetNetworkDriverList() map[string]bool { 322 pluginList := make(map[string]bool) 323 324 if !daemon.NetworkControllerEnabled() { 325 return nil 326 } 327 c := daemon.netController 328 networks := c.Networks() 329 330 for _, network := range networks { 331 driver := network.Type() 332 pluginList[driver] = true 333 } 334 // TODO : Replace this with proper libnetwork API 335 pluginList["overlay"] = true 336 337 return pluginList 338 } 339 340 // DeleteManagedNetwork deletes an agent network. 341 func (daemon *Daemon) DeleteManagedNetwork(networkID string) error { 342 return daemon.deleteNetwork(networkID, true) 343 } 344 345 // DeleteNetwork destroys a network unless it's one of docker's predefined networks. 346 func (daemon *Daemon) DeleteNetwork(networkID string) error { 347 return daemon.deleteNetwork(networkID, false) 348 } 349 350 func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error { 351 nw, err := daemon.FindNetwork(networkID) 352 if err != nil { 353 return err 354 } 355 356 if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic { 357 err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name()) 358 return errors.NewRequestForbiddenError(err) 359 } 360 361 if err := nw.Delete(); err != nil { 362 return err 363 } 364 daemon.LogNetworkEvent(nw, "destroy") 365 return nil 366 } 367 368 // GetNetworks returns a list of all networks 369 func (daemon *Daemon) GetNetworks() []libnetwork.Network { 370 return daemon.getAllNetworks() 371 }