Example #1
0
func (driver *driver) joinEndpoint(w http.ResponseWriter, r *http.Request) {
	var (
		j   api.JoinRequest
		err error
	)
	if err := json.NewDecoder(r.Body).Decode(&j); err != nil {
		sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
		return
	}
	log.Debugf("Join request: %+v", &j)

	ep, err := driver.client.EndpointGetByDockerEPID(j.EndpointID)
	if err != nil {
		sendError(w, fmt.Sprintf("Error retrieving endpoint %s", err), http.StatusBadRequest)
		return
	}
	if ep == nil {
		sendError(w, "Endpoint does not exist", http.StatusBadRequest)
		return
	}

	veth, _, tmpIfName, err := plugins.SetupVeth(j.EndpointID, 1450, ep)
	if err != nil {
		sendError(w, "Error while setting up veth pair: "+err.Error(), http.StatusBadRequest)
		return
	}
	defer func() {
		if err != nil {
			if err = netlink.LinkDel(veth); err != nil {
				log.Warningf("failed to clean up veth %q: %s", veth.Name, err)
			}
		}
	}()

	ifname := &api.InterfaceName{
		SrcName:   tmpIfName,
		DstPrefix: ContainerInterfacePrefix,
	}
	if err = driver.client.EndpointJoin(*ep); err != nil {
		log.Errorf("Joining endpoint failed: %s", err)
		sendError(w, "Unable to create BPF map: "+err.Error(), http.StatusInternalServerError)
	}

	rep, err := driver.client.GetIPAMConf(ipam.LibnetworkIPAMType, ipam.IPAMReq{})
	if err != nil {
		sendError(w, fmt.Sprintf("Could not get cilium IPAM configuration: %s", err), http.StatusBadRequest)
	}

	lnRoutes := []api.StaticRoute{}
	for _, route := range rep.IPAMConfig.IP6.Routes {
		nh := ""
		if route.IsL3() {
			nh = route.NextHop.String()
		}
		lnRoute := api.StaticRoute{
			Destination: route.Destination.String(),
			RouteType:   route.Type,
			NextHop:     nh,
		}
		lnRoutes = append(lnRoutes, lnRoute)
	}
	if rep.IPAMConfig.IP4 != nil {
		for _, route := range rep.IPAMConfig.IP4.Routes {
			nh := ""
			if route.IsL3() {
				nh = route.NextHop.String()
			}
			lnRoute := api.StaticRoute{
				Destination: route.Destination.String(),
				RouteType:   route.Type,
				NextHop:     nh,
			}
			lnRoutes = append(lnRoutes, lnRoute)
		}
	}

	res := &api.JoinResponse{
		GatewayIPv6:           rep.IPAMConfig.IP6.Gateway.String(),
		InterfaceName:         ifname,
		StaticRoutes:          lnRoutes,
		DisableGatewayService: true,
	}

	// FIXME? Having the following code results on a runtime error: docker: Error
	// response from daemon: oci runtime error: process_linux.go:334: running prestart
	// hook 0 caused "exit status 1: time=\"2016-10-26T06:33:17-07:00\" level=fatal
	// msg=\"failed to set gateway while updating gateway: file exists\" \n"
	//
	// If empty, it works as expected without docker runtime errors
	// if rep.IPAMConfig.IP4 != nil {
	//	res.Gateway = rep.IPAMConfig.IP4.Gateway.String()
	// }
	log.Debugf("Join response: %+v", res)
	objectResponse(w, res)
}
Example #2
0
func cmdAdd(args *skel.CmdArgs) error {
	n, err := loadNetConf(args.StdinData)
	if err != nil {
		return err
	}

	log.Debugf("Args %s", args)

	c, err := cnc.NewDefaultClient()
	if err != nil {
		return fmt.Errorf("error while starting cilium-client: %s", err)
	}

	netNs, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %s", args.Netns, err)
	}
	defer netNs.Close()

	if err := removeIfFromNSIfExists(netNs, args.IfName); err != nil {
		return fmt.Errorf("failed removing interface %q from namespace %q: %s",
			args.IfName, args.Netns, err)
	}

	var ep endpoint.Endpoint
	veth, peer, tmpIfName, err := plugins.SetupVeth(args.ContainerID, n.MTU, &ep)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			if err = netlink.LinkDel(veth); err != nil {
				log.Warningf("failed to clean up veth %q: %s", veth.Name, err)
			}
		}
	}()

	if err = netlink.LinkSetNsFd(*peer, int(netNs.Fd())); err != nil {
		return fmt.Errorf("unable to move veth pair %q to netns: %s", peer, err)
	}

	err = netNs.Do(func(_ ns.NetNS) error {
		err := renameLink(tmpIfName, args.IfName)
		if err != nil {
			return fmt.Errorf("failed to rename %q to %q: %s", tmpIfName, args.IfName, err)
		}
		return nil
	})

	req := ipam.IPAMReq{}
	ipamConf, err := c.AllocateIP(ipam.CNIIPAMType, req)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil && ipamConf != nil {
			if ipamConf.IP6 != nil {
				req := ipam.IPAMReq{IP: &ipamConf.IP6.IP.IP}
				if err = c.ReleaseIP(ipam.CNIIPAMType, req); err != nil {
					log.Warningf("failed to release allocated IPv6 of container ID %q: %s", args.ContainerID, err)
				}
			}
			if ipamConf.IP4 != nil {
				req := ipam.IPAMReq{IP: &ipamConf.IP4.IP.IP}
				if err = c.ReleaseIP(ipam.CNIIPAMType, req); err != nil {
					log.Warningf("failed to release allocated IPv4 of container ID %q: %s", args.ContainerID, err)
				}
			}
		}
	}()

	if err = netNs.Do(func(_ ns.NetNS) error {
		return configureIface(args.IfName, ipamConf)
	}); err != nil {
		return err
	}

	ep.IPv6 = addressing.DeriveCiliumIPv6(ipamConf.IP6.IP.IP)
	if ipamConf.IP4 != nil {
		ep.IPv4 = addressing.DeriveCiliumIPv4(ipamConf.IP4.IP.IP)
	}
	ep.NodeIP = ipamConf.IP6.Gateway
	ep.DockerID = args.ContainerID
	ep.SetID()
	if err = c.EndpointJoin(ep); err != nil {
		return fmt.Errorf("unable to create eBPF map: %s", err)
	}

	return createCNIReply(ipamConf)
}