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