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