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-1.27] Fix vmssflex ensureBackendPoolDeletedFromNode #4085

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 6 additions & 5 deletions pkg/provider/azure_standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"unicode"

Expand Down Expand Up @@ -1101,7 +1102,6 @@ func (as *availabilitySet) EnsureBackendPoolDeleted(service *v1.Service, backend
}
nicUpdaters := make([]func() error, 0)
allErrs := make([]error, 0)
var nicUpdated bool

ipconfigPrefixToNicMap := map[string]network.Interface{} // ipconfig prefix -> nic
for i := range ipConfigurationIDs {
Expand Down Expand Up @@ -1150,6 +1150,7 @@ func (as *availabilitySet) EnsureBackendPoolDeleted(service *v1.Service, backend
ipconfigPrefixToNicMap[ipConfigIDPrefix] = nic
}
}
var nicUpdated atomic.Bool
for k := range ipconfigPrefixToNicMap {
nic := ipconfigPrefixToNicMap[k]
newIPConfigs := *nic.IPConfigurations
Expand Down Expand Up @@ -1182,21 +1183,21 @@ func (as *availabilitySet) EnsureBackendPoolDeleted(service *v1.Service, backend
klog.Errorf("EnsureBackendPoolDeleted CreateOrUpdate for NIC(%s, %s) failed with error %v", as.ResourceGroup, pointer.StringDeref(nic.Name, ""), rerr.Error())
return rerr.Error()
}
nicUpdated = true
nicUpdated.Store(true)
return nil
})
}
errs := utilerrors.AggregateGoroutines(nicUpdaters...)
if errs != nil {
return nicUpdated, utilerrors.Flatten(errs)
return nicUpdated.Load(), utilerrors.Flatten(errs)
}
// Fail if there are other errors.
if len(allErrs) > 0 {
return nicUpdated, utilerrors.Flatten(utilerrors.NewAggregate(allErrs))
return nicUpdated.Load(), utilerrors.Flatten(utilerrors.NewAggregate(allErrs))
}

isOperationSucceeded = true
return nicUpdated, nil
return nicUpdated.Load(), nil
}

func getAvailabilitySetNameByID(asID string) (string, error) {
Expand Down
11 changes: 6 additions & 5 deletions pkg/provider/azure_vmss.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-03-01/compute"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-07-01/network"
Expand Down Expand Up @@ -1889,7 +1890,7 @@ func (ss *ScaleSet) ensureBackendPoolDeleted(service *v1.Service, backendPoolIDs
}

// Update VMs with best effort that have already been added to nodeUpdates.
var updatedVM bool
var updatedVM atomic.Bool
for meta, update := range nodeUpdates {
// create new instance of meta and update for passing to anonymous function
meta := meta
Expand Down Expand Up @@ -1918,22 +1919,22 @@ func (ss *ScaleSet) ensureBackendPoolDeleted(service *v1.Service, backendPoolIDs
return rerr.Error()
}

updatedVM = true
updatedVM.Store(true)
return nil
})
}
errs := utilerrors.AggregateGoroutines(hostUpdates...)
if errs != nil {
return updatedVM, utilerrors.Flatten(errs)
return updatedVM.Load(), utilerrors.Flatten(errs)
}

// Fail if there are other errors.
if len(allErrs) > 0 {
return updatedVM, utilerrors.Flatten(utilerrors.NewAggregate(allErrs))
return updatedVM.Load(), utilerrors.Flatten(utilerrors.NewAggregate(allErrs))
}

isOperationSucceeded = true
return updatedVM, nil
return updatedVM.Load(), nil
}

// EnsureBackendPoolDeleted ensures the loadBalancer backendAddressPools deleted from the specified nodes.
Expand Down
16 changes: 9 additions & 7 deletions pkg/provider/azure_vmssflex.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-03-01/compute"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2022-07-01/network"
Expand Down Expand Up @@ -958,8 +959,8 @@ func (fs *FlexScaleSet) EnsureBackendPoolDeleted(service *v1.Service, backendPoo
}
}

klog.V(2).Infof("Ensure backendPoolIDs deleted from the VMSS VMs.", backendPoolIDs)
klog.V(2).Infof("go into fs.ensureBackendPoolDeletedFromNode, vmssFlexVMNameMap: %s, size: %s", vmssFlexVMNameMap, len(vmssFlexVMNameMap))
klog.V(2).Infof("Ensure backendPoolIDs %q deleted from the VMSS VMs.", backendPoolIDs)
klog.V(2).Infof("go into fs.ensureBackendPoolDeletedFromNode, vmssFlexVMNameMap: %s, size: %d", vmssFlexVMNameMap, len(vmssFlexVMNameMap))
nicUpdated, err := fs.ensureBackendPoolDeletedFromNode(vmssFlexVMNameMap, backendPoolIDs)
klog.V(2).Infof("exit from fs.ensureBackendPoolDeletedFromNode")
if err != nil {
Expand All @@ -978,7 +979,6 @@ func (fs *FlexScaleSet) EnsureBackendPoolDeleted(service *v1.Service, backendPoo
func (fs *FlexScaleSet) ensureBackendPoolDeletedFromNode(vmssFlexVMNameMap map[string]string, backendPoolIDs []string) (bool, error) {
nicUpdaters := make([]func() error, 0)
allErrs := make([]error, 0)
var nicUpdated bool
nics := map[string]network.Interface{} // nicName -> nic
for nodeName, nicName := range vmssFlexVMNameMap {
if _, ok := nics[nicName]; ok {
Expand All @@ -1002,7 +1002,9 @@ func (fs *FlexScaleSet) ensureBackendPoolDeletedFromNode(vmssFlexVMNameMap map[s
nics[nicName] = nic
}
}
var nicUpdated atomic.Bool
for _, nic := range nics {
nic := nic
newIPConfigs := *nic.IPConfigurations
for j, ipConf := range newIPConfigs {
if !pointer.BoolDeref(ipConf.Primary, false) {
Expand Down Expand Up @@ -1033,18 +1035,18 @@ func (fs *FlexScaleSet) ensureBackendPoolDeletedFromNode(vmssFlexVMNameMap map[s
klog.Errorf("EnsureBackendPoolDeleted CreateOrUpdate for NIC(%s, %s) failed with error %v", fs.ResourceGroup, pointer.StringDeref(nic.Name, ""), rerr.Error())
return rerr.Error()
}
nicUpdated = true
nicUpdated.Store(true)
klog.V(2).Infof("EnsureBackendPoolDeleted done")
return nil
})
}
klog.V(2).Infof("nicUpdaters size: %s", len(nicUpdaters))
klog.V(2).Infof("nicUpdaters size: %d", len(nicUpdaters))
errs := utilerrors.AggregateGoroutines(nicUpdaters...)
if errs != nil {
allErrs = append(allErrs, utilerrors.Flatten(errs))
}
if len(allErrs) > 0 {
return nicUpdated, utilerrors.Flatten(utilerrors.NewAggregate(allErrs))
return nicUpdated.Load(), utilerrors.Flatten(utilerrors.NewAggregate(allErrs))
}
return nicUpdated, nil
return nicUpdated.Load(), nil
}
50 changes: 29 additions & 21 deletions pkg/provider/azure_vmssflex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1709,19 +1709,23 @@ func TestEnsureBackendPoolDeletedFromNodeVmssFlex(t *testing.T) {
description string
vmssFlexVMNameMap map[string]string
backendPoolID string
nic network.Interface
nics []network.Interface
expectedPutNICTimes int
nicGetErr *retry.Error
nicPutErr *retry.Error
expectedErr error
}{
{
description: "EnsureBackendPoolDeletedFromNode should remove a backend pool from the vmss flex vm",
description: "EnsureBackendPoolDeletedFromNode should remove backend pools from the vmss flex vm",
vmssFlexVMNameMap: map[string]string{
"vmssflex1000001": "testvm1-nic",
"vmssflex1000002": "testvm2-nic",
},
backendPoolID: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/lb/backendAddressPools/backendpool-0",
nics: []network.Interface{
generateTestNic("testvm1-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1"),
generateTestNic("testvm2-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm2"),
},
backendPoolID: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/lb/backendAddressPools/backendpool-0",
nic: generateTestNic("testvm1-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1"),
expectedPutNICTimes: 1,
nicGetErr: nil,
expectedErr: nil,
Expand All @@ -1732,7 +1736,7 @@ func TestEnsureBackendPoolDeletedFromNodeVmssFlex(t *testing.T) {
"vmssflex1000001": "testvm1-nic",
},
backendPoolID: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/lb/backendAddressPools/backendpool-0",
nic: generateTestNic("testvm1-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1"),
nics: []network.Interface{generateTestNic("testvm1-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1")},
nicGetErr: &retry.Error{RawError: fmt.Errorf("failed to get nic")},
expectedErr: fmt.Errorf("ensureBackendPoolDeletedFromNode: failed to get interface of name testvm1-nic: Retriable: false, RetryAfter: 0s, HTTPStatusCode: 0, RawError: failed to get nic"),
},
Expand All @@ -1742,7 +1746,7 @@ func TestEnsureBackendPoolDeletedFromNodeVmssFlex(t *testing.T) {
"vmssflex1000001": "testvm1-nic",
},
backendPoolID: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/lb/backendAddressPools/backendpool-0",
nic: generateTestNic("testvm1-nic", false, network.ProvisioningStateFailed, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1"),
nics: []network.Interface{generateTestNic("testvm1-nic", false, network.ProvisioningStateFailed, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1")},
nicGetErr: nil,
expectedErr: nil,
},
Expand All @@ -1752,7 +1756,7 @@ func TestEnsureBackendPoolDeletedFromNodeVmssFlex(t *testing.T) {
"vmssflex1000001": "testvm1-nic",
},
backendPoolID: "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/lb/backendAddressPools/backendpool-0",
nic: generateTestNic("testvm1-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1"),
nics: []network.Interface{generateTestNic("testvm1-nic", false, network.ProvisioningStateSucceeded, "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/testvm1")},
expectedPutNICTimes: 1,
nicGetErr: nil,
nicPutErr: &retry.Error{RawError: fmt.Errorf("failed to update nic")},
Expand All @@ -1761,25 +1765,29 @@ func TestEnsureBackendPoolDeletedFromNodeVmssFlex(t *testing.T) {
}

for _, tc := range testCases {
fs, err := NewTestFlexScaleSet(ctrl)
assert.NoError(t, err, "unexpected error when creating test FlexScaleSet")
t.Run(tc.description, func(t *testing.T) {
fs, err := NewTestFlexScaleSet(ctrl)
assert.NoError(t, err, "unexpected error when creating test FlexScaleSet")

mockInterfacesClient := fs.InterfacesClient.(*mockinterfaceclient.MockInterface)
mockInterfacesClient.EXPECT().Get(gomock.Any(), gomock.Any(), "testvm1-nic", gomock.Any()).Return(tc.nic, tc.nicGetErr).AnyTimes()
mockInterfacesClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(tc.nicPutErr).Times(tc.expectedPutNICTimes)
mockInterfacesClient := fs.InterfacesClient.(*mockinterfaceclient.MockInterface)
for i := range tc.nics {
nic := tc.nics[i]
mockInterfacesClient.EXPECT().Get(gomock.Any(), gomock.Any(), *nic.Name, gomock.Any()).Return(nic, tc.nicGetErr).AnyTimes()
mockInterfacesClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), *nic.Name, gomock.Any()).Return(tc.nicPutErr).Times(tc.expectedPutNICTimes)
}

updated, err := fs.ensureBackendPoolDeletedFromNode(tc.vmssFlexVMNameMap, []string{tc.backendPoolID})
updated, err := fs.ensureBackendPoolDeletedFromNode(tc.vmssFlexVMNameMap, []string{tc.backendPoolID})

if tc.expectedErr != nil {
assert.EqualError(t, err, tc.expectedErr.Error(), tc.description)
} else {
assert.NoError(t, err, tc.description)
if tc.expectedPutNICTimes > 0 {
assert.True(t, updated, tc.description)
if tc.expectedErr != nil {
assert.EqualError(t, err, tc.expectedErr.Error())
} else {
assert.NoError(t, err)
if tc.expectedPutNICTimes > 0 {
assert.True(t, updated)
}
}
}
})
}

}

func TestEnsureBackendPoolDeletedVmssFlex(t *testing.T) {
Expand Down