forked from containernetworking/plugins
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit has the following changes
+ windows cni plugins are added (*) hostgw (*) overlay vxlan + windows netconf unit test + Fix appveyor config to run the test + Vendor commit for (*) github.com/Microsoft/hcsshim (*) golang.org/x/sys + Build Release support for windows plugins
- Loading branch information
Showing
332 changed files
with
79,255 additions
and
23,183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// +build windows | ||
|
||
// Copyright 2017 CNI authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package hns | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net" | ||
"strings" | ||
|
||
"github.com/Microsoft/hcsshim" | ||
"github.com/containernetworking/cni/pkg/types/current" | ||
) | ||
|
||
// ConstructEndpointName constructs enpointId which is used to identify an endpoint from HNS | ||
// There is a special consideration for netNs name here, which is required for Windows Server 1709 | ||
// containerID is the Id of the container on which the endpoint is worked on | ||
func ConstructEndpointName(containerID string, netNs string, networkName string) string { | ||
if netNs != "" { | ||
splits := strings.Split(netNs, ":") | ||
if len(splits) == 2 { | ||
containerID = splits[1] | ||
} | ||
} | ||
epName := containerID + "_" + networkName | ||
return epName | ||
} | ||
|
||
// DeprovisionEndpoint removes an endpoint from the container by sending a Detach request to HNS | ||
// For shared endpoint, ContainerDetach is used | ||
// for removing the endpoint completely, HotDetachEndpoint is used | ||
func DeprovisionEndpoint(epName string, netns string, containerID string) error { | ||
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epName) | ||
if err != nil { | ||
log.Printf("[win-cni] Failed to find endpoint %v, err:%v", epName, err) | ||
return err | ||
} | ||
|
||
if netns != "none" { | ||
// Shared endpoint removal. Do not remove the endpoint. | ||
err := hnsEndpoint.ContainerDetach(containerID) | ||
if err != nil { | ||
log.Printf("[win-cni] Failed to detach the container endpoint %v, err:%v", epName, err) | ||
} | ||
return nil | ||
} | ||
|
||
err = hcsshim.HotDetachEndpoint(containerID, hnsEndpoint.Id) | ||
if err != nil { | ||
log.Printf("[win-cni] Failed to detach endpoint %v, err:%v", epName, err) | ||
// Do not consider this as failure, else this would leak endpoints | ||
} | ||
|
||
_, err = hnsEndpoint.Delete() | ||
if err != nil { | ||
log.Printf("[win-cni] Failed to delete endpoint %v, err:%v", epName, err) | ||
// Do not return error | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type EndpointMakerFunc func() (*hcsshim.HNSEndpoint, error) | ||
|
||
// ProvisionEndpoint provisions an endpoint to a container specified by containerID. | ||
// If an endpoint already exists, the endpoint is reused. | ||
// This call is idempotent | ||
func ProvisionEndpoint(epName string, expectedNetworkId string, containerID string, makeEndpoint EndpointMakerFunc) (*hcsshim.HNSEndpoint, error) { | ||
// check if endpoint already exists | ||
createEndpoint := true | ||
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(epName) | ||
if hnsEndpoint != nil && hnsEndpoint.VirtualNetwork == expectedNetworkId { | ||
log.Printf("[win-cni] Found existing endpoint %v", epName) | ||
createEndpoint = false | ||
} | ||
|
||
if createEndpoint { | ||
if hnsEndpoint != nil { | ||
_, err = hnsEndpoint.Delete() | ||
if err != nil { | ||
log.Printf("[win-cni] Failed to delete stale endpoint %v, err:%v", epName, err) | ||
} | ||
} | ||
|
||
if hnsEndpoint, err = makeEndpoint(); err != nil { | ||
return nil, err | ||
} | ||
|
||
if hnsEndpoint, err = hnsEndpoint.Create(); err != nil { | ||
return nil, err | ||
} | ||
|
||
} | ||
|
||
// hot attach | ||
if err = hcsshim.HotAttachEndpoint(containerID, hnsEndpoint.Id); err != nil { | ||
return nil, err | ||
} | ||
|
||
return hnsEndpoint, nil | ||
} | ||
|
||
// ConstructResult constructs the CNI result for the endpoint | ||
func ConstructResult(hnsNetwork *hcsshim.HNSNetwork, hnsEndpoint *hcsshim.HNSEndpoint) (*current.Result, error) { | ||
resultInterface := ¤t.Interface{ | ||
Name: hnsEndpoint.Name, | ||
Mac: hnsEndpoint.MacAddress, | ||
} | ||
_, ipSubnet, err := net.ParseCIDR(hnsNetwork.Subnets[0].AddressPrefix) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var ipVersion string | ||
if ipv4 := hnsEndpoint.IPAddress.To4(); ipv4 != nil { | ||
ipVersion = "4" | ||
} else if ipv6 := hnsEndpoint.IPAddress.To16(); ipv6 != nil { | ||
ipVersion = "6" | ||
} else { | ||
return nil, fmt.Errorf("[win-cni] The IPAddress of hnsEndpoint isn't a valid ipv4 or ipv6 Address.") | ||
} | ||
|
||
resultIPConfig := ¤t.IPConfig{ | ||
Version: ipVersion, | ||
Address: net.IPNet{ | ||
IP: hnsEndpoint.IPAddress, | ||
Mask: ipSubnet.Mask}, | ||
Gateway: net.ParseIP(hnsEndpoint.GatewayAddress), | ||
} | ||
result := ¤t.Result{} | ||
result.Interfaces = []*current.Interface{resultInterface} | ||
result.IPs = []*current.IPConfig{resultIPConfig} | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// Copyright 2017 CNI authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package hns | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/containernetworking/cni/pkg/types" | ||
"strings" | ||
) | ||
|
||
// NetConf is the CNI spec | ||
type NetConf struct { | ||
types.NetConf | ||
AdditionalArgs []policyArgument `json:"AdditionalArgs,omitempty"` | ||
} | ||
|
||
type policyArgument struct { | ||
Name string | ||
Value map[string]interface{} | ||
} | ||
|
||
// MarshalPolicies converts the Endpoint policies in AdditionalArgs | ||
// to HNS specific policies as Json raw bytes | ||
func (n *NetConf) MarshalPolicies() []json.RawMessage { | ||
if n.AdditionalArgs == nil { | ||
n.AdditionalArgs = []policyArgument{} | ||
} | ||
|
||
var result []json.RawMessage | ||
for _, policyArg := range n.AdditionalArgs { | ||
if !strings.EqualFold(policyArg.Name, "EndpointPolicy") { | ||
continue | ||
} | ||
if data, err := json.Marshal(policyArg.Value); err == nil { | ||
result = append(result, data) | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
// ApplyOutboundNatPolicy applies NAT Policy in VFP using HNS | ||
// Simultaneously an exception is added for the network that has to be Nat'd | ||
func (n *NetConf) ApplyOutboundNatPolicy(nwToNat string) { | ||
if n.AdditionalArgs == nil { | ||
n.AdditionalArgs = []policyArgument{} | ||
} | ||
|
||
for _, policy := range n.AdditionalArgs { | ||
if !strings.EqualFold(policy.Name, "EndpointPolicy") { | ||
continue | ||
} | ||
|
||
pv := policy.Value | ||
if !hasKey(pv, "Type") { | ||
continue | ||
} | ||
|
||
if !strings.EqualFold(pv["Type"].(string), "OutBoundNAT") { | ||
continue | ||
} | ||
|
||
if !hasKey(pv, "ExceptionList") { | ||
// add the exception since there weren't any | ||
pv["ExceptionList"] = []interface{}{nwToNat} | ||
return | ||
} | ||
|
||
nets := pv["ExceptionList"].([]interface{}) | ||
for _, net := range nets { | ||
if net.(string) == nwToNat { | ||
// found it - do nothing | ||
return | ||
} | ||
} | ||
|
||
// its not in the list of exceptions, add it and we're done | ||
pv["ExceptionList"] = append(nets, nwToNat) | ||
return | ||
} | ||
|
||
// didn't find the policy, add it | ||
natEntry := policyArgument{ | ||
Name: "EndpointPolicy", | ||
Value: map[string]interface{}{ | ||
"Type": "OutBoundNAT", | ||
"ExceptionList": []interface{}{ | ||
nwToNat, | ||
}, | ||
}, | ||
} | ||
|
||
n.AdditionalArgs = append(n.AdditionalArgs, natEntry) | ||
} | ||
|
||
// ApplyDefaultPAPolicy is used to configure a endpoint PA policy in HNS | ||
func (n *NetConf) ApplyDefaultPAPolicy(paAddress string) { | ||
if n.AdditionalArgs == nil { | ||
n.AdditionalArgs = []policyArgument{} | ||
} | ||
|
||
// if its already present, leave untouched | ||
for _, policy := range n.AdditionalArgs { | ||
if policy.Name == "EndpointPolicy" { | ||
if hasKey(policy.Value, "PA") { | ||
// found it, don't override | ||
return | ||
} | ||
} | ||
} | ||
|
||
// did not find, add it now | ||
paPolicyData := map[string]interface{}{ | ||
"Type": "PA", | ||
"PA": paAddress, | ||
} | ||
paPolicy := &policyArgument{ | ||
Name: "EndpointPolicy", | ||
Value: paPolicyData, | ||
} | ||
|
||
n.AdditionalArgs = append(n.AdditionalArgs, *paPolicy) | ||
|
||
return | ||
} | ||
|
||
func hasKey(m map[string]interface{}, k string) bool { | ||
_, ok := m[k] | ||
return ok | ||
} |
Oops, something went wrong.