From 516f1beb47435a1a2a3f7404b73044a4fc204d88 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 24 Jan 2024 14:01:14 -0800 Subject: [PATCH 1/3] error handling for lb vip out of range --- api/v1beta1/conditions_consts.go | 2 + .../azurestackhcicluster_controller.go | 2 +- .../azurestackhcicluster_reconciler.go | 2 +- .../azurestackhciloadbalancer_controller.go | 46 +++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/api/v1beta1/conditions_consts.go b/api/v1beta1/conditions_consts.go index 2cc8999..485b54a 100644 --- a/api/v1beta1/conditions_consts.go +++ b/api/v1beta1/conditions_consts.go @@ -66,6 +66,8 @@ const ( LoadBalancerMachineReconciliationFailedReason = "MachineReconciliationFailed" // LoadBalancerAddressUnavailableReason used when waiting for loadbalancer to have an address. LoadBalancerAddressUnavailableReason = "AddressUnavailable" + // LoadBalancerVIPOutOfRangeReason used when provided Load Balancer VIP is out of the vip address range. + LoadBalancerVIPOutOfRangeReason = "LoadBalancerVIPOutOfRange" // LoadBalancerNoReplicasReadyReason used when no replicas are in a ready state. LoadBalancerNoReplicasReadyReason = "NoReplicasReady" diff --git a/controllers/azurestackhcicluster_controller.go b/controllers/azurestackhcicluster_controller.go index c176c12..1ac31ef 100644 --- a/controllers/azurestackhcicluster_controller.go +++ b/controllers/azurestackhcicluster_controller.go @@ -423,4 +423,4 @@ func (r *AzureStackHCIClusterReconciler) reconcilePhase(clusterScope *scope.Clus if !azureStackHCICluster.DeletionTimestamp.IsZero() { azureStackHCICluster.Status.SetTypedPhase(infrav1.AzureStackHCIClusterPhaseDeleting) } -} +} \ No newline at end of file diff --git a/controllers/azurestackhcicluster_reconciler.go b/controllers/azurestackhcicluster_reconciler.go index 1d23751..39b8017 100644 --- a/controllers/azurestackhcicluster_reconciler.go +++ b/controllers/azurestackhcicluster_reconciler.go @@ -135,4 +135,4 @@ func (r *azureStackHCIClusterReconciler) createOrUpdateVnetName() { if r.scope.Vnet().Name == "" { r.scope.Vnet().Name = azurestackhci.GenerateVnetName(r.scope.Name()) } -} +} \ No newline at end of file diff --git a/controllers/azurestackhciloadbalancer_controller.go b/controllers/azurestackhciloadbalancer_controller.go index c6452f0..b3413de 100644 --- a/controllers/azurestackhciloadbalancer_controller.go +++ b/controllers/azurestackhciloadbalancer_controller.go @@ -20,6 +20,7 @@ package controllers import ( "context" "fmt" + "net" "time" "github.com/go-logr/logr" @@ -27,9 +28,11 @@ import ( azurestackhci "github.com/microsoft/cluster-api-provider-azurestackhci/cloud" "github.com/microsoft/cluster-api-provider-azurestackhci/cloud/scope" "github.com/microsoft/cluster-api-provider-azurestackhci/cloud/services/loadbalancers" + "github.com/microsoft/cluster-api-provider-azurestackhci/cloud/services/virtualnetworks" infrav1util "github.com/microsoft/cluster-api-provider-azurestackhci/pkg/util" "github.com/microsoft/moc-sdk-for-go/services/network" mocerrors "github.com/microsoft/moc/pkg/errors" + mocnet "github.com/microsoft/moc/pkg/net" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -223,6 +226,13 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileNormal(lbs *scope.LoadBal } } + err = r.reconcileLoadBalancerVIP(lbs, clusterScope) + if err != nil { + r.Recorder.Eventf(lbs.AzureStackHCILoadBalancer, corev1.EventTypeWarning, "FailureReconcileLBVIP", errors.Wrapf(err, "Failed to reconcile Load Balancer VIP").Error()) + conditions.MarkFalse(lbs.AzureStackHCILoadBalancer, infrav1.LoadBalancerInfrastructureReadyCondition, infrav1.LoadBalancerVIPOutOfRangeReason, clusterv1.ConditionSeverityError, err.Error()) + return reconcile.Result{}, err + } + // When a SDN integration is present, LB replica count will be 0 as the loadbalancing is handled by SDN. // So fail only if the configured replica count is not 0. if lbs.GetReplicas() != 0 && lbs.GetReadyReplicas() < 1 { @@ -370,3 +380,39 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileStatus(lbs *scope.LoadBal lbs.SetPhase(infrav1.AzureStackHCILoadBalancerPhaseProvisioned) } + +func (r *AzureStackHCILoadBalancerReconciler) reconcileLoadBalancerVIP(lbs *scope.LoadBalancerScope, clusterScope *scope.ClusterScope) error { + + lbs.Info("Attempting to get vnet for loadbalancer vip", "name", lbs.AzureStackHCILoadBalancer.Name) + vnetSpec := &virtualnetworks.Spec{ + Name: clusterScope.AzureStackHCICluster.Spec.NetworkSpec.Vnet.Name, + Group: clusterScope.AzureStackHCICluster.Spec.NetworkSpec.Vnet.Group, + } + vnetInterface, err := virtualnetworks.NewService(clusterScope).Get(clusterScope.Context, vnetSpec) + if err != nil { + return err + } + + vnet, ok := vnetInterface.(network.VirtualNetwork) + if !ok { + return errors.New("error getting virtualnetwork service") + } + + lbVIP := net.ParseIP(lbs.Address()) + + for _, subnet := range *vnet.Subnets { + for _, ippool := range subnet.IPPools { + + if (ippool.Type == network.VIPPOOL) { + startVIP := net.ParseIP(ippool.Start) + endVIP := net.ParseIP(ippool.End) + + if (mocnet.RangeContains(startVIP, endVIP, lbVIP)) { + return nil + } + } + } + } + + return errors.Errorf("Load Balancer VIP out of VIP Pool range.")// LB VIP: %s Start: %s End: %s", controlPlaneHost, ippool.Start, ippool.End) +} \ No newline at end of file From 3e841ea0ec7ee38fbf650740d86d418e27c3e560 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 29 Jan 2024 14:45:29 -0800 Subject: [PATCH 2/3] clean up --- controllers/azurestackhcicluster_controller.go | 2 +- controllers/azurestackhcicluster_reconciler.go | 2 +- controllers/azurestackhciloadbalancer_controller.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/controllers/azurestackhcicluster_controller.go b/controllers/azurestackhcicluster_controller.go index 1ac31ef..c176c12 100644 --- a/controllers/azurestackhcicluster_controller.go +++ b/controllers/azurestackhcicluster_controller.go @@ -423,4 +423,4 @@ func (r *AzureStackHCIClusterReconciler) reconcilePhase(clusterScope *scope.Clus if !azureStackHCICluster.DeletionTimestamp.IsZero() { azureStackHCICluster.Status.SetTypedPhase(infrav1.AzureStackHCIClusterPhaseDeleting) } -} \ No newline at end of file +} diff --git a/controllers/azurestackhcicluster_reconciler.go b/controllers/azurestackhcicluster_reconciler.go index 39b8017..1d23751 100644 --- a/controllers/azurestackhcicluster_reconciler.go +++ b/controllers/azurestackhcicluster_reconciler.go @@ -135,4 +135,4 @@ func (r *azureStackHCIClusterReconciler) createOrUpdateVnetName() { if r.scope.Vnet().Name == "" { r.scope.Vnet().Name = azurestackhci.GenerateVnetName(r.scope.Name()) } -} \ No newline at end of file +} diff --git a/controllers/azurestackhciloadbalancer_controller.go b/controllers/azurestackhciloadbalancer_controller.go index b3413de..f9b1664 100644 --- a/controllers/azurestackhciloadbalancer_controller.go +++ b/controllers/azurestackhciloadbalancer_controller.go @@ -414,5 +414,5 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileLoadBalancerVIP(lbs *scop } } - return errors.Errorf("Load Balancer VIP out of VIP Pool range.")// LB VIP: %s Start: %s End: %s", controlPlaneHost, ippool.Start, ippool.End) + return errors.Errorf("Load Balancer VIP out of VIP Pool range.") } \ No newline at end of file From 11a21e5a55ec346026182a6b0b31fff42771fced Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 29 Jan 2024 15:15:06 -0800 Subject: [PATCH 3/3] gofmt --- controllers/azurestackhciloadbalancer_controller.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/controllers/azurestackhciloadbalancer_controller.go b/controllers/azurestackhciloadbalancer_controller.go index f9b1664..3c7888b 100644 --- a/controllers/azurestackhciloadbalancer_controller.go +++ b/controllers/azurestackhciloadbalancer_controller.go @@ -385,7 +385,7 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileLoadBalancerVIP(lbs *scop lbs.Info("Attempting to get vnet for loadbalancer vip", "name", lbs.AzureStackHCILoadBalancer.Name) vnetSpec := &virtualnetworks.Spec{ - Name: clusterScope.AzureStackHCICluster.Spec.NetworkSpec.Vnet.Name, + Name: clusterScope.AzureStackHCICluster.Spec.NetworkSpec.Vnet.Name, Group: clusterScope.AzureStackHCICluster.Spec.NetworkSpec.Vnet.Group, } vnetInterface, err := virtualnetworks.NewService(clusterScope).Get(clusterScope.Context, vnetSpec) @@ -403,11 +403,11 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileLoadBalancerVIP(lbs *scop for _, subnet := range *vnet.Subnets { for _, ippool := range subnet.IPPools { - if (ippool.Type == network.VIPPOOL) { + if ippool.Type == network.VIPPOOL { startVIP := net.ParseIP(ippool.Start) endVIP := net.ParseIP(ippool.End) - if (mocnet.RangeContains(startVIP, endVIP, lbVIP)) { + if mocnet.RangeContains(startVIP, endVIP, lbVIP) { return nil } } @@ -415,4 +415,4 @@ func (r *AzureStackHCILoadBalancerReconciler) reconcileLoadBalancerVIP(lbs *scop } return errors.Errorf("Load Balancer VIP out of VIP Pool range.") -} \ No newline at end of file +}