Skip to content

Commit

Permalink
[VPC] Support NSXLB for VPC
Browse files Browse the repository at this point in the history
Signed-off-by: gran <gran@vmware.com>
  • Loading branch information
gran-vmv committed Jul 5, 2024
1 parent 6522fff commit 502a1ef
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 15 deletions.
7 changes: 7 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,10 @@ func (coeConfig *CoeConfig) validate() error {
func (nsxConfig *NsxConfig) ValidateConfigFromCmd() error {
return nsxConfig.validate(true)
}

func (nsxConfig *NsxConfig) NSXLBEnabled() bool {
if nsxConfig.UseAVILB == false && (nsxConfig.UseNativeLoadBalancer == nil || *nsxConfig.UseNativeLoadBalancer == true) {
return true
}
return false
}
7 changes: 4 additions & 3 deletions pkg/controllers/networkinfo/networkinfo_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (r *NetworkInfoReconciler) Reconcile(ctx context.Context, req ctrl.Request)
log.Error(err, "failed to check if namespace is shared", "Namespace", obj.GetNamespace())
return common.ResultRequeue, err
}
if !isShared {
if r.Service.NSXConfig.NsxConfig.UseAVILB && !isShared {
err = r.Service.CreateOrUpdateAVIRule(createdVpc, obj.Namespace)
if err != nil {
state := &v1alpha1.VPCState{
Expand Down Expand Up @@ -113,10 +113,11 @@ func (r *NetworkInfoReconciler) Reconcile(ctx context.Context, req ctrl.Request)
}
}

// TODO(gran) check if we need to query NSXLBSubnetInfo
// if lb vpc enabled, read avi subnet path and cidr
// nsx bug, if set LoadBalancerVpcEndpoint.Enabled to false, when read this vpc back,
// LoadBalancerVpcEndpoint.Enabled will become a nil pointer.
if createdVpc.LoadBalancerVpcEndpoint.Enabled != nil && *createdVpc.LoadBalancerVpcEndpoint.Enabled {
if r.Service.NSXConfig.NsxConfig.UseAVILB && createdVpc.LoadBalancerVpcEndpoint.Enabled != nil && *createdVpc.LoadBalancerVpcEndpoint.Enabled {
path, cidr, err = r.Service.GetAVISubnetInfo(*createdVpc)
if err != nil {
log.Error(err, "failed to read lb subnet path and cidr", "VPC", createdVpc.Id)
Expand All @@ -139,7 +140,7 @@ func (r *NetworkInfoReconciler) Reconcile(ctx context.Context, req ctrl.Request)
LoadBalancerIPAddresses: cidr,
PrivateIPv4CIDRs: nc.PrivateIPv4CIDRs,
}
updateSuccess(r, &ctx, obj, r.Client, state, nc.Name, path)
updateSuccess(r, &ctx, obj, r.Client, state, nc.Name, path, r.Service.GetNSXLBSPath(*createdVpc.Id))
} else {
if controllerutil.ContainsFinalizer(obj, commonservice.NetworkInfoFinalizerName) {
metrics.CounterInc(r.Service.NSXConfig, metrics.ControllerDeleteTotal, common.MetricResTypeNetworkInfo)
Expand Down
7 changes: 4 additions & 3 deletions pkg/controllers/networkinfo/networkinfo_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ func updateFail(r *NetworkInfoReconciler, c *context.Context, o *v1alpha1.Networ
}

func updateSuccess(r *NetworkInfoReconciler, c *context.Context, o *v1alpha1.NetworkInfo, client client.Client,
vpcState *v1alpha1.VPCState, ncName string, subnetPath string) {
vpcState *v1alpha1.VPCState, ncName string, subnetPath string, nsxLBSPath string) {
setNetworkInfoVPCStatus(c, o, client, vpcState)
// ako needs to know the avi subnet path created by nsx
setVPCNetworkConfigurationStatus(c, client, ncName, vpcState.Name, subnetPath)
setVPCNetworkConfigurationStatus(c, client, ncName, vpcState.Name, subnetPath, nsxLBSPath)
r.Recorder.Event(o, v1.EventTypeNormal, common.ReasonSuccessfulUpdate, "NetworkInfo CR has been successfully updated")
metrics.CounterInc(r.Service.NSXConfig, metrics.ControllerUpdateSuccessTotal, common.MetricResTypeNetworkInfo)
}
Expand All @@ -59,7 +59,7 @@ func setNetworkInfoVPCStatus(ctx *context.Context, networkInfo *v1alpha1.Network
}
}

func setVPCNetworkConfigurationStatus(ctx *context.Context, client client.Client, ncName string, vpcName string, aviSubnetPath string) {
func setVPCNetworkConfigurationStatus(ctx *context.Context, client client.Client, ncName string, vpcName string, aviSubnetPath string, nsxLBSPath string) {
// read v1alpha1.VPCNetworkConfiguration by ncName
nc := &v1alpha1.VPCNetworkConfiguration{}
err := client.Get(*ctx, apitypes.NamespacedName{Name: ncName}, nc)
Expand All @@ -69,6 +69,7 @@ func setVPCNetworkConfigurationStatus(ctx *context.Context, client client.Client
createdVPCInfo := &v1alpha1.VPCInfo{
Name: vpcName,
AVISESubnetPath: aviSubnetPath,
NSXLBSPath: nsxLBSPath,
}
// iterate through VPCNetworkConfiguration.Status.VPCs, if vpcName already exists, update it
for i, vpc := range nc.Status.VPCs {
Expand Down
3 changes: 3 additions & 0 deletions pkg/nsx/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type Client struct {
IPAllocationClient ip_pools.IpAllocationsClient
SubnetsClient vpcs.SubnetsClient
RealizedStateClient realized_state.RealizedEntitiesClient
VPCLBSClient vpcs.VpcLbsClient

NSXChecker NSXHealthChecker
NSXVerChecker NSXVersionChecker
Expand Down Expand Up @@ -163,6 +164,7 @@ func GetClient(cf *config.NSXOperatorConfig) *Client {
subnetsClient := vpcs.NewSubnetsClient(restConnector(cluster))
subnetStatusClient := subnets.NewStatusClient(restConnector(cluster))
realizedStateClient := realized_state.NewRealizedEntitiesClient(restConnector(cluster))
vpcLBSClient := vpcs.NewVpcLbsClient(restConnector(cluster))

vpcSecurityClient := vpcs.NewSecurityPoliciesClient(restConnector(cluster))
vpcRuleClient := vpc_sp.NewRulesClient(restConnector(cluster))
Expand Down Expand Up @@ -204,6 +206,7 @@ func GetClient(cf *config.NSXOperatorConfig) *Client {
SubnetStatusClient: subnetStatusClient,
VPCSecurityClient: vpcSecurityClient,
VPCRuleClient: vpcRuleClient,
VPCLBSClient: vpcLBSClient,

NSXChecker: *nsxChecker,
NSXVerChecker: *nsxVersionChecker,
Expand Down
1 change: 1 addition & 0 deletions pkg/nsx/services/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ var (
ResourceTypeVpc = "Vpc"
ResourceTypeSubnetPort = "VpcSubnetPort"
ResourceTypeVirtualMachine = "VirtualMachine"
ResourceTypeLBService = "LBService"
ResourceTypeShare = "Share"
ResourceTypeSharedResource = "SharedResource"
ResourceTypeChildSharedResource = "ChildSharedResource"
Expand Down
84 changes: 84 additions & 0 deletions pkg/nsx/services/common/wrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package common

import (
"github.com/openlyinc/pointy"
"github.com/vmware/vsphere-automation-sdk-go/runtime/data"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

// WrapInfra TODO(gran) refactor existing code in other package
func (service *Service) WrapInfra(children []*data.StructValue) (*model.Infra, error) {
// This is the outermost layer of the hierarchy infra client.
// It doesn't need ID field.
resourceType := ResourceTypeInfra
infraObj := model.Infra{
Children: children,
ResourceType: &resourceType,
}
return &infraObj, nil
}

func (service *Service) WrapOrgRoot(children []*data.StructValue) (*model.OrgRoot, error) {
resourceType := ResourceTypeOrgRoot
orgRootObj := model.OrgRoot{
Children: children,
ResourceType: &resourceType,
}
return &orgRootObj, nil
}

func (service *Service) WrapOrg(org string, children []*data.StructValue) ([]*data.StructValue, error) {
targetType := ResourceTypeOrg
return wrapChildResourceReference(targetType, org, children)
}

func (service *Service) WrapProject(nsxtProject string, children []*data.StructValue) ([]*data.StructValue, error) {
targetType := ResourceTypeProject
return wrapChildResourceReference(targetType, nsxtProject, children)
}

func wrapChildResourceReference(targetType, id string, children []*data.StructValue) ([]*data.StructValue, error) {
resourceType := ResourceTypeChildResourceReference
childProject := model.ChildResourceReference{
Id: &id,
ResourceType: resourceType,
TargetType: &targetType,
Children: children,
}
dataValue, errors := NewConverter().ConvertToVapi(childProject, childProject.GetType__())
if len(errors) > 0 {
return nil, errors[0]
}
return []*data.StructValue{dataValue.(*data.StructValue)}, nil

}

func (service *Service) WrapVPC(vpc *model.Vpc) ([]*data.StructValue, error) {
vpc.ResourceType = pointy.String(ResourceTypeVpc)
childVpc := model.ChildVpc{
Id: vpc.Id,
MarkedForDelete: vpc.MarkedForDelete,
ResourceType: "ChildVpc",
Vpc: vpc,
}
dataValue, errs := NewConverter().ConvertToVapi(childVpc, childVpc.GetType__())
if len(errs) > 0 {
return nil, errs[0]
}
return []*data.StructValue{dataValue.(*data.StructValue)}, nil
}

func (service *Service) WrapLBS(lbs *model.LBService) ([]*data.StructValue, error) {
lbs.ResourceType = pointy.String(ResourceTypeLBService)
childLBService := model.ChildLBService{
Id: lbs.Id,
MarkedForDelete: lbs.MarkedForDelete,
ResourceType: "ChildLBService",
LbService: lbs,
}
dataValue, errs := NewConverter().ConvertToVapi(childLBService, childLBService.GetType__())
if len(errs) > 0 {
return nil, errs[0]
}
return []*data.StructValue{dataValue.(*data.StructValue)}, nil
}
2 changes: 1 addition & 1 deletion pkg/nsx/services/realizestate/realize_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (service *RealizeStateService) CheckRealizeState(backoff wait.Backoff, inte
return err
}
for _, result := range results.Results {
if *result.EntityType != entityType {
if entityType != "" && *result.EntityType != entityType {
continue
}
if *result.State == model.GenericPolicyRealizedResource_STATE_REALIZED {
Expand Down
24 changes: 21 additions & 3 deletions pkg/nsx/services/vpc/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func buildPrivateIpBlock(networkInfo *v1alpha1.NetworkInfo, nsObj *v1.Namespace,
}

func buildNSXVPC(obj *v1alpha1.NetworkInfo, nsObj *v1.Namespace, nc common.VPCNetworkConfigInfo, cluster string, pathMap map[string]string,
nsxVPC *model.Vpc) (*model.Vpc,
nsxVPC *model.Vpc, useAVILB bool) (*model.Vpc,
error) {
vpc := &model.Vpc{}
if nsxVPC != nil {
Expand All @@ -61,7 +61,7 @@ func buildNSXVPC(obj *v1alpha1.NetworkInfo, nsObj *v1.Namespace, nc common.VPCNe
return nil, nil
}
// for updating vpc case, use current vpc id, name
vpc = nsxVPC
*vpc = *nsxVPC
} else {
// for creating vpc case, fill in vpc properties based on networkconfig
vpcName := util.GenerateDisplayName("", "vpc", obj.GetNamespace(), "", cluster)
Expand All @@ -76,7 +76,11 @@ func buildNSXVPC(obj *v1alpha1.NetworkInfo, nsObj *v1.Namespace, nc common.VPCNe
},
}
vpc.SiteInfos = siteInfos
vpc.LoadBalancerVpcEndpoint = &model.LoadBalancerVPCEndpoint{Enabled: &DefaultLoadBalancerVPCEndpointEnabled}
loadBalancerVPCEndpointEnabled := false
if useAVILB {
loadBalancerVPCEndpointEnabled = true
}
vpc.LoadBalancerVpcEndpoint = &model.LoadBalancerVPCEndpoint{Enabled: &loadBalancerVPCEndpointEnabled}
vpc.Tags = util.BuildBasicTags(cluster, obj, nsObj.UID)
}

Expand All @@ -89,3 +93,17 @@ func buildNSXVPC(obj *v1alpha1.NetworkInfo, nsObj *v1.Namespace, nc common.VPCNe

return vpc, nil
}

func buildNSXLBS(obj *v1alpha1.NetworkInfo, nsObj *v1.Namespace, cluster, lbsSize, vpcPath string, relaxScaleValidation *bool) (*model.LBService, error) {
lbs := &model.LBService{}
lbsName := util.GenerateDisplayName("", "vpc", nsObj.GetName(), "", cluster)
// LBS id should equal VPC id
lbs.Id = common.String(string(nsObj.GetUID()))
lbs.DisplayName = &lbsName
// TODO(gran) do we need "created_for" and "lb_t1_link_ip" tag?
lbs.Tags = util.BuildBasicTags(cluster, obj, nsObj.GetUID())
lbs.Size = &lbsSize
lbs.ConnectivityPath = &vpcPath
lbs.RelaxScaleValidation = relaxScaleValidation
return lbs, nil
}
18 changes: 18 additions & 0 deletions pkg/nsx/services/vpc/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func keyFunc(obj interface{}) (string, error) {
switch v := obj.(type) {
case *model.Vpc:
return *v.Id, nil
case *model.LBService:
return *v.Id, nil
case *model.IpAddressBlock:
return generateIPBlockKey(*v), nil
default:
Expand All @@ -27,6 +29,8 @@ func indexFunc(obj interface{}) ([]string, error) {
switch o := obj.(type) {
case *model.Vpc:
return filterTag(o.Tags), nil
case *model.LBService:
return filterTag(o.Tags), nil
case *model.IpAddressBlock:
return filterTag(o.Tags), nil
default:
Expand Down Expand Up @@ -148,6 +152,20 @@ func (is *IPBlockStore) GetByIndex(index string, value string) *model.IpAddressB
return block
}

// LBSStore is a store for LBS
type LBSStore struct {
common.ResourceStore
}

func (ls *LBSStore) GetByKey(key string) *model.LBService {
obj := ls.ResourceStore.GetByKey(key)
if obj != nil {
lbs := obj.(*model.LBService)
return lbs
}
return nil
}

// keyFuncAVI is used to get the key of a AVI rule related resource
func keyFuncAVI(obj interface{}) (string, error) {
switch v := obj.(type) {
Expand Down
Loading

0 comments on commit 502a1ef

Please sign in to comment.