func (driver *driver) createEndpoint(w http.ResponseWriter, r *http.Request) { var create CreateEndpointRequest if err := json.NewDecoder(r.Body).Decode(&create); err != nil { sendError(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) return } log.Debugf("Create endpoint request: %+v", &create) endID := create.EndpointID ipv6Address := create.Interface.AddressIPv6 ipv4Address := create.Interface.Address if ipv4Address == "" { log.Warningf("No IPv4 address provided in CreateEndpoint request") } if ipv6Address == "" { sendError(w, "No IPv6 address provided (required)", http.StatusBadRequest) return } maps := make([]endpoint.PortMap, 0, 32) for key, val := range create.Options { switch key { case "com.docker.network.portmap": var portmap []lnTypes.PortBinding if err := json.Unmarshal(val, &portmap); err != nil { sendError(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) return } log.Debugf("PortBinding: %+v", &portmap) // FIXME: Host IP is ignored for now for _, m := range portmap { maps = append(maps, endpoint.PortMap{ From: m.HostPort, To: m.Port, Proto: uint8(m.Proto), }) } case "com.docker.network.endpoint.exposedports": var tp []lnTypes.TransportPort if err := json.Unmarshal(val, &tp); err != nil { sendError(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) return } log.Debugf("ExposedPorts: %+v", &tp) // TODO: handle exposed ports } } ep, err := driver.client.EndpointGetByDockerEPID(endID) if err != nil { sendError(w, fmt.Sprintf("Error retrieving endpoint %s", err), http.StatusBadRequest) return } if ep != nil { sendError(w, "Endpoint already exists", http.StatusBadRequest) return } endpoint := endpoint.Endpoint{ NodeIP: driver.nodeAddress, DockerNetworkID: create.NetworkID, DockerEndpointID: endID, PortMap: maps, } if ipv6Address != "" { ip6, _, err := net.ParseCIDR(ipv6Address) if err != nil { sendError(w, fmt.Sprintf("Invalid IPv6 address: %s", err), http.StatusBadRequest) return } endpoint.IPv6 = addressing.DeriveCiliumIPv6(ip6) } if ipv4Address != "" { ip4, _, err := net.ParseCIDR(ipv4Address) if err != nil { sendError(w, fmt.Sprintf("Invalid IPv4 address: %s", err), http.StatusBadRequest) return } endpoint.IPv4 = addressing.DeriveCiliumIPv4(ip4) } endpoint.SetID() if err = driver.client.EndpointSave(endpoint); err != nil { sendError(w, fmt.Sprintf("Error retrieving endpoint %s", err), http.StatusBadRequest) return } log.Debugf("Created Endpoint: %+v", endpoint) log.Infof("New endpoint %s with IPv6: %s, IPv4: %s", endID, ipv6Address, ipv4Address) respIface := &api.EndpointInterface{ // Fixme: the lxcmac is an empty string at this point and we only know the // mac address at the end of joinEndpoint // There's no problem in the setup but docker inspect will show an empty mac address MacAddress: endpoint.LXCMAC.String(), } resp := &api.CreateEndpointResponse{ Interface: respIface, } log.Debugf("Create endpoint response: %+v", resp) objectResponse(w, resp) }
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) }