Skip to content
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

[release/0.9] Backport networking commits #2170

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions hcn/hcn.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ func SetPolicySupported() error {
return platformDoesNotSupportError("SetPolicy")
}

// ModifyLoadbalancerSupported returns an error if the HCN version does not support ModifyLoadbalancer.
func ModifyLoadbalancerSupported() error {
supported, err := GetCachedSupportedFeatures()
if err != nil {
return err
}
if supported.ModifyLoadbalancer {
return nil
}
return platformDoesNotSupportError("ModifyLoadbalancer")
}

// VxlanPortSupported returns an error if the HCN version does not support configuring the VXLAN TCP port.
func VxlanPortSupported() error {
supported, err := GetCachedSupportedFeatures()
Expand Down
6 changes: 6 additions & 0 deletions hcn/hcnerrors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/Microsoft/hcsshim/internal/hcserror"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)

var (
Expand Down Expand Up @@ -50,6 +51,7 @@ type ErrorCode uint32
const (
ERROR_NOT_FOUND = 0x490
HCN_E_PORT_ALREADY_EXISTS ErrorCode = 0x803b0013
HCN_E_NOTIMPL ErrorCode = ErrorCode(windows.E_NOTIMPL)
)

type HcnError struct {
Expand Down Expand Up @@ -77,6 +79,10 @@ func IsPortAlreadyExistsError(err error) bool {
return CheckErrorWithCode(err, HCN_E_PORT_ALREADY_EXISTS)
}

func IsNotImplemented(err error) bool {
return CheckErrorWithCode(err, HCN_E_NOTIMPL)
}

func new(hr error, title string, rest string) error {
err := &HcnError{}
hcsError := hcserror.New(hr, title, rest)
Expand Down
5 changes: 5 additions & 0 deletions hcn/hcnglobals.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ var (

//HNS 15.0 allows for NestedIpSet support
NestedIpSetVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 15, Minor: 0}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}}

//HNS 15.1 allows support for DisableHostPort flag.
DisableHostPortVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 15, Minor: 1}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}}
// HNS 15.4 allows for Modify Loadbalancer support
ModifyLoadbalancerVersion = VersionRanges{VersionRange{MinVersion: Version{Major: 15, Minor: 4}, MaxVersion: Version{Major: math.MaxInt32, Minor: math.MaxInt32}}}
)

// GetGlobals returns the global properties of the HCN Service.
Expand Down
64 changes: 62 additions & 2 deletions hcn/hcnloadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ type HostComputeLoadBalancer struct {
Flags LoadBalancerFlags `json:",omitempty"` // 0: None, 1: EnableDirectServerReturn
}

//LoadBalancerFlags modify settings for a loadbalancer.
// LoadBalancerFlags modify settings for a loadbalancer.
type LoadBalancerFlags uint32

var (
// LoadBalancerFlagsNone is the default.
LoadBalancerFlagsNone LoadBalancerFlags = 0
// LoadBalancerFlagsDSR enables Direct Server Return (DSR)
LoadBalancerFlagsDSR LoadBalancerFlags = 1
LoadBalancerFlagsDSR LoadBalancerFlags = 1
LoadBalancerFlagsIPv6 LoadBalancerFlags = 2
)

Expand Down Expand Up @@ -161,6 +161,49 @@ func createLoadBalancer(settings string) (*HostComputeLoadBalancer, error) {
return &outputLoadBalancer, nil
}

func updateLoadBalancer(loadbalancerId string, settings string) (*HostComputeLoadBalancer, error) {
loadBalancerGuid, err := guid.FromString(loadbalancerId)
if err != nil {
return nil, errInvalidLoadBalancerID
}
// Update loadBalancer.
var (
loadBalancerHandle hcnLoadBalancer
resultBuffer *uint16
propertiesBuffer *uint16
)
hr := hcnOpenLoadBalancer(&loadBalancerGuid, &loadBalancerHandle, &resultBuffer)
if err := checkForErrors("hcnOpenLoadBalancer", hr, resultBuffer); err != nil {
return nil, err
}
hr = hcnModifyLoadBalancer(loadBalancerHandle, settings, &resultBuffer)
if err := checkForErrors("hcnModifyLoadBalancer", hr, resultBuffer); err != nil {
return nil, err
}
// Query loadBalancer.
hcnQuery := defaultQuery()
query, err := json.Marshal(hcnQuery)
if err != nil {
return nil, err
}
hr = hcnQueryLoadBalancerProperties(loadBalancerHandle, string(query), &propertiesBuffer, &resultBuffer)
if err := checkForErrors("hcnQueryLoadBalancerProperties", hr, resultBuffer); err != nil {
return nil, err
}
properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
// Close loadBalancer.
hr = hcnCloseLoadBalancer(loadBalancerHandle)
if err := checkForErrors("hcnCloseLoadBalancer", hr, nil); err != nil {
return nil, err
}
// Convert output to HostComputeLoadBalancer
var outputLoadBalancer HostComputeLoadBalancer
if err := json.Unmarshal([]byte(properties), &outputLoadBalancer); err != nil {
return nil, err
}
return &outputLoadBalancer, nil
}

func deleteLoadBalancer(loadBalancerId string) error {
loadBalancerGuid, err := guid.FromString(loadBalancerId)
if err != nil {
Expand Down Expand Up @@ -235,6 +278,23 @@ func (loadBalancer *HostComputeLoadBalancer) Create() (*HostComputeLoadBalancer,
return loadBalancer, nil
}

// Update Loadbalancer.
func (loadBalancer *HostComputeLoadBalancer) Update(hnsLoadbalancerID string) (*HostComputeLoadBalancer, error) {
logrus.Debugf("hcn::HostComputeLoadBalancer::Create id=%s", hnsLoadbalancerID)

jsonString, err := json.Marshal(loadBalancer)
if err != nil {
return nil, err
}

logrus.Debugf("hcn::HostComputeLoadBalancer::Update JSON: %s", jsonString)
loadBalancer, hcnErr := updateLoadBalancer(hnsLoadbalancerID, string(jsonString))
if hcnErr != nil {
return nil, hcnErr
}
return loadBalancer, nil
}

// Delete LoadBalancer.
func (loadBalancer *HostComputeLoadBalancer) Delete() error {
logrus.Debugf("hcn::HostComputeLoadBalancer::Delete id=%s", loadBalancer.Id)
Expand Down
64 changes: 64 additions & 0 deletions hcn/hcnloadbalancer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,70 @@ func TestCreateDeleteLoadBalancer(t *testing.T) {
}
}

func TestCreateUpdateDeleteLoadBalancer(t *testing.T) {
network, err := CreateTestOverlayNetwork()
if err != nil {
t.Fatal(err)
}
endpoint, err := HcnCreateTestEndpoint(network)
if err != nil {
t.Fatal(err)
}
loadBalancer, err := HcnCreateTestLoadBalancer(endpoint)
if err != nil {
t.Fatal(err)
}
jsonString, err := json.Marshal(loadBalancer)
if err != nil {
t.Fatal(err)
}
fmt.Printf("LoadBalancer JSON:\n%s \n", jsonString)

secondEndpoint, err := HcnCreateTestEndpoint(network)
if err != nil {
t.Fatal(err)
}

HcnLoadBalancerTestAddBackend(loadBalancer, secondEndpoint.Id)

loadBalancer, err = loadBalancer.Update(loadBalancer.Id)
if err != nil {
t.Fatal(err)
}

if len(loadBalancer.HostComputeEndpoints) != 2 {
t.Fatalf("Update loadBalancer with backend add failed")
}

HcnLoadBalancerTestRemoveBackend(loadBalancer, secondEndpoint.Id)

loadBalancer, err = loadBalancer.Update(loadBalancer.Id)
if err != nil {
t.Fatal(err)
}

if len(loadBalancer.HostComputeEndpoints) != 1 {
t.Fatalf("Update loadBalancer with backend remove failed")
}

err = loadBalancer.Delete()
if err != nil {
t.Fatal(err)
}
err = secondEndpoint.Delete()
if err != nil {
t.Fatal(err)
}
err = endpoint.Delete()
if err != nil {
t.Fatal(err)
}
err = network.Delete()
if err != nil {
t.Fatal(err)
}
}

func TestGetLoadBalancerById(t *testing.T) {
network, err := CreateTestOverlayNetwork()
if err != nil {
Expand Down
9 changes: 5 additions & 4 deletions hcn/hcnpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ type QosPolicySetting struct {

// OutboundNatPolicySetting sets outbound Network Address Translation on an Endpoint.
type OutboundNatPolicySetting struct {
VirtualIP string `json:",omitempty"`
Exceptions []string `json:",omitempty"`
Destinations []string `json:",omitempty"`
Flags NatFlags `json:",omitempty"`
VirtualIP string `json:",omitempty"`
Exceptions []string `json:",omitempty"`
Destinations []string `json:",omitempty"`
Flags NatFlags `json:",omitempty"`
MaxPortPoolUsage uint16 `json:",omitempty"`
}

// SDNRoutePolicySetting sets SDN Route on an Endpoint.
Expand Down
4 changes: 4 additions & 0 deletions hcn/hcnsupport.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type SupportedFeatures struct {
TierAcl bool `json:"TierAcl"`
NetworkACL bool `json:"NetworkACL"`
NestedIpSet bool `json:"NestedIpSet"`
DisableHostPort bool `json:"DisableHostPort"`
ModifyLoadbalancer bool `json:"ModifyLoadbalancer"`
}

// AclFeatures are the supported ACL possibilities.
Expand Down Expand Up @@ -111,6 +113,8 @@ func getSupportedFeatures() (SupportedFeatures, error) {
features.TierAcl = isFeatureSupported(globals.Version, TierAclPolicyVersion)
features.NetworkACL = isFeatureSupported(globals.Version, NetworkACLPolicyVersion)
features.NestedIpSet = isFeatureSupported(globals.Version, NestedIpSetVersion)
features.DisableHostPort = isFeatureSupported(globals.Version, DisableHostPortVersion)
features.ModifyLoadbalancer = isFeatureSupported(globals.Version, ModifyLoadbalancerVersion)

logrus.WithFields(logrus.Fields{
"version": fmt.Sprintf("%+v", globals.Version),
Expand Down
17 changes: 17 additions & 0 deletions hcn/hcnutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,23 @@ func HcnCreateTestLoadBalancer(endpoint *HostComputeEndpoint) (*HostComputeLoadB
return loadBalancer.Create()
}

func HcnLoadBalancerTestAddBackend(loadBalancer *HostComputeLoadBalancer, endpointId string) {
endpointIds := loadBalancer.HostComputeEndpoints
endpointIds = append(endpointIds, endpointId)
loadBalancer.HostComputeEndpoints = endpointIds
}

func HcnLoadBalancerTestRemoveBackend(loadBalancer *HostComputeLoadBalancer, endpointId string) {
endpointIds := loadBalancer.HostComputeEndpoints
for i, v := range endpointIds {
if v == endpointId {
endpointIds = append(endpointIds[:i], endpointIds[i+1:]...)
break
}
}
loadBalancer.HostComputeEndpoints = endpointIds
}

func HcnCreateTestRemoteSubnetRoute() (*PolicyNetworkRequest, error) {
rsr := RemoteSubnetRoutePolicySetting{
DestinationPrefix: "192.168.2.0/24",
Expand Down
7 changes: 4 additions & 3 deletions internal/hns/hnspolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ type PaPolicy struct {

type OutboundNatPolicy struct {
Policy
VIP string `json:"VIP,omitempty"`
Exceptions []string `json:"ExceptionList,omitempty"`
Destinations []string `json:",omitempty"`
VIP string `json:"VIP,omitempty"`
Exceptions []string `json:"ExceptionList,omitempty"`
Destinations []string `json:",omitempty"`
MaxPortPoolUsage uint16 `json:",omitempty"`
}

type ProxyPolicy struct {
Expand Down
Loading