func cmdAdd(args *skel.CmdArgs) error { tuningConf := TuningConf{} if err := json.Unmarshal(args.StdinData, &tuningConf); err != nil { return fmt.Errorf("failed to load netconf: %v", err) } // The directory /proc/sys/net is per network namespace. Enter in the // network namespace before writing on it. err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error { for key, value := range tuningConf.SysCtl { fileName := filepath.Join("/proc/sys", strings.Replace(key, ".", "/", -1)) fileName = filepath.Clean(fileName) // Refuse to modify sysctl parameters that don't belong // to the network subsystem. if !strings.HasPrefix(fileName, "/proc/sys/net/") { return fmt.Errorf("invalid net sysctl key: %q", key) } content := []byte(value) err := ioutil.WriteFile(fileName, content, 0644) if err != nil { return err } } return nil }) if err != nil { return err } result := types.Result{} return result.Print() }
func cmdAdd(args *skel.CmdArgs) error { result := types.Result{} if err := rpcCall("DHCP.Allocate", args, &result); err != nil { return err } return result.Print() }
func createCNIReply(ipamConf *ipam.IPAMRep) error { v6Routes := []cniTypes.Route{} v4Routes := []cniTypes.Route{} for _, r := range ipamConf.IP6.Routes { newRoute := cniTypes.Route{ Dst: r.Destination, } if r.NextHop != nil { newRoute.GW = r.NextHop } v6Routes = append(v6Routes, newRoute) } r := cniTypes.Result{ IP6: &cniTypes.IPConfig{ IP: ipamConf.IP6.IP, Gateway: ipamConf.IP6.Gateway, Routes: v6Routes, }, } if ipamConf.IP4 != nil { for _, r := range ipamConf.IP4.Routes { newRoute := cniTypes.Route{ Dst: r.Destination, } if r.NextHop != nil { newRoute.GW = r.NextHop } v4Routes = append(v4Routes, newRoute) } r.IP4 = &cniTypes.IPConfig{ IP: ipamConf.IP4.IP, Gateway: ipamConf.IP4.Gateway, Routes: v4Routes, } } return r.Print() }
func cmdAdd(args *skel.CmdArgs) error { args.IfName = "lo" // ignore config, this only works for loopback err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error { link, err := netlink.LinkByName(args.IfName) if err != nil { return err // not tested } err = netlink.LinkSetUp(link) if err != nil { return err // not tested } return nil }) if err != nil { return err // not tested } result := types.Result{} return result.Print() }
func cmdAdd(args *skel.CmdArgs) error { // Unmarshall the network config, and perform validation conf := NetConf{} if err := json.Unmarshal(args.StdinData, &conf); err != nil { return fmt.Errorf("failed to load netconf: %v", err) } ConfigureLogging(conf.LogLevel) workload, orchestrator, err := GetIdentifiers(args) if err != nil { return err } logger := CreateContextLogger(workload) // Allow the hostname to be overridden by the network config if conf.Hostname != "" { hostname = conf.Hostname } logger.WithFields(log.Fields{ "Orchestrator": orchestrator, "Node": hostname, }).Info("Extracted identifiers") logger.WithFields(log.Fields{"NetConfg": conf}).Info("Loaded CNI NetConf") calicoClient, err := CreateClient(conf) if err != nil { return err } // Always check if there's an existing endpoint. endpoints, err := calicoClient.WorkloadEndpoints().List(api.WorkloadEndpointMetadata{ Node: hostname, Orchestrator: orchestrator, Workload: workload}) if err != nil { return err } logger.Debugf("Retrieved endpoints: %v", endpoints) var endpoint *api.WorkloadEndpoint if len(endpoints.Items) == 1 { endpoint = &endpoints.Items[0] } fmt.Fprintf(os.Stderr, "Calico CNI checking for existing endpoint: %v\n", endpoint) // Collect the result in this variable - this is ultimately what gets "returned" by this function by printing // it to stdout. var result *types.Result // If running under Kubernetes then branch off into the kubernetes code, otherwise handle everything in this // function. if orchestrator == "k8s" { if result, err = k8s.CmdAddK8s(args, conf, hostname, calicoClient, endpoint); err != nil { return err } } else { // Default CNI behavior - use the CNI network name as the Calico profile. profileID := conf.Name if endpoint != nil { // There is an existing endpoint - no need to create another. // This occurs when adding an existing container to a new CNI network // Find the IP address from the endpoint and use that in the response. // Don't create the veth or do any networking. // Just update the profile on the endpoint. The profile will be created if needed during the // profile processing step. fmt.Fprintf(os.Stderr, "Calico CNI appending profile: %s\n", profileID) endpoint.Spec.Profiles = append(endpoint.Spec.Profiles, profileID) result, err = CreateResultFromEndpoint(endpoint) logger.WithField("result", result).Debug("Created result from endpoint") if err != nil { return err } } else { // There's no existing endpoint, so we need to do the following: // 1) Call the configured IPAM plugin to get IP address(es) // 2) Configure the Calico endpoint // 3) Create the veth, configuring it on both the host and container namespace. // 1) Run the IPAM plugin and make sure there's an IP address returned. logger.WithFields(log.Fields{"paths": os.Getenv("CNI_PATH"), "type": conf.IPAM.Type}).Debug("Looking for IPAM plugin in paths") result, err = ipam.ExecAdd(conf.IPAM.Type, args.StdinData) logger.WithField("result", result).Info("Got result from IPAM plugin") if err != nil { return err } // Parse endpoint labels passed in by Mesos, and store in a map. labels := map[string]string{} for _, label := range conf.Args.Mesos.NetworkInfo.Labels.Labels { labels[label.Key] = label.Value } // 2) Create the endpoint object endpoint = api.NewWorkloadEndpoint() endpoint.Metadata.Name = args.IfName endpoint.Metadata.Node = hostname endpoint.Metadata.Orchestrator = orchestrator endpoint.Metadata.Workload = workload endpoint.Metadata.Labels = labels endpoint.Spec.Profiles = []string{profileID} logger.WithField("endpoint", endpoint).Debug("Populated endpoint (without nets)") if err = PopulateEndpointNets(endpoint, result); err != nil { // Cleanup IP allocation and return the error. ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData) return err } logger.WithField("endpoint", endpoint).Info("Populated endpoint (with nets)") fmt.Fprintf(os.Stderr, "Calico CNI using IPs: %s\n", endpoint.Spec.IPNetworks) // 3) Set up the veth hostVethName, contVethMac, err := DoNetworking(args, conf, result, logger, "") if err != nil { // Cleanup IP allocation and return the error. ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData) return err } logger.WithFields(log.Fields{ "HostVethName": hostVethName, "ContainerVethMac": contVethMac, }).Info("Networked namespace") mac, err := net.ParseMAC(contVethMac) if err != nil { // Cleanup IP allocation and return the error. ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData) return err } endpoint.Spec.MAC = &cnet.MAC{HardwareAddr: mac} endpoint.Spec.InterfaceName = hostVethName } // Write the endpoint object (either the newly created one, or the updated one with a new ProfileIDs). if _, err := calicoClient.WorkloadEndpoints().Apply(endpoint); err != nil { // Cleanup IP allocation and return the error. ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData) return err } logger.WithField("endpoint", endpoint).Info("Wrote endpoint to datastore") } // Handle profile creation - this is only done if there isn't a specific policy handler. if conf.Policy.PolicyType == "" { logger.Debug("Handling profiles") // Start by checking if the profile already exists. If it already exists then there is no work to do. // The CNI plugin never updates a profile. exists := true _, err = calicoClient.Profiles().Get(api.ProfileMetadata{Name: conf.Name}) if err != nil { _, ok := err.(errors.ErrorResourceDoesNotExist) if ok { exists = false } else { // Cleanup IP allocation and return the error. ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData) return err } } if !exists { // The profile doesn't exist so needs to be created. The rules vary depending on whether k8s is being used. // Under k8s (without full policy support) the rule is permissive and allows all traffic. // Otherwise, incoming traffic is only allowed from profiles with the same tag. fmt.Fprintf(os.Stderr, "Calico CNI creating profile: %s\n", conf.Name) var inboundRules []api.Rule if orchestrator == "k8s" { inboundRules = []api.Rule{{Action: "allow"}} } else { inboundRules = []api.Rule{{Action: "allow", Source: api.EntityRule{Tag: conf.Name}}} } profile := &api.Profile{ Metadata: api.ProfileMetadata{ Name: conf.Name, Tags: []string{conf.Name}, }, Spec: api.ProfileSpec{ EgressRules: []api.Rule{{Action: "allow"}}, IngressRules: inboundRules, }, } logger.WithField("profile", profile).Info("Creating profile") if _, err := calicoClient.Profiles().Create(profile); err != nil { // Cleanup IP allocation and return the error. ReleaseIPAllocation(logger, conf.IPAM.Type, args.StdinData) return err } } } return result.Print() }