-
Notifications
You must be signed in to change notification settings - Fork 802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
V2 API support for win-overlay CNI #725
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
{ | ||
"cniVersion": "0.2.0", | ||
"name": "OVNKubernetesHybridOverlayNetwork", | ||
"type": "win-overlay", | ||
"ipam": { | ||
"type": "host-local", | ||
"subnet": "10.132.0.0/24" | ||
}, | ||
"apiVersion": 2, | ||
"capabilities": { | ||
"portMappings": true, | ||
"dns": true | ||
}, | ||
"policies": [ | ||
{ | ||
"name": "EndpointPolicy", | ||
"value": { | ||
"Type": "OutBoundNAT", | ||
"Settings": { | ||
"Exceptions": [ | ||
"172.30.0.0/16" | ||
] | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "EndpointPolicy", | ||
"value": { | ||
"Type": "SDNRoute", | ||
"Settings": { | ||
"DestinationPrefix": "172.30.0.0/16", | ||
"NeedEncap": true | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "EndpointPolicy", | ||
"value": { | ||
"Type": "ProviderAddress", | ||
"Settings": { | ||
"ProviderAddress": "10.0.133.170" | ||
} | ||
} | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,11 +17,13 @@ package main | |
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net" | ||
"runtime" | ||
"strings" | ||
|
||
"github.com/Microsoft/hcsshim" | ||
|
||
"github.com/Microsoft/hcsshim/hcn" | ||
"github.com/containernetworking/cni/pkg/skel" | ||
"github.com/containernetworking/cni/pkg/types" | ||
current "github.com/containernetworking/cni/pkg/types/100" | ||
|
@@ -55,16 +57,106 @@ func loadNetConf(bytes []byte) (*NetConf, string, error) { | |
return n, n.CNIVersion, nil | ||
} | ||
|
||
func cmdAdd(args *skel.CmdArgs) error { | ||
success := false | ||
n, cniVersion, err := loadNetConf(args.StdinData) | ||
func processEndpointArgs(args *skel.CmdArgs, n *NetConf) (*hns.EndpointInfo, error) { | ||
epInfo := new(hns.EndpointInfo) | ||
epInfo.NetworkName = n.Name | ||
epInfo.EndpointName = hns.ConstructEndpointName(args.ContainerID, args.Netns, epInfo.NetworkName) | ||
|
||
if n.IPAM.Type != "" { | ||
r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData) | ||
if err != nil { | ||
return nil, errors.Annotatef(err, "error while executing IPAM addition") | ||
} | ||
|
||
// convert whatever the IPAM result was into the current result | ||
result, err := current.NewResultFromResult(r) | ||
if err != nil { | ||
return nil, errors.Annotatef(err, "error while converting the result from IPAM addition") | ||
} | ||
if len(result.IPs) == 0 { | ||
return nil, fmt.Errorf("IPAM plugin return is missing IP config") | ||
} | ||
epInfo.IpAddress = result.IPs[0].Address.IP.To4() | ||
if epInfo.IpAddress == nil { | ||
return nil, fmt.Errorf("IPAM plugin return is missing valid IP Address") | ||
} | ||
epInfo.MacAddress = fmt.Sprintf("%v-%02x-%02x-%02x-%02x", n.EndpointMacPrefix, epInfo.IpAddress[0], epInfo.IpAddress[1], epInfo.IpAddress[2], epInfo.IpAddress[3]) | ||
|
||
} | ||
epInfo.DNS = n.GetDNS() | ||
if n.LoopbackDSR { | ||
n.ApplyLoopbackDSRPolicy(&epInfo.IpAddress) | ||
} | ||
return epInfo, nil | ||
} | ||
|
||
func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { | ||
if len(n.EndpointMacPrefix) != 0 { | ||
if len(n.EndpointMacPrefix) != 5 || n.EndpointMacPrefix[2] != '-' { | ||
return nil, fmt.Errorf("endpointMacPrefix [%v] is invalid, value must be of the format xx-xx", n.EndpointMacPrefix) | ||
} | ||
} else { | ||
n.EndpointMacPrefix = "0E-2A" | ||
} | ||
|
||
networkName := n.Name | ||
hnsNetwork, err := hcsshim.GetHNSNetworkByName(networkName) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit Feels like we should be able to avoid making a query to get network representation through HNS APIs since the result from HCN APIs should be sufficient... Or is there a reason we are getting the same network using both HCN and HNS? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear, this is a nit-pick and not blocking. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @daschott I was running into an issue where I was not able to get the exact gateway IP from the HCN network object. The way win-bridge CNI gets the gateway IP address is returning me a "different IP" when I tried to use it in win-overlay. That is the only reason I am still using the HNS network object. I already discussed it with @mansikulkarni96 and will take it as a separate improvement PR. I need to dig and find the right way to get the default IP. |
||
hcnNetwork, err := hcn.GetNetworkByName(networkName) | ||
if err != nil { | ||
return nil, errors.Annotatef(err, "error while hcn.GetNetworkByName(%s)", networkName) | ||
} | ||
if hcnNetwork == nil { | ||
return nil, fmt.Errorf("network %v is not found", networkName) | ||
} | ||
if hnsNetwork == nil { | ||
return nil, fmt.Errorf("network %v not found", networkName) | ||
} | ||
|
||
if !strings.EqualFold(string (hcnNetwork.Type), "Overlay") { | ||
return nil, fmt.Errorf("network %v is of an unexpected type: %v", networkName, hcnNetwork.Type) | ||
} | ||
|
||
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name) | ||
|
||
hcnEndpoint, err := hns.AddHcnEndpoint(epName, hcnNetwork.Id, args.Netns, func() (*hcn.HostComputeEndpoint, error) { | ||
epInfo, err := processEndpointArgs(args, n) | ||
if err != nil { | ||
return nil, errors.Annotate(err, "error while processing endpoint args") | ||
} | ||
epInfo.NetworkId = hcnNetwork.Id | ||
gatewayAddr := net.ParseIP(hnsNetwork.Subnets[0].GatewayAddress) | ||
epInfo.Gateway = gatewayAddr.To4() | ||
n.ApplyDefaultPAPolicy(hnsNetwork.ManagementIP) | ||
if n.IPMasq { | ||
n.ApplyOutboundNatPolicy(hnsNetwork.Subnets[0].AddressPrefix) | ||
} | ||
hcnEndpoint, err := hns.GenerateHcnEndpoint(epInfo, &n.NetConf) | ||
|
||
if err != nil { | ||
return nil, errors.Annotate(err, "error while generating HostComputeEndpoint") | ||
} | ||
return hcnEndpoint, nil | ||
}) | ||
if err != nil { | ||
return errors.Annotate(err, "error while loadNetConf") | ||
return nil, errors.Annotate(err, "error while adding HostComputeEndpoint") | ||
} | ||
|
||
result, err := hns.ConstructHcnResult(hcnNetwork, hcnEndpoint) | ||
|
||
if err != nil { | ||
ipam.ExecDel(n.IPAM.Type, args.StdinData) | ||
return nil, errors.Annotate(err, "error while constructing HostComputeEndpoint addition result") | ||
} | ||
|
||
return result, nil | ||
|
||
} | ||
func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) { | ||
success := false | ||
|
||
if len(n.EndpointMacPrefix) != 0 { | ||
if len(n.EndpointMacPrefix) != 5 || n.EndpointMacPrefix[2] != '-' { | ||
return fmt.Errorf("endpointMacPrefix [%v] is invalid, value must be of the format xx-xx", n.EndpointMacPrefix) | ||
return nil, fmt.Errorf("endpointMacPrefix [%v] is invalid, value must be of the format xx-xx", n.EndpointMacPrefix) | ||
} | ||
} else { | ||
n.EndpointMacPrefix = "0E-2A" | ||
|
@@ -73,15 +165,15 @@ func cmdAdd(args *skel.CmdArgs) error { | |
networkName := n.Name | ||
hnsNetwork, err := hcsshim.GetHNSNetworkByName(networkName) | ||
if err != nil { | ||
return errors.Annotatef(err, "error while GETHNSNewtorkByName(%s)", networkName) | ||
return nil, errors.Annotatef(err, "error while GETHNSNewtorkByName(%s)", networkName) | ||
} | ||
|
||
if hnsNetwork == nil { | ||
return fmt.Errorf("network %v not found", networkName) | ||
return nil, fmt.Errorf("network %v not found", networkName) | ||
} | ||
|
||
if !strings.EqualFold(hnsNetwork.Type, "Overlay") { | ||
return fmt.Errorf("network %v is of an unexpected type: %v", networkName, hnsNetwork.Type) | ||
return nil, fmt.Errorf("network %v is of an unexpected type: %v", networkName, hnsNetwork.Type) | ||
} | ||
|
||
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name) | ||
|
@@ -140,15 +232,34 @@ func cmdAdd(args *skel.CmdArgs) error { | |
} | ||
}() | ||
if err != nil { | ||
return errors.Annotatef(err, "error while AddHnsEndpoint(%v,%v,%v)", epName, hnsNetwork.Id, args.ContainerID) | ||
return nil, errors.Annotatef(err, "error while AddHnsEndpoint(%v,%v,%v)", epName, hnsNetwork.Id, args.ContainerID) | ||
} | ||
|
||
result, err := hns.ConstructHnsResult(hnsNetwork, hnsEndpoint) | ||
if err != nil { | ||
return errors.Annotatef(err, "error while constructResult") | ||
return nil, errors.Annotatef(err, "error while constructResult") | ||
} | ||
|
||
success = true | ||
return result, nil | ||
} | ||
func cmdAdd(args *skel.CmdArgs) error { | ||
n, cniVersion, err := loadNetConf(args.StdinData) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var result *current.Result | ||
if n.ApiVersion == 2 { | ||
selansen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
result, err = cmdHcnAdd(args, n) | ||
} else { | ||
result, err = cmdHnsAdd(args, n) | ||
} | ||
if err != nil { | ||
ipam.ExecDel(n.IPAM.Type, args.StdinData) | ||
return err | ||
} | ||
|
||
return types.PrintResult(result, cniVersion) | ||
} | ||
|
||
|
@@ -158,12 +269,16 @@ func cmdDel(args *skel.CmdArgs) error { | |
return err | ||
} | ||
|
||
if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil { | ||
return err | ||
if n.IPAM.Type != "" { | ||
if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name) | ||
|
||
if n.ApiVersion == 2 { | ||
return hns.RemoveHcnEndpoint(epName) | ||
selansen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
return hns.RemoveHnsEndpoint(epName, args.Netns, args.ContainerID) | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tip: FYI If desirable, we could expand this to fallback to HNS to provision an IP address and MAC address for you, instead of requiring on an IPAM plugin. This is just an FYI, it is also a perfectly valid decision to require IPAM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, this is not blocking.