Skip to content

Commit b153b78

Browse files
authored
Fetch Subnet totalip for each SubnetPort creation (#1380)
This PR fixes 2 issues for the current Subnet totalIP calculation - We only fetch the Subnet totalIP for DHCP_DEACTIVATED Subnet with StaticIPAllocation enabled once at the first SubnetPort is created on the Subnet, but when Subnet IPReservation is created or delete, the Subnet totalIP will change. Thus we need to get the totalIP for such Subnet every time when a SubnetPort is created. - When shared Subnet is removed from cache, the Port count info of the Subnet should be deleted. Signed-off-by: Yanjun Zhou <yanjun.zhou@broadcom.com>
1 parent 4414ee7 commit b153b78

File tree

14 files changed

+122
-26
lines changed

14 files changed

+122
-26
lines changed

cmd/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ func startServiceController(mgr manager.Manager, nsxClient *nsx.Client) {
206206
os.Exit(1)
207207
}
208208
}
209-
subnetIPReservationService, err := subnetipreservationservice.InitializeService(commonService)
209+
subnetIPReservationService, err := subnetipreservationservice.InitializeService(commonService, subnetPortService)
210210
if err != nil {
211211
log.Error(err, "Failed to initialize SubnetIPReservation commonService", "controller", "SubnetIPReservation")
212212
os.Exit(1)
@@ -230,7 +230,7 @@ func startServiceController(mgr manager.Manager, nsxClient *nsx.Client) {
230230
reconcilerList = append(
231231
reconcilerList,
232232
networkinfocontroller.NewNetworkInfoReconciler(mgr, vpcService, ipblocksInfoService),
233-
namespacecontroller.NewNamespaceReconciler(mgr, cf, vpcService, subnetService),
233+
namespacecontroller.NewNamespaceReconciler(mgr, cf, vpcService, subnetService, subnetPortService),
234234
subnet.NewSubnetReconciler(mgr, subnetService, subnetPortService, vpcService, subnetBindingService),
235235
subnetSetReconcile,
236236
node.NewNodeReconciler(mgr, nodeService),

pkg/clean/clean.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ func InitializeCleanupService(cf *config.NSXOperatorConfig, nsxClient *nsx.Clien
115115
if err != nil {
116116
return nil, err
117117
}
118+
subnetPortService, err := subnetport.InitializeSubnetPort(commonService, vpcService, ipAddressAllocationService)
119+
if err != nil {
120+
return nil, err
121+
}
118122

119123
// initialize all the CR services
120124
// Use Fluent Interface to escape error check hell
@@ -141,9 +145,9 @@ func InitializeCleanupService(cf *config.NSXOperatorConfig, nsxClient *nsx.Clien
141145
}
142146
}
143147

144-
wrapInitializeSubnetPort := func(service common.Service) cleanupFunc {
148+
wrapInitializeSubnetPort := func(_ common.Service) cleanupFunc {
145149
return func() (interface{}, error) {
146-
return subnetport.InitializeSubnetPort(service, vpcService, ipAddressAllocationService)
150+
return subnetPortService, nil
147151
}
148152
}
149153
wrapInitializeIPAddressAllocation := func(service common.Service) cleanupFunc {
@@ -158,7 +162,7 @@ func InitializeCleanupService(cf *config.NSXOperatorConfig, nsxClient *nsx.Clien
158162
}
159163
wrapInitializeSubnetIPReservation := func(service common.Service) cleanupFunc {
160164
return func() (interface{}, error) {
161-
return subnetipreservation.InitializeService(service)
165+
return subnetipreservation.InitializeService(service, subnetPortService)
162166
}
163167
}
164168

pkg/controllers/namespace/namespace_controller.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type NamespaceReconciler struct {
4747
NSXConfig *config.NSXOperatorConfig
4848
VPCService types.VPCServiceProvider
4949
SubnetService *subnet.SubnetService
50+
SubnetPortService types.SubnetPortServiceProvider
5051
Recorder record.EventRecorder
5152
SubnetStatusUpdater common.StatusUpdater
5253
}
@@ -357,15 +358,16 @@ func (r *NamespaceReconciler) StartController(mgr ctrl.Manager, _ webhook.Server
357358
}
358359

359360
func NewNamespaceReconciler(mgr ctrl.Manager, cf *config.NSXOperatorConfig, vpcService types.VPCServiceProvider,
360-
subnetService *subnet.SubnetService) *NamespaceReconciler {
361+
subnetService *subnet.SubnetService, subnetportService types.SubnetPortServiceProvider) *NamespaceReconciler {
361362
nsReconciler := &NamespaceReconciler{
362-
Client: mgr.GetClient(),
363-
APIReader: mgr.GetAPIReader(),
364-
Scheme: mgr.GetScheme(),
365-
NSXConfig: cf,
366-
VPCService: vpcService,
367-
SubnetService: subnetService,
368-
Recorder: mgr.GetEventRecorderFor("namespace-controller"),
363+
Client: mgr.GetClient(),
364+
APIReader: mgr.GetAPIReader(),
365+
Scheme: mgr.GetScheme(),
366+
NSXConfig: cf,
367+
VPCService: vpcService,
368+
SubnetService: subnetService,
369+
SubnetPortService: subnetportService,
370+
Recorder: mgr.GetEventRecorderFor("namespace-controller"),
369371
}
370372
nsReconciler.SubnetStatusUpdater = common.NewStatusUpdater(nsReconciler.Client, nsReconciler.SubnetService.NSXConfig, nsReconciler.Recorder, MetricResTypeSubnet, "Subnet", "Subnet")
371373
return nsReconciler

pkg/controllers/namespace/namespace_controller_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
_ "github.com/vmware-tanzu/nsx-operator/pkg/nsx/ratelimiter"
3636
servicetypes "github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
3737
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/subnet"
38+
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/subnetport"
3839
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/vpc"
3940
"github.com/vmware-tanzu/nsx-operator/pkg/util"
4041
)
@@ -294,6 +295,11 @@ func TestNamespaceReconciler_StartController(t *testing.T) {
294295
Client: fakeClient,
295296
},
296297
}
298+
subnetportService := &subnetport.SubnetPortService{
299+
Service: servicetypes.Service{
300+
Client: fakeClient,
301+
},
302+
}
297303
mockMgr := &MockManager{scheme: runtime.NewScheme(), client: fakeClient, apiReader: fakeAPIReader}
298304
patches := gomonkey.ApplyFunc((*NamespaceReconciler).setupWithManager, func(r *NamespaceReconciler, mgr manager.Manager) error {
299305
return nil
@@ -302,7 +308,7 @@ func TestNamespaceReconciler_StartController(t *testing.T) {
302308
return
303309
})
304310
defer patches.Reset()
305-
r := NewNamespaceReconciler(mockMgr, nil, vpcService, subnetService)
311+
r := NewNamespaceReconciler(mockMgr, nil, vpcService, subnetService, subnetportService)
306312
err := r.StartController(mockMgr, nil)
307313
assert.Nil(t, err)
308314
}

pkg/controllers/namespace/subnet_share_controller.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,13 @@ func (r *NamespaceReconciler) deleteUnusedSharedSubnets(ctx context.Context, ns
334334

335335
// Clear the cache to prevent stale data when the subnet is recreated on NSX
336336
r.SubnetService.RemoveSubnetFromCache(associatedResource, "shared subnet CR deleted")
337-
337+
subnetPath, err := servicecommon.GetSubnetPathFromAssociatedResource(associatedResource)
338+
if err != nil {
339+
log.Error(err, "Invalid associatedResource", "associatedResource", associatedResource)
340+
return err
341+
} else {
342+
r.SubnetPortService.DeletePortCount(subnetPath)
343+
}
338344
log.Info("Deleted Subnet CR for shared Subnet",
339345
"Namespace", ns, "Name", subnet.Name, "AssociatedResource", associatedResource)
340346
r.SubnetStatusUpdater.DeleteSuccess(client.ObjectKey{Namespace: ns, Name: subnet.Name}, subnet)

pkg/controllers/namespace/subnet_share_controller_test.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/vmware-tanzu/nsx-operator/pkg/nsx"
3030
servicecommon "github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
3131
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/subnet"
32+
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/subnetport"
3233
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/vpc"
3334
)
3435

@@ -73,13 +74,22 @@ func createTestNamespaceReconciler(objs []client.Object) *NamespaceReconciler {
7374
},
7475
}
7576

77+
subnetPortService := &subnetport.SubnetPortService{
78+
Service: servicecommon.Service{
79+
Client: fakeClient,
80+
NSXClient: &nsx.Client{},
81+
NSXConfig: nsxConfig,
82+
},
83+
}
84+
7685
nsReconciler := &NamespaceReconciler{
77-
Client: fakeClient,
78-
APIReader: fakeClient,
79-
Scheme: newScheme,
80-
VPCService: vpcService,
81-
SubnetService: subnetService,
82-
NSXConfig: nsxConfig,
86+
Client: fakeClient,
87+
APIReader: fakeClient,
88+
Scheme: newScheme,
89+
VPCService: vpcService,
90+
SubnetService: subnetService,
91+
SubnetPortService: subnetPortService,
92+
NSXConfig: nsxConfig,
8393
}
8494
nsReconciler.SubnetStatusUpdater = common.NewStatusUpdater(nsReconciler.Client, nsReconciler.SubnetService.NSXConfig, nil, "Subnet", "Subnet", "Subnet")
8595
return nsReconciler
@@ -673,6 +683,7 @@ func TestProcessNewSharedSubnets(t *testing.T) {
673683

674684
func TestDeleteUnusedSharedSubnets(t *testing.T) {
675685
// Test cases
686+
var subnetportService *subnetport.SubnetPortService
676687
tests := []struct {
677688
name string
678689
existingSubnets []client.Object
@@ -715,6 +726,7 @@ func TestDeleteUnusedSharedSubnets(t *testing.T) {
715726
func(_ *NamespaceReconciler, _ context.Context, _ string, _ *v1alpha1.Subnet, _ string) (bool, error) {
716727
return false, nil
717728
})
729+
patches.ApplyMethod(reflect.TypeOf(subnetportService), "DeletePortCount", func(_ servicecommon.SubnetPortServiceProvider, subnetPath string) {})
718730
return patches
719731
},
720732
},
@@ -775,6 +787,7 @@ func TestDeleteUnusedSharedSubnets(t *testing.T) {
775787
// Only subnet-1 has references
776788
return subnet.Name == "subnet-1", nil
777789
})
790+
patches.ApplyMethod(reflect.TypeOf(subnetportService), "DeletePortCount", func(_ servicecommon.SubnetPortServiceProvider, subnetPath string) {})
778791
return patches
779792
},
780793
},

pkg/controllers/subnet/subnet_poll.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"sigs.k8s.io/controller-runtime/pkg/reconcile"
1414

1515
"github.com/vmware-tanzu/nsx-operator/pkg/apis/vpc/v1alpha1"
16+
servicecommon "github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
1617
)
1718

1819
var ticker = time.NewTicker(10 * time.Minute)
@@ -81,6 +82,12 @@ func (r *SubnetReconciler) pollAllSharedSubnets() {
8182
if _, ok := r.SubnetService.SharedSubnetResourceMap[associatedResource]; !ok {
8283
log.Debug("Remove Subnet from cache", "AssociatedResource", associatedResource)
8384
r.SubnetService.RemoveSubnetFromCache(associatedResource, "no valid subnets")
85+
subnetPath, err := servicecommon.GetSubnetPathFromAssociatedResource(associatedResource)
86+
if err != nil {
87+
log.Error(err, "Invalid associatedResource", "associatedResource", associatedResource)
88+
} else {
89+
r.SubnetPortService.DeletePortCount(subnetPath)
90+
}
8491
}
8592
}
8693
}
@@ -197,6 +204,12 @@ func (r *SubnetReconciler) handleNSXSubnetError(ctx context.Context, err error,
197204
errorType string) {
198205
log.Error(err, fmt.Sprintf("Failed to get %s", errorType), "AssociatedResource", associatedResource)
199206
r.SubnetService.RemoveSubnetFromCache(associatedResource, "NSXSubnetError")
207+
subnetPath, err := servicecommon.GetSubnetPathFromAssociatedResource(associatedResource)
208+
if err != nil {
209+
log.Error(err, "Invalid associatedResource", "associatedResource", associatedResource)
210+
} else {
211+
r.SubnetPortService.DeletePortCount(subnetPath)
212+
}
200213
// Set subnet ready status to false for all valid subnets
201214
for namespacedName := range validSubnets {
202215
r.updateSharedSubnetWithError(ctx, namespacedName, err, errorType)

pkg/controllers/subnet/subnet_poll_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/vmware-tanzu/nsx-operator/pkg/apis/vpc/v1alpha1"
1919
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
2020
subnetservice "github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/subnet"
21+
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/subnetport"
2122
)
2223

2324
func TestHasSubnetSpecChanged(t *testing.T) {
@@ -689,12 +690,22 @@ func TestPollAllSharedSubnets(t *testing.T) {
689690
sharedSubnetsMap map[string][]types.NamespacedName
690691
expectedUniqueResources int // Number of unique associated resources
691692
expectedEnqueueCalls int // Number of times enqueueSubnetForReconciliation should be called
693+
initialCache map[string]struct {
694+
Subnet *model.VpcSubnet
695+
StatusList []model.VpcSubnetStatus
696+
}
692697
}{
693698
{
694699
name: "Empty shared subnets map",
695700
sharedSubnetsMap: map[string][]types.NamespacedName{},
696701
expectedUniqueResources: 0,
697702
expectedEnqueueCalls: 0,
703+
initialCache: map[string]struct {
704+
Subnet *model.VpcSubnet
705+
StatusList []model.VpcSubnetStatus
706+
}{
707+
"project1:vpc1:subnet1": {Subnet: &model.VpcSubnet{}},
708+
},
698709
},
699710
{
700711
name: "One shared subnet",
@@ -749,6 +760,7 @@ func TestPollAllSharedSubnets(t *testing.T) {
749760
}
750761

751762
r := createFakeSubnetReconciler(subnetCRs)
763+
r.SubnetService.NSXSubnetCache = tt.initialCache
752764

753765
// Set up the SharedSubnetResourceMap
754766
for associatedResource, namespacedNames := range tt.sharedSubnetsMap {
@@ -802,6 +814,9 @@ func TestPollAllSharedSubnets(t *testing.T) {
802814
enqueueSubnetCalls[namespacedName] = true
803815
})
804816

817+
var subnetportService *subnetport.SubnetPortService
818+
patches.ApplyMethod(reflect.TypeOf(subnetportService), "DeletePortCount", func(_ common.SubnetPortServiceProvider, subnetPath string) {})
819+
805820
// Call the actual function being tested
806821
r.pollAllSharedSubnets()
807822

pkg/mock/services_mock.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ func (m *MockSubnetPortServiceProvider) GetSubnetPathForSubnetPortFromStore(crUi
164164
return args.String(0)
165165
}
166166

167+
func (m *MockSubnetPortServiceProvider) ResetSubnetTotalIP(path string) {
168+
return
169+
}
170+
167171
type MockIPAddressAllocationProvider struct {
168172
mock.Mock
169173
}

pkg/nsx/services/common/services.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type SubnetPortServiceProvider interface {
4949
IsEmptySubnet(path string) bool
5050
DeletePortCount(path string)
5151
GetSubnetPathForSubnetPortFromStore(crUid types.UID) string
52+
ResetSubnetTotalIP(path string)
5253
}
5354

5455
type NodeServiceReader interface {

0 commit comments

Comments
 (0)