From f0ad756e3d6d814eb053a65ef5da65e510c8f6b1 Mon Sep 17 00:00:00 2001 From: Yatin Karel Date: Wed, 1 Jul 2026 20:06:17 +0530 Subject: [PATCH] Fix OVN condition flapping during minor updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During minor updates, reconcileOVNControllers was called on every reconcile throughout all update phases, causing two issues: 1. OVNReadyCondition flapping: Since InitConditions() resets all conditions to Unknown on each reconcile, calling reconcileOVNControllers during later phases (RabbitMQ, Galera, etc.) could transiently flip OVNReadyCondition to False, blocking the OpenStackVersion controller from maintaining MinorUpdateOVNControlplane as True. 2. Metrics DaemonSet unnecessary restarts: reconcileOVNControllers passed an empty string for the metrics cert name, clearing the MetricsTLS fields on the OVNController CR. This changed the metrics config hash, causing two spurious DaemonSet rollouts — once when MetricsTLS was cleared during the update, and again when the normal reconcile path restored it after the update completed. Fix both by: - Skipping reconcileOVNControllers after the OVN controlplane phase completes, directly marking OVNReadyCondition True instead (needed because InitConditions() resets conditions each reconcile). - Passing the correct metrics cert name via EnsureOVNMetricsCert so MetricsTLS stays consistent when reconcileOVNControllers does run. There was another issue in ovn-operator for pre mature readiness, that is being fixed as part of https://github.com/openstack-k8s-operators/ovn-operator/pull/587 Related-Issue: https://redhat.atlassian.net/browse/OSPRH-31318 Assisted-By: Claude Signed-off-by: Yatin Karel --- .../core/openstackcontrolplane_controller.go | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/internal/controller/core/openstackcontrolplane_controller.go b/internal/controller/core/openstackcontrolplane_controller.go index 6797fec57a..a41d0cfd8b 100644 --- a/internal/controller/core/openstackcontrolplane_controller.go +++ b/internal/controller/core/openstackcontrolplane_controller.go @@ -315,16 +315,23 @@ func (r *OpenStackControlPlaneReconciler) Reconcile(ctx context.Context, req ctr } // OVN - Log.Info("Minor update OVN on the ControlPlane") - ctrlResult, err = r.reconcileOVNControllers(ctx, instance, version, helper) - if err != nil { - return ctrl.Result{}, err - } else if (ctrlResult != ctrl.Result{}) { - return ctrlResult, nil - } - instance.Status.DeployedOVNVersion = &version.Spec.TargetVersion + // Once the OVN controlplane phase is complete, skip reconcileOVNControllers to prevent + // transient OVN readiness changes from flapping OVNReadyCondition during + // later phases. We still need to mark OVNReadyCondition True because + // InitConditions() resets all conditions to Unknown on each reconcile. if !version.Status.Conditions.IsTrue(corev1beta1.OpenStackVersionMinorUpdateOVNControlplane) { + Log.Info("Minor update OVN on the ControlPlane") + ctrlResult, err = r.reconcileOVNControllers(ctx, instance, version, helper) + if err != nil { + return ctrl.Result{}, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + instance.Status.DeployedOVNVersion = &version.Spec.TargetVersion + // Wait for the OpenStackVersion controller to acknowledge OVN controlplane update return ctrlResult, nil + } else { + instance.Status.Conditions.MarkTrue(corev1beta1.OpenStackControlPlaneOVNReadyCondition, corev1beta1.OpenStackControlPlaneOVNReadyMessage) } // only if OVN dataplane is updated @@ -402,7 +409,15 @@ func (r *OpenStackControlPlaneReconciler) Reconcile(ctx context.Context, req ctr } func (r *OpenStackControlPlaneReconciler) reconcileOVNControllers(ctx context.Context, instance *corev1beta1.OpenStackControlPlane, version *corev1beta1.OpenStackVersion, helper *common_helper.Helper) (ctrl.Result, error) { - OVNControllerReady, OVNControllerConditions, err := openstack.ReconcileOVNController(ctx, instance, version, helper, "") + var ovnMetricsCertName string + if instance.Spec.TLS.PodLevel.Enabled { + var err error + ovnMetricsCertName, err = openstack.EnsureOVNMetricsCert(ctx, instance, helper) + if err != nil { + return ctrl.Result{}, err + } + } + OVNControllerReady, OVNControllerConditions, err := openstack.ReconcileOVNController(ctx, instance, version, helper, ovnMetricsCertName) if err != nil { return ctrl.Result{}, err } else if !OVNControllerReady {