func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { // TODO Windows: Remove this once TP4 builds are not supported // Windows TP4 build don't support libnetwork and in that case // daemon.netController will be nil if daemon.netController == nil { return nil } n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings) if err != nil { return err } if n == nil { return nil } controller := daemon.netController sb := daemon.getNetworkSandbox(container) createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb) if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") ep, err := n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } defer func() { if err != nil { if e := ep.Delete(false); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } }() if endpointConfig != nil { container.NetworkSettings.Networks[n.Name()] = endpointConfig } if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } if sb == nil { options, err := daemon.buildSandboxOptions(container, n) if err != nil { return err } sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } container.UpdateSandboxNetworkSettings(sb) } joinOptions, err := container.BuildJoinOptions(n) if err != nil { return err } if err := ep.Join(sb, joinOptions...); err != nil { return err } if err := container.UpdateJoinInfo(n, ep); err != nil { return fmt.Errorf("Updating join info failed: %v", err) } daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) return nil }
func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings) if err != nil { return err } if n == nil { return nil } controller := daemon.netController sb := daemon.getNetworkSandbox(container) createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb) if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") ep, err := n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } defer func() { if err != nil { if e := ep.Delete(false); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } }() if endpointConfig != nil { container.NetworkSettings.Networks[n.Name()] = endpointConfig } if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } if sb == nil { options, err := daemon.buildSandboxOptions(container, n) if err != nil { return err } sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } container.UpdateSandboxNetworkSettings(sb) } joinOptions, err := container.BuildJoinOptions(n) if err != nil { return err } if err := ep.Join(sb, joinOptions...); err != nil { return err } if err := container.UpdateJoinInfo(n, ep); err != nil { return derr.ErrorCodeJoinInfo.WithArgs(err) } daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) return nil }
func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { start := time.Now() if container.HostConfig.NetworkMode.IsContainer() { return runconfig.ErrConflictSharedNetwork } if containertypes.NetworkMode(idOrName).IsBridge() && daemon.configStore.DisableBridge { container.Config.NetworkDisabled = true return nil } if endpointConfig == nil { endpointConfig = &networktypes.EndpointSettings{} } n, config, err := daemon.findAndAttachNetwork(container, idOrName, endpointConfig) if err != nil { return err } if n == nil { return nil } var operIPAM bool if config != nil { if epConfig, ok := config.EndpointsConfig[n.Name()]; ok { if endpointConfig.IPAMConfig == nil || (endpointConfig.IPAMConfig.IPv4Address == "" && endpointConfig.IPAMConfig.IPv6Address == "" && len(endpointConfig.IPAMConfig.LinkLocalIPs) == 0) { operIPAM = true } // copy IPAMConfig and NetworkID from epConfig via AttachNetwork endpointConfig.IPAMConfig = epConfig.IPAMConfig endpointConfig.NetworkID = epConfig.NetworkID } } err = daemon.updateNetworkConfig(container, n, endpointConfig, updateSettings) if err != nil { return err } controller := daemon.netController sb := daemon.getNetworkSandbox(container) createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb, daemon.configStore.DNS) if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") ep, err := n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } defer func() { if err != nil { if e := ep.Delete(false); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } }() container.NetworkSettings.Networks[n.Name()] = &network.EndpointSettings{ EndpointSettings: endpointConfig, IPAMOperational: operIPAM, } if _, ok := container.NetworkSettings.Networks[n.ID()]; ok { delete(container.NetworkSettings.Networks, n.ID()) } if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } if sb == nil { options, err := daemon.buildSandboxOptions(container) if err != nil { return err } sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } container.UpdateSandboxNetworkSettings(sb) } joinOptions, err := container.BuildJoinOptions(n) if err != nil { return err } if err := ep.Join(sb, joinOptions...); err != nil { return err } if err := container.UpdateJoinInfo(n, ep); err != nil { return fmt.Errorf("Updating join info failed: %v", err) } container.NetworkSettings.Ports = getPortMapInfo(sb) daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) networkActions.WithValues("connect").UpdateSince(start) return nil }
func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { n, err := daemon.updateNetworkConfig(container, idOrName, updateSettings) if err != nil { return err } if n == nil { return nil } if !containertypes.NetworkMode(idOrName).IsUserDefined() && hasUserDefinedIPAddress(endpointConfig) { return runconfig.ErrUnsupportedNetworkAndIP } controller := daemon.netController if err := validateNetworkingConfig(n, endpointConfig); err != nil { return err } if endpointConfig != nil { container.NetworkSettings.Networks[n.Name()] = endpointConfig } ep, err := container.GetEndpointInNetwork(n) if err == nil { return fmt.Errorf("Conflict. A container with name %q is already connected to network %s.", strings.TrimPrefix(container.Name, "/"), idOrName) } if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok { return err } createOptions, err := container.BuildCreateEndpointOptions(n) if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") ep, err = n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } defer func() { if err != nil { if e := ep.Delete(false); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } }() if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } sb := daemon.getNetworkSandbox(container) if sb == nil { options, err := daemon.buildSandboxOptions(container, n) if err != nil { return err } sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } container.UpdateSandboxNetworkSettings(sb) } joinOptions, err := container.BuildJoinOptions(n) if err != nil { return err } if err := ep.Join(sb, joinOptions...); err != nil { return err } if err := container.UpdateJoinInfo(n, ep); err != nil { return derr.ErrorCodeJoinInfo.WithArgs(err) } daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) return nil }
//对每一个网络进行加入。 func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) { // TODO Windows: Remove this once TP4 builds are not supported // Windows TP4 build don't support libnetwork and in that case // daemon.netController will be nil if daemon.netController == nil { return nil } //这一步就更新容器的网路配置了吗?应该还没有吧。 //返回的是network对象。 n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings) if err != nil { return err } if n == nil { return nil } controller := daemon.netController //获取容器的sandbox。sandbox是一个这样的结构: /* type sandbox struct { id string containerID string config containerConfig extDNS []string osSbox osl.Sandbox controller *controller resolver Resolver resolverOnce sync.Once refCnt int endpoints epHeap epPriority map[string]int joinLeaveDone chan struct{} dbIndex uint64 dbExists bool isStub bool inDelete bool sync.Mutex } */ //创建沙盒? sb := daemon.getNetworkSandbox(container) //貌似在这一步就会创建容器相应的IP地址等信息了。 createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb) if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") //调用Plugin的CreateEndpoint方法创建endpoint。 //这里的n是一个Network接口。network的createEndpoint会调用addEndpoint方法, //addEndpoint方法会调用具体的driver,比如bridge driver的createEndpoint方法。 //在宿主机上真实的创建endpoint。同时,这个endpoint是和network关联的,比如说 //bridge模式下,创建endpoint就是创建veth设备,并且在这一步骤里面,veth设备的 //一端就已经连接到了bridge上。 ep, err := n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } defer func() { if err != nil { if e := ep.Delete(false); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } }() //更新容器的endpoint配置。 if endpointConfig != nil { container.NetworkSettings.Networks[n.Name()] = endpointConfig } //这个是要更新谁? if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } //什么情况下sb会是空的? if sb == nil { options, err := daemon.buildSandboxOptions(container, n) if err != nil { return err } //创建新的沙盒。 sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } container.UpdateSandboxNetworkSettings(sb) } //? joinOptions, err := container.BuildJoinOptions(n) if err != nil { return err } //将沙盒和endpoint连接起来。每一个沙盒对应一个容器。 if err := ep.Join(sb, joinOptions...); err != nil { return err } if err := container.UpdateJoinInfo(n, ep); err != nil { return fmt.Errorf("Updating join info failed: %v", err) } //更新容器的ports信息。 container.NetworkSettings.Ports = getPortMapInfo(sb) daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID}) return nil }