func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) {
	if container.HostConfig.NetworkMode.IsContainer() {
		return runconfig.ErrConflictSharedNetwork
	}

	if !containertypes.NetworkMode(idOrName).IsUserDefined() && hasUserDefinedIPAddress(endpointConfig) {
		return runconfig.ErrUnsupportedNetworkAndIP
	}

	if containertypes.NetworkMode(idOrName).IsBridge() &&
		daemon.configStore.DisableBridge {
		container.Config.NetworkDisabled = true
		return nil
	}

	controller := daemon.netController

	n, err := daemon.FindNetwork(idOrName)
	if err != nil {
		return err
	}

	if err := validateNetworkingConfig(n, endpointConfig); err != nil {
		return err
	}

	if updateSettings {
		if err := daemon.updateNetworkSettings(container, n); 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(); 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)
	}

	if err := ep.Join(sb); 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
}
Esempio n. 2
0
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, updateSettings bool) (err error) {
	if container.HostConfig.NetworkMode.IsContainer() {
		return runconfig.ErrConflictSharedNetwork
	}

	if runconfig.NetworkMode(idOrName).IsBridge() &&
		daemon.configStore.DisableBridge {
		container.Config.NetworkDisabled = true
		return nil
	}

	controller := daemon.netController

	n, err := daemon.FindNetwork(idOrName)
	if err != nil {
		return err
	}

	if updateSettings {
		if err := daemon.updateNetworkSettings(container, n); err != nil {
			return err
		}
	}

	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(); 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)
	}

	if err := ep.Join(sb); err != nil {
		return err
	}

	if err := container.UpdateJoinInfo(n, ep); err != nil {
		return derr.ErrorCodeJoinInfo.WithArgs(err)
	}

	return nil
}
Esempio n. 4
0
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
}
Esempio n. 5
0
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
}
Esempio n. 6
0
//对每一个网络进行加入。
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
}