Skip to content

Commit

Permalink
✨ support accelerated networking
Browse files Browse the repository at this point in the history
  • Loading branch information
mboersma committed May 29, 2020
1 parent 4565290 commit b4e6772
Show file tree
Hide file tree
Showing 21 changed files with 557 additions and 43 deletions.
3 changes: 3 additions & 0 deletions api/v1alpha2/azuremachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ func (src *AzureMachine) ConvertTo(dstRaw conversion.Hub) error { // nolint
if len(restored.Spec.UserAssignedIdentities) > 0 {
dst.Spec.UserAssignedIdentities = restored.Spec.UserAssignedIdentities
}
if restored.Spec.AcceleratedNetworking != nil {
dst.Spec.AcceleratedNetworking = restored.Spec.AcceleratedNetworking
}

dst.Spec.FailureDomain = restored.Spec.FailureDomain

Expand Down
3 changes: 3 additions & 0 deletions api/v1alpha2/azuremachinetemplate_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ func (src *AzureMachineTemplate) ConvertTo(dstRaw conversion.Hub) error { // nol
if len(restored.Spec.Template.Spec.UserAssignedIdentities) > 0 {
dst.Spec.Template.Spec.UserAssignedIdentities = restored.Spec.Template.Spec.UserAssignedIdentities
}
if restored.Spec.Template.Spec.AcceleratedNetworking != nil {
dst.Spec.Template.Spec.AcceleratedNetworking = restored.Spec.Template.Spec.AcceleratedNetworking
}
dst.Spec.Template.Spec.FailureDomain = restored.Spec.Template.Spec.FailureDomain

return nil
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions api/v1alpha3/azuremachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ type AzureMachineSpec struct {
// AllocatePublicIP allows the ability to create dynamic public ips for machines where this value is true.
// +optional
AllocatePublicIP bool `json:"allocatePublicIP,omitempty"`

// AcceleratedNetworking enables or disables Azure accelerated networking. If omitted, it will be set based on
// whether the requested VMSize supports accelerated networking.
// If AcceleratedNetworking is set to true with a VMSize that does not support it, Azure will return an error.
// +kubebuilder:validation:nullable
// +optional
AcceleratedNetworking *bool `json:"acceleratedNetworking,omitempty"`
}

// AzureMachineStatus defines the observed state of AzureMachine
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions cloud/services/networkinterfaces/networkinterfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Spec struct {
PublicLoadBalancerName string
InternalLoadBalancerName string
PublicIPName string
AcceleratedNetworking *bool
}

// Get provides information about a network interface.
Expand Down Expand Up @@ -125,6 +126,16 @@ func (s *Service) Reconcile(ctx context.Context, spec interface{}) error {
nicConfig.PublicIPAddress = &publicIP
}

if nicSpec.AcceleratedNetworking == nil {
// set accelerated networking to the capability of the VMSize
sku := s.MachineScope.AzureMachine.Spec.VMSize
accelNet, err := s.ResourceSkusClient.HasAcceleratedNetworking(ctx, sku)
if err != nil {
return errors.Wrap(err, "failed to get accelerated networking capability")
}
nicSpec.AcceleratedNetworking = to.BoolPtr(accelNet)
}

err = s.Client.CreateOrUpdate(ctx,
s.Scope.ResourceGroup(),
nicSpec.Name,
Expand All @@ -137,6 +148,7 @@ func (s *Service) Reconcile(ctx context.Context, spec interface{}) error {
InterfaceIPConfigurationPropertiesFormat: nicConfig,
},
},
EnableAcceleratedNetworking: nicSpec.AcceleratedNetworking,
},
})

Expand Down
147 changes: 133 additions & 14 deletions cloud/services/networkinterfaces/networkinterfaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import (
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/networkinterfaces/mock_networkinterfaces"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/publicips/mock_publicips"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/publicloadbalancers/mock_publicloadbalancers"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/resourceskus/mock_resourceskus"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/subnets/mock_subnets"
"sigs.k8s.io/cluster-api-provider-azure/internal/test/matchers"

"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
Expand Down Expand Up @@ -236,7 +238,8 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder)
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient)
}{
{
name: "get subnets fails",
Expand All @@ -251,7 +254,8 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").
Return(network.Subnet{}, autorest.NewErrorWithResponse("", "", &http.Response{StatusCode: 500}, "Internal Server Error"))
},
Expand All @@ -269,7 +273,9 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(gomock.Any(), gomock.Any())
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").
Return(network.Subnet{}, nil),
Expand All @@ -291,7 +297,9 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(gomock.Any(), gomock.Any())
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", gomock.AssignableToTypeOf(network.Interface{})))
Expand All @@ -310,7 +318,9 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(gomock.Any(), gomock.Any())
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", gomock.AssignableToTypeOf(network.Interface{})))
Expand All @@ -331,7 +341,9 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(gomock.Any(), gomock.Any())
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").
Return(network.Subnet{ID: to.StringPtr("my-subnet-id")}, nil),
Expand Down Expand Up @@ -374,9 +386,10 @@ func TestReconcileNetworkInterface(t *testing.T) {
},
},
}}, nil),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", network.Interface{
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", matchers.DiffEq(network.Interface{
Location: to.StringPtr("test-location"),
InterfacePropertiesFormat: &network.InterfacePropertiesFormat{
EnableAcceleratedNetworking: to.BoolPtr(false),
IPConfigurations: &[]network.InterfaceIPConfiguration{
{
Name: to.StringPtr("pipConfig"),
Expand All @@ -389,7 +402,7 @@ func TestReconcileNetworkInterface(t *testing.T) {
},
},
},
}))
})))
},
},
{
Expand All @@ -407,7 +420,8 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
mPublicLoadBalancer.Get(context.TODO(), "my-rg", "my-publiclb").
Expand All @@ -429,7 +443,8 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
mPublicLoadBalancer.Get(context.TODO(), "my-rg", "my-publiclb").Return(network.LoadBalancer{
Expand Down Expand Up @@ -493,7 +508,8 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
mInternalLoadBalancer.Get(context.TODO(), "my-rg", "my-internal-lb").
Expand All @@ -514,7 +530,9 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(gomock.Any(), gomock.Any())
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
mPublicIP.CreateOrUpdate(context.TODO(), "my-rg", "my-public-ip", gomock.AssignableToTypeOf(network.PublicIPAddress{})),
Expand All @@ -536,14 +554,112 @@ func TestReconcileNetworkInterface(t *testing.T) {
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder) {
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
mPublicIP.CreateOrUpdate(context.TODO(), "my-rg", "my-public-ip", gomock.AssignableToTypeOf(network.PublicIPAddress{})),
mPublicIP.Get(context.TODO(), "my-rg", "my-public-ip").Return(network.PublicIPAddress{}, autorest.NewErrorWithResponse("", "", &http.Response{StatusCode: 500}, "Internal Server Error")),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", gomock.AssignableToTypeOf(network.Interface{})))
},
},
{
name: "network interface with accelerated networking successfully created",
netInterfaceSpec: Spec{
Name: "my-net-interface",
VnetName: "my-vnet",
SubnetName: "my-subnet",
},
expectedError: "",
expect: func(m *mock_networkinterfaces.MockClientMockRecorder,
mSubnet *mock_subnets.MockClientMockRecorder,
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(context.TODO(), gomock.Any()).Return(true, nil)
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", matchers.DiffEq(network.Interface{
Location: to.StringPtr("test-location"),
InterfacePropertiesFormat: &network.InterfacePropertiesFormat{
EnableAcceleratedNetworking: to.BoolPtr(true),
IPConfigurations: &[]network.InterfaceIPConfiguration{
{
Name: to.StringPtr("pipConfig"),
InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{
Subnet: &network.Subnet{},
PrivateIPAllocationMethod: network.Dynamic,
LoadBalancerBackendAddressPools: &[]network.BackendAddressPool{},
},
},
},
},
})),
)
},
},
{
name: "network interface without accelerated networking successfully created",
netInterfaceSpec: Spec{
Name: "my-net-interface",
VnetName: "my-vnet",
SubnetName: "my-subnet",
},
expectedError: "",
expect: func(m *mock_networkinterfaces.MockClientMockRecorder,
mSubnet *mock_subnets.MockClientMockRecorder,
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(context.TODO(), gomock.Any()).Return(false, nil)
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", matchers.DiffEq(network.Interface{
Location: to.StringPtr("test-location"),
InterfacePropertiesFormat: &network.InterfacePropertiesFormat{
EnableAcceleratedNetworking: to.BoolPtr(false),
IPConfigurations: &[]network.InterfaceIPConfiguration{
{
Name: to.StringPtr("pipConfig"),
InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{
Subnet: &network.Subnet{},
PrivateIPAllocationMethod: network.Dynamic,
LoadBalancerBackendAddressPools: &[]network.BackendAddressPool{},
},
},
},
},
})),
)
},
},
{
name: "network interface fails to get accelerated networking capability",
netInterfaceSpec: Spec{
Name: "my-net-interface",
VnetName: "my-vnet",
SubnetName: "my-subnet",
},
expectedError: "failed to get accelerated networking capability: #: Internal Server Error: StatusCode=500",
expect: func(m *mock_networkinterfaces.MockClientMockRecorder,
mSubnet *mock_subnets.MockClientMockRecorder,
mPublicLoadBalancer *mock_publicloadbalancers.MockClientMockRecorder,
mInboundNATRules *mock_inboundnatrules.MockClientMockRecorder,
mInternalLoadBalancer *mock_internalloadbalancers.MockClientMockRecorder,
mPublicIP *mock_publicips.MockClientMockRecorder,
mResourceSku *mock_resourceskus.MockClient) {
mResourceSku.EXPECT().HasAcceleratedNetworking(context.TODO(), gomock.Any()).Return(
false, autorest.NewErrorWithResponse("", "", &http.Response{StatusCode: 500}, "Internal Server Error"))
gomock.InOrder(
mSubnet.Get(context.TODO(), "my-rg", "my-vnet", "my-subnet").Return(network.Subnet{}, nil),
m.CreateOrUpdate(context.TODO(), "my-rg", "my-net-interface", gomock.AssignableToTypeOf(network.Interface{})),
)
},
},
}

for _, tc := range testcases {
Expand All @@ -555,6 +671,7 @@ func TestReconcileNetworkInterface(t *testing.T) {
inboundNatRulesMock := mock_inboundnatrules.NewMockClient(mockCtrl)
internalLoadBalancerMock := mock_internalloadbalancers.NewMockClient(mockCtrl)
publicIPsMock := mock_publicips.NewMockClient(mockCtrl)
resourceSkusMock := mock_resourceskus.NewMockClient(mockCtrl)

cluster := &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"},
Expand Down Expand Up @@ -613,7 +730,8 @@ func TestReconcileNetworkInterface(t *testing.T) {

tc.expect(netInterfaceMock.EXPECT(), subnetMock.EXPECT(),
publicLoadBalancerMock.EXPECT(), inboundNatRulesMock.EXPECT(),
internalLoadBalancerMock.EXPECT(), publicIPsMock.EXPECT())
internalLoadBalancerMock.EXPECT(), publicIPsMock.EXPECT(),
resourceSkusMock)

s := &Service{
Scope: clusterScope,
Expand All @@ -624,6 +742,7 @@ func TestReconcileNetworkInterface(t *testing.T) {
InboundNATRulesClient: inboundNatRulesMock,
InternalLoadBalancersClient: internalLoadBalancerMock,
PublicIPsClient: publicIPsMock,
ResourceSkusClient: resourceSkusMock,
}

err = s.Reconcile(context.TODO(), &tc.netInterfaceSpec)
Expand Down
3 changes: 3 additions & 0 deletions cloud/services/networkinterfaces/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/internalloadbalancers"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/publicips"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/publicloadbalancers"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/resourceskus"
"sigs.k8s.io/cluster-api-provider-azure/cloud/services/subnets"
)

Expand All @@ -35,6 +36,7 @@ type Service struct {
InternalLoadBalancersClient internalloadbalancers.Client
PublicIPsClient publicips.Client
InboundNATRulesClient inboundnatrules.Client
ResourceSkusClient resourceskus.Client
}

// NewService creates a new service.
Expand All @@ -48,5 +50,6 @@ func NewService(scope *scope.ClusterScope, machineScope *scope.MachineScope) *Se
InternalLoadBalancersClient: internalloadbalancers.NewClient(scope.SubscriptionID, scope.Authorizer),
PublicIPsClient: publicips.NewClient(scope.SubscriptionID, scope.Authorizer),
InboundNATRulesClient: inboundnatrules.NewClient(scope.SubscriptionID, scope.Authorizer),
ResourceSkusClient: resourceskus.NewClient(scope.SubscriptionID, scope.Authorizer),
}
}

0 comments on commit b4e6772

Please sign in to comment.