func()

in common/core/network.go [95:238]


func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
	logrus.Debugf("[cni-net] Processing ADD command with args {ContainerID:%v Netns:%v IfName:%v Args:%v Path:%v}.",
		args.ContainerID, args.Netns, args.IfName, args.Args, args.Path)

	var err error
	var nwConfig *network.NetworkInfo

	podConfig, err := cni.ParseCniArgs(args.Args)
	k8sNamespace := ""
	if err == nil {
		k8sNamespace = string(podConfig.K8S_POD_NAMESPACE)
	}

	// Parse network configuration from stdin.
	cniConfig, err := cni.ParseNetworkConfig(args.StdinData)
	if err != nil {
		logrus.Errorf("[cni-net] Failed to parse network configuration, err:%v.", err)
		return err
	}

	logrus.Debugf("[cni-net] Read network configuration %+v.", cniConfig)

	if cniConfig.OptionalFlags.EnableDualStack == false {
		logrus.Infof("[cni-net] Dual stack is disabled")
	} else {
		logrus.Infof("[cni-net] Dual stack is enabled")
	}

	// Convert cniConfig to NetworkInfo
	// We don't set namespace, setting namespace is not valid for EP creation
	networkInfo, err := cniConfig.GetNetworkInfo(k8sNamespace)
	if err != nil {
		logrus.Errorf("[cni-net] Failed to get network information from network configuration, err:%v.", err)
		return err
	}
	epInfo, err := cniConfig.GetEndpointInfo(networkInfo, args.ContainerID, "")

	if err != nil {
		return err
	}

	epInfo.DualStack = cniConfig.OptionalFlags.EnableDualStack

	// Check for missing namespace
	if args.Netns == "" {
		logrus.Errorf("[cni-net] Missing Namespace, cannot add, endpoint : [%v].", epInfo)
		return errors.New("cannot create endpoint without a namespace")
	}

	if cniConfig.OptionalFlags.EnableDualStack == false {
		nwConfig, err = getOrCreateNetwork(plugin, networkInfo, cniConfig)
	} else {
		// The network must be created beforehand
		nwConfig, err = plugin.nm.GetNetworkByName(cniConfig.Name)

		if nwConfig.Type != network.L2Bridge {
			logrus.Errorf("[cni-net] Dual stack can only be specified with l2bridge network: [%v].", nwConfig.Type)
			return errors.New("Dual stack specified with non l2bridge network")	
		}
	}
	if err != nil {
		return err
	}

	hnsEndpoint, err := plugin.nm.GetEndpointByName(epInfo.Name, cniConfig.OptionalFlags.EnableDualStack)
	if hnsEndpoint != nil {
		logrus.Infof("[cni-net] Endpoint %+v already exists for network %v.", hnsEndpoint, nwConfig.ID)
		// Endpoint exists
		// Validate for duplication
		if hnsEndpoint.NetworkID == nwConfig.ID {
			// An endpoint already exists in the same network.
			// Do not allow creation of more endpoints on same network
			logrus.Debugf("[cni-net] Endpoint exists on same network, ignoring add : [%v].", epInfo)
			// Convert result to the requested CNI version.
			res := cni.GetCurrResult(nwConfig, hnsEndpoint, args.IfName, cniConfig)
			result, err := res.GetAsVersion(cniConfig.CniVersion)
			if err != nil {
				return err
			}

			result.Print()
			return nil
		}
	} else {
		logrus.Debugf("[cni-net] Creating a new Endpoint")
	}

	// If Ipam was provided, allocate a pool and obtain address
	if cniConfig.Ipam.Type != "" {
		err = allocateIpam(
			networkInfo,
			epInfo,
			cniConfig,
			cniConfig.OptionalFlags.ForceBridgeGateway,
			args.StdinData)
		if err != nil {
			// Error was logged by allocateIpam.
			return err
		}
		defer func() {
			if resultError != nil {
				logrus.Debugf("[cni-net] failure during ADD cleaning-up ipam, %v", err)
				os.Setenv("CNI_COMMAND", "DEL")
				err := deallocateIpam(cniConfig, args.StdinData)

				os.Setenv("CNI_COMMAND", "ADD")
				if err != nil {
					logrus.Debugf("[cni-net] failed during ADD command for clean-up delegate delete call, %v", err)
				}
			}
		}()
	}

	if cniConfig.OptionalFlags.GatewayFromAdditionalRoutes {
		logrus.Debugf("[cni-net] GatewayFromAdditionalRoutes set")
		addEndpointGatewaysFromConfig(epInfo, cniConfig)
	}

	// Apply the Network Policy for Endpoint
	epInfo.Policies = append(epInfo.Policies, networkInfo.Policies...)

	// If LoopbackDSR is set, add to policies
	if cniConfig.OptionalFlags.LoopbackDSR {
		hcnLoopbackRoute, _ := network.GetLoopbackDSRPolicy(&epInfo.IPAddress)
		epInfo.Policies = append(epInfo.Policies, hcnLoopbackRoute)
	}

	epInfo, err = plugin.nm.CreateEndpoint(nwConfig.ID, epInfo, args.Netns)
	if err != nil {
		logrus.Errorf("[cni-net] Failed to create endpoint, error : %v.", err)
		return err
	}

	// Convert result to the requested CNI version.
	res := cni.GetCurrResult(nwConfig, epInfo, args.IfName, cniConfig)
	result, err := res.GetAsVersion(cniConfig.CniVersion)
	if err != nil {
		return err
	}

	result.Print()
	logrus.Debugf("[cni-net] result: %+v", result)
	return nil
}