github.com/portworx/docker@v1.12.1/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 // Cleanup any stale endpoints that might be left over during previous iterations 131 epList := n.Endpoints() 132 for _, ep := range epList { 133 if err := ep.Delete(true); err != nil { 134 logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err) 135 } 136 } 137 138 if err := n.Delete(); err != nil { 139 logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err) 140 return 141 } 142 } 143 144 if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil { 145 // If it is any other error other than already 146 // exists error log error and return. 147 if _, ok := err.(libnetwork.NetworkNameError); !ok { 148 logrus.Errorf("Failed creating ingress network: %v", err) 149 return 150 } 151 152 // Otherwise continue down the call to create or recreate sandbox. 153 } 154 155 n, err := daemon.GetNetworkByID(create.ID) 156 if err != nil { 157 logrus.Errorf("Failed getting ingress network by id after creating: %v", err) 158 return 159 } 160 161 sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress()) 162 if err != nil { 163 if _, ok := err.(networktypes.ForbiddenError); !ok { 164 logrus.Errorf("Failed creating ingress sandbox: %v", err) 165 } 166 return 167 } 168 169 ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil)) 170 if err != nil { 171 logrus.Errorf("Failed creating ingress endpoint: %v", err) 172 return 173 } 174 175 if err := ep.Join(sb, nil); err != nil { 176 logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err) 177 } 178 }() 179 180 return nil 181 } 182 183 // SetNetworkBootstrapKeys sets the bootstrap keys. 184 func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error { 185 return daemon.netController.SetKeys(keys) 186 } 187 188 // CreateManagedNetwork creates an agent network. 189 func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error { 190 _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true) 191 return err 192 } 193 194 // CreateNetwork creates a network with the given name, driver and other optional parameters 195 func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) { 196 resp, err := daemon.createNetwork(create, "", false) 197 if err != nil { 198 return nil, err 199 } 200 return resp, err 201 } 202 203 func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) { 204 // If there is a pending ingress network creation wait here 205 // since ingress network creation can happen via node download 206 // from manager or task download. 207 if isIngressNetwork(create.Name) { 208 defer ingressWait()() 209 } 210 211 if runconfig.IsPreDefinedNetwork(create.Name) && !agent { 212 err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name) 213 return nil, errors.NewRequestForbiddenError(err) 214 } 215 216 var warning string 217 nw, err := daemon.GetNetworkByName(create.Name) 218 if err != nil { 219 if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { 220 return nil, err 221 } 222 } 223 if nw != nil { 224 if create.CheckDuplicate { 225 return nil, libnetwork.NetworkNameError(create.Name) 226 } 227 warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID()) 228 } 229 230 c := daemon.netController 231 driver := create.Driver 232 if driver == "" { 233 driver = c.Config().Daemon.DefaultDriver 234 } 235 236 ipam := create.IPAM 237 v4Conf, v6Conf, err := getIpamConfig(ipam.Config) 238 if err != nil { 239 return nil, err 240 } 241 242 nwOptions := []libnetwork.NetworkOption{ 243 libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options), 244 libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6), 245 libnetwork.NetworkOptionDriverOpts(create.Options), 246 libnetwork.NetworkOptionLabels(create.Labels), 247 } 248 if create.Internal { 249 nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork()) 250 } 251 if agent { 252 nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic()) 253 nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false)) 254 } 255 256 if isIngressNetwork(create.Name) { 257 nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress()) 258 } 259 260 n, err := c.NewNetwork(driver, create.Name, id, nwOptions...) 261 if err != nil { 262 return nil, err 263 } 264 265 daemon.LogNetworkEvent(n, "create") 266 return &types.NetworkCreateResponse{ 267 ID: n.ID(), 268 Warning: warning, 269 }, nil 270 } 271 272 func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) { 273 ipamV4Cfg := []*libnetwork.IpamConf{} 274 ipamV6Cfg := []*libnetwork.IpamConf{} 275 for _, d := range data { 276 iCfg := libnetwork.IpamConf{} 277 iCfg.PreferredPool = d.Subnet 278 iCfg.SubPool = d.IPRange 279 iCfg.Gateway = d.Gateway 280 iCfg.AuxAddresses = d.AuxAddress 281 ip, _, err := net.ParseCIDR(d.Subnet) 282 if err != nil { 283 return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err) 284 } 285 if ip.To4() != nil { 286 ipamV4Cfg = append(ipamV4Cfg, &iCfg) 287 } else { 288 ipamV6Cfg = append(ipamV6Cfg, &iCfg) 289 } 290 } 291 return ipamV4Cfg, ipamV6Cfg, nil 292 } 293 294 // UpdateContainerServiceConfig updates a service configuration. 295 func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error { 296 container, err := daemon.GetContainer(containerName) 297 if err != nil { 298 return err 299 } 300 301 container.NetworkSettings.Service = serviceConfig 302 return nil 303 } 304 305 // ConnectContainerToNetwork connects the given container to the given 306 // network. If either cannot be found, an err is returned. If the 307 // network cannot be set up, an err is returned. 308 func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error { 309 container, err := daemon.GetContainer(containerName) 310 if err != nil { 311 return err 312 } 313 return daemon.ConnectToNetwork(container, networkName, endpointConfig) 314 } 315 316 // DisconnectContainerFromNetwork disconnects the given container from 317 // the given network. If either cannot be found, an err is returned. 318 func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error { 319 container, err := daemon.GetContainer(containerName) 320 if err != nil { 321 if force { 322 return daemon.ForceEndpointDelete(containerName, network) 323 } 324 return err 325 } 326 return daemon.DisconnectFromNetwork(container, network, force) 327 } 328 329 // GetNetworkDriverList returns the list of plugins drivers 330 // registered for network. 331 func (daemon *Daemon) GetNetworkDriverList() map[string]bool { 332 pluginList := make(map[string]bool) 333 334 if !daemon.NetworkControllerEnabled() { 335 return nil 336 } 337 c := daemon.netController 338 networks := c.Networks() 339 340 for _, network := range networks { 341 driver := network.Type() 342 pluginList[driver] = true 343 } 344 // TODO : Replace this with proper libnetwork API 345 pluginList["overlay"] = true 346 347 return pluginList 348 } 349 350 // DeleteManagedNetwork deletes an agent network. 351 func (daemon *Daemon) DeleteManagedNetwork(networkID string) error { 352 return daemon.deleteNetwork(networkID, true) 353 } 354 355 // DeleteNetwork destroys a network unless it's one of docker's predefined networks. 356 func (daemon *Daemon) DeleteNetwork(networkID string) error { 357 return daemon.deleteNetwork(networkID, false) 358 } 359 360 func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error { 361 nw, err := daemon.FindNetwork(networkID) 362 if err != nil { 363 return err 364 } 365 366 if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic { 367 err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name()) 368 return errors.NewRequestForbiddenError(err) 369 } 370 371 if err := nw.Delete(); err != nil { 372 return err 373 } 374 daemon.LogNetworkEvent(nw, "destroy") 375 return nil 376 } 377 378 // GetNetworks returns a list of all networks 379 func (daemon *Daemon) GetNetworks() []libnetwork.Network { 380 return daemon.getAllNetworks() 381 }