From 694e089f9ead68a07343ecb986c425bcf0e83a93 Mon Sep 17 00:00:00 2001 From: Marwan Ahmed Date: Sun, 14 Jun 2020 20:17:24 -0700 Subject: [PATCH] switch scalesets to delete asynchronously without waiting on future --- .../cloudprovider/azure/azure_scale_set.go | 38 ++++++++++++++++--- .../azure/azure_scale_set_test.go | 6 +-- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/cluster-autoscaler/cloudprovider/azure/azure_scale_set.go b/cluster-autoscaler/cloudprovider/azure/azure_scale_set.go index e2b1bf0adbae..cc0301758a07 100644 --- a/cluster-autoscaler/cloudprovider/azure/azure_scale_set.go +++ b/cluster-autoscaler/cloudprovider/azure/azure_scale_set.go @@ -227,6 +227,29 @@ func (scaleSet *ScaleSet) GetScaleSetSize() (int64, error) { return scaleSet.getCurSize() } +func (scaleSet *ScaleSet) waitForDeleteInstances(future *azure.Future, requiredIds *compute.VirtualMachineScaleSetVMInstanceRequiredIDs) { + var err error + + defer func() { + if err != nil { + klog.Errorf("Failed to delete instances %v. Invalidating the cache to get the real scale set size", requiredIds.InstanceIds) + scaleSet.invalidateStatusCacheWithLock() + } + }() + + ctx, cancel := getContextWithCancel() + defer cancel() + + httpResponse, err := scaleSet.manager.azClient.virtualMachineScaleSetsClient.WaitForAsyncOperationResult(ctx, future) + isSuccess, err := isSuccessHTTPResponse(httpResponse, err) + if isSuccess { + klog.V(3).Infof("virtualMachineScaleSetsClient.WaitForAsyncOperationResult - DeleteInstances(%v) success", requiredIds.InstanceIds) + scaleSet.invalidateInstanceCache() + return + } + klog.Errorf("virtualMachineScaleSetsClient.WaitForAsyncOperationResult - DeleteInstances for instances %v failed with error: %v", requiredIds.InstanceIds, err) +} + // updateVMSSCapacity invokes virtualMachineScaleSetsClient to update the capacity for VMSS. func (scaleSet *ScaleSet) updateVMSSCapacity(future *azure.Future) { var err error @@ -428,6 +451,13 @@ func (scaleSet *ScaleSet) DeleteInstances(instances []*azureRef) error { ctx, cancel := getContextWithCancel() defer cancel() resourceGroup := scaleSet.manager.config.ResourceGroup + klog.V(3).Infof("Calling virtualMachineScaleSetsClient.DeleteInstancesAsync(%v)", requiredIds.InstanceIds) + + future, rerr := scaleSet.manager.azClient.virtualMachineScaleSetsClient.DeleteInstancesAsync(ctx, resourceGroup, commonAsg.Id(), *requiredIds) + if rerr != nil { + klog.Errorf("virtualMachineScaleSetsClient.DeleteInstancesAsync for instances %v failed: %v", requiredIds.InstanceIds, err) + return rerr.Error() + } // Proactively decrement scale set size so that we don't // go below minimum node count if cache data is stale @@ -435,12 +465,8 @@ func (scaleSet *ScaleSet) DeleteInstances(instances []*azureRef) error { scaleSet.curSize-- scaleSet.sizeMutex.Unlock() - rerr := scaleSet.manager.azClient.virtualMachineScaleSetsClient.DeleteInstances(ctx, resourceGroup, commonAsg.Id(), *requiredIds) - if rerr != nil { - klog.Errorf("Failed to delete instances %v. Invalidating the cache to get the real scale set size", requiredIds) - scaleSet.invalidateStatusCacheWithLock() - } - return rerr.Error() + go scaleSet.waitForDeleteInstances(future, requiredIds) + return nil } // DeleteNodes deletes the nodes from the group. diff --git a/cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go b/cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go index ec9e7d4df3a0..b62b255f7d7b 100644 --- a/cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go +++ b/cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go @@ -108,9 +108,6 @@ func TestTargetSize(t *testing.T) { assert.True(t, registered) assert.Equal(t, len(provider.NodeGroups()), 1) - ng := provider.NodeGroups()[0] - size, err := ng.TargetSize() - println(size) targetSize, err := provider.NodeGroups()[0].TargetSize() assert.NoError(t, err) assert.Equal(t, 3, targetSize) @@ -259,7 +256,8 @@ func TestDeleteNodes(t *testing.T) { mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) mockVMSSClient.EXPECT().List(gomock.Any(), manager.config.ResourceGroup).Return(expectedScaleSets, nil).AnyTimes() - mockVMSSClient.EXPECT().DeleteInstances(gomock.Any(), manager.config.ResourceGroup, gomock.Any(), gomock.Any()).Return(nil) + mockVMSSClient.EXPECT().DeleteInstancesAsync(gomock.Any(), manager.config.ResourceGroup, gomock.Any(), gomock.Any()).Return(nil, nil) + mockVMSSClient.EXPECT().WaitForAsyncOperationResult(gomock.Any(), gomock.Any()).Return(&http.Response{StatusCode: http.StatusOK}, nil).AnyTimes() manager.azClient.virtualMachineScaleSetsClient = mockVMSSClient mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) mockVMSSVMClient.EXPECT().List(gomock.Any(), manager.config.ResourceGroup, "test-asg", gomock.Any()).Return(expectedVMSSVMs, nil).AnyTimes()