Skip to content

Commit ee07591

Browse files
Merge pull request #792 from dprince/ovn_update_order_edpm
Enforce update order for OVN for Ctlplane/EDPM
2 parents 114839d + ae9065e commit ee07591

30 files changed

+591
-48
lines changed

config/rbac/role.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ rules:
180180
- get
181181
- patch
182182
- update
183+
- apiGroups:
184+
- dataplane.openstack.org
185+
resources:
186+
- openstackdataplanenodesets
187+
verbs:
188+
- get
189+
- list
190+
- watch
183191
- apiGroups:
184192
- designate.openstack.org
185193
resources:

controllers/core/openstackcontrolplane_controller.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,9 @@ func (r *OpenStackControlPlaneReconciler) Reconcile(ctx context.Context, req ctr
245245
}
246246
instance.Status.DeployedOVNVersion = &version.Spec.TargetVersion
247247
return ctrl.Result{}, nil
248-
} else if !version.Status.Conditions.IsTrue(corev1beta1.OpenStackVersionMinorUpdateControlplane) {
248+
} else if version.Status.Conditions.IsTrue(corev1beta1.OpenStackVersionMinorUpdateOVNDataplane) &&
249+
!version.Status.Conditions.IsTrue(corev1beta1.OpenStackVersionMinorUpdateControlplane) {
250+
249251
Log.Info("Minor update on the ControlPlane")
250252
ctrlResult, err := r.reconcileNormal(ctx, instance, version, helper)
251253
if err != nil {

controllers/core/openstackversion_controller.go

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3333

3434
"github.com/go-logr/logr"
35+
dataplanev1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1"
3536
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
3637
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
3738
corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1"
@@ -56,16 +57,6 @@ func SetupVersionDefaults() {
5657
envContainerImages = localVars
5758
}
5859

59-
func compareStringPointers(a, b *string) bool {
60-
if a == nil && b == nil {
61-
return true
62-
}
63-
if a == nil || b == nil {
64-
return false
65-
}
66-
return *a == *b
67-
}
68-
6960
// OpenStackVersionReconciler reconciles a OpenStackVersion object
7061
type OpenStackVersionReconciler struct {
7162
client.Client
@@ -79,9 +70,11 @@ func (r *OpenStackVersionReconciler) GetLogger(ctx context.Context) logr.Logger
7970
return log.FromContext(ctx).WithName("Controllers").WithName("OpenStackVersion")
8071
}
8172

82-
//+kubebuilder:rbac:groups=core.openstack.org,resources=openstackversions,verbs=get;list;watch;create;update;patch;delete
83-
//+kubebuilder:rbac:groups=core.openstack.org,resources=openstackversions/status,verbs=get;update;patch
84-
//+kubebuilder:rbac:groups=core.openstack.org,resources=openstackversions/finalizers,verbs=update
73+
// +kubebuilder:rbac:groups=core.openstack.org,resources=openstackversions,verbs=get;list;watch;create;update;patch;delete
74+
// +kubebuilder:rbac:groups=core.openstack.org,resources=openstackversions/status,verbs=get;update;patch
75+
// +kubebuilder:rbac:groups=core.openstack.org,resources=openstackversions/finalizers,verbs=update
76+
// +kubebuilder:rbac:groups=core.openstack.org,resources=openstackcontrolplanes,verbs=get;list;watch
77+
// +kubebuilder:rbac:groups=dataplane.openstack.org,resources=openstackdataplanenodesets,verbs=get;list;watch
8578

8679
// Reconcile is part of the main kubernetes reconciliation loop which aims to
8780
// move the current state of the cluster closer to the desired state.
@@ -159,10 +152,10 @@ func (r *OpenStackVersionReconciler) Reconcile(ctx context.Context, req ctrl.Req
159152
// no minor update conditions unless we have a deployed version
160153
if instance.Status.DeployedVersion != nil && instance.Spec.TargetVersion != *instance.Status.DeployedVersion {
161154
cl = append(cl, *condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateOVNControlplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)),
162-
*condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateControlplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)))
163-
// fixme add dataplane conditions here
164-
//condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateOVNDataplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)),
165-
//condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateDataplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)))
155+
*condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateOVNDataplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)),
156+
*condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateControlplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)),
157+
*condition.UnknownCondition(corev1beta1.OpenStackVersionMinorUpdateDataplane, condition.InitReason, string(corev1beta1.OpenStackVersionMinorUpdateInitMessage)),
158+
)
166159
}
167160
instance.Status.Conditions.Init(&cl)
168161
instance.Status.ObservedGeneration = instance.Generation
@@ -182,13 +175,14 @@ func (r *OpenStackVersionReconciler) Reconcile(ctx context.Context, req ctrl.Req
182175

183176
instance.Status.AvailableVersion = &envAvailableVersion
184177
defaults := openstack.InitializeOpenStackVersionImageDefaults(ctx, envContainerImages)
185-
// store the defaults for the currently available version
186178
if instance.Status.ContainerImageVersionDefaults == nil {
187179
instance.Status.ContainerImageVersionDefaults = make(map[string]*corev1beta1.ContainerDefaults)
188180
}
181+
// store the defaults for the currently available version
189182
instance.Status.ContainerImageVersionDefaults[envAvailableVersion] = defaults
190183

191184
// calculate the container images for the target version
185+
Log.Info("Target version: ", "targetVersion", instance.Spec.TargetVersion)
192186
val, ok := instance.Status.ContainerImageVersionDefaults[instance.Spec.TargetVersion]
193187
if !ok {
194188
Log.Info("Target version not found in defaults", "targetVersion", instance.Spec.TargetVersion)
@@ -208,25 +202,30 @@ func (r *OpenStackVersionReconciler) Reconcile(ctx context.Context, req ctrl.Req
208202
Name: instance.Name,
209203
}, controlPlane)
210204
if err != nil {
211-
// we ignore not found
212205
if k8s_errors.IsNotFound(err) {
213-
Log.Info("No controlplane found.")
206+
Log.Info("Controlplane not found:", "instance name", instance.Name)
214207
return ctrl.Result{}, nil
215208
}
216209
return ctrl.Result{}, err
217210
}
218211

219-
// greenfield deployment //FIXME check dataplane here too
220-
if controlPlane.Status.DeployedVersion == nil {
221-
Log.Info("No controlplane or controlplane is not deployed")
222-
return ctrl.Result{}, nil
212+
// lookup nodesets
213+
dataplaneNodesets, err := openstack.GetDataplaneNodesets(ctx, controlPlane, versionHelper)
214+
if err != nil {
215+
Log.Error(err, "Failed to get dataplane nodesets")
216+
return ctrl.Result{}, err
223217
}
224218

225-
// TODO minor update for OVN Dataplane in progress
219+
// greenfield deployment
220+
if controlPlane.Status.DeployedVersion == nil && !openstack.DataplaneNodesetsDeployedVersionIsSet(dataplaneNodesets) {
221+
Log.Info("Waiting for controlplane and dataplane nodesets to be deployed.")
222+
return ctrl.Result{}, nil
223+
}
226224

227-
// minor update for OVN Controlplane in progress
225+
// minor update in progress
228226
if instance.Status.DeployedVersion != nil && instance.Spec.TargetVersion != *instance.Status.DeployedVersion {
229-
if !compareStringPointers(controlPlane.Status.ContainerImages.OvnControllerImage, instance.Status.ContainerImages.OvnControllerImage) ||
227+
228+
if !openstack.OVNControllerImageMatch(controlPlane, instance) ||
230229
!controlPlane.Status.Conditions.IsTrue(corev1beta1.OpenStackControlPlaneOVNReadyCondition) {
231230
instance.Status.Conditions.Set(condition.FalseCondition(
232231
corev1beta1.OpenStackVersionMinorUpdateOVNControlplane,
@@ -240,10 +239,22 @@ func (r *OpenStackVersionReconciler) Reconcile(ctx context.Context, req ctrl.Req
240239
corev1beta1.OpenStackVersionMinorUpdateOVNControlplane,
241240
corev1beta1.OpenStackVersionMinorUpdateReadyMessage)
242241

242+
// minor update for Dataplane OVN
243+
if !openstack.DataplaneNodesetsOVNControllerImagesMatch(instance, dataplaneNodesets) {
244+
instance.Status.Conditions.Set(condition.FalseCondition(
245+
corev1beta1.OpenStackVersionMinorUpdateOVNDataplane,
246+
condition.RequestedReason,
247+
condition.SeverityInfo,
248+
corev1beta1.OpenStackVersionMinorUpdateReadyRunningMessage))
249+
Log.Info("Waiting on OVN Dataplane updates to complete")
250+
return ctrl.Result{}, nil
251+
}
252+
instance.Status.Conditions.MarkTrue(
253+
corev1beta1.OpenStackVersionMinorUpdateOVNDataplane,
254+
corev1beta1.OpenStackVersionMinorUpdateReadyMessage)
255+
243256
// minor update for Controlplane in progress
244-
// we only check keystone here as it will only get updated during this phase
245-
// FIXME: add checks to all images on the Controlplane here once conditions and observedGeneration work are finished
246-
if !compareStringPointers(controlPlane.Status.ContainerImages.KeystoneAPIImage, instance.Status.ContainerImages.KeystoneAPIImage) ||
257+
if !openstack.ControlplaneContainerImageMatch(controlPlane, instance) ||
247258
!controlPlane.IsReady() {
248259
instance.Status.Conditions.Set(condition.FalseCondition(
249260
corev1beta1.OpenStackVersionMinorUpdateControlplane,
@@ -253,11 +264,23 @@ func (r *OpenStackVersionReconciler) Reconcile(ctx context.Context, req ctrl.Req
253264
Log.Info("Minor update for Controlplane in progress")
254265
return ctrl.Result{}, nil
255266
}
256-
// TODO minor update for Dataplane in progress goes here
257-
258267
instance.Status.Conditions.MarkTrue(
259268
corev1beta1.OpenStackVersionMinorUpdateControlplane,
260269
corev1beta1.OpenStackVersionMinorUpdateReadyMessage)
270+
271+
if !openstack.DataplaneNodesetsDeployed(instance, dataplaneNodesets) {
272+
instance.Status.Conditions.Set(condition.FalseCondition(
273+
corev1beta1.OpenStackVersionMinorUpdateDataplane,
274+
condition.RequestedReason,
275+
condition.SeverityInfo,
276+
corev1beta1.OpenStackVersionMinorUpdateReadyRunningMessage))
277+
Log.Info("Waiting on Dataplane update to complete")
278+
return ctrl.Result{}, nil
279+
}
280+
281+
instance.Status.Conditions.MarkTrue(
282+
corev1beta1.OpenStackVersionMinorUpdateDataplane,
283+
corev1beta1.OpenStackVersionMinorUpdateReadyMessage)
261284
}
262285

263286
if controlPlane.IsReady() {
@@ -301,6 +324,7 @@ func (r *OpenStackVersionReconciler) SetupWithManager(mgr ctrl.Manager) error {
301324

302325
return ctrl.NewControllerManagedBy(mgr).
303326
Watches(&corev1beta1.OpenStackControlPlane{}, versionFunc).
327+
Watches(&dataplanev1.OpenStackDataPlaneNodeSet{}, versionFunc).
304328
For(&corev1beta1.OpenStackVersion{}).
305329
Complete(r)
306330
}

pkg/openstack/barbican.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
3333
}
3434
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneBarbicanReadyCondition)
3535
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneExposeBarbicanReadyCondition)
36+
instance.Status.ContainerImages.BarbicanAPIImage = nil
37+
instance.Status.ContainerImages.BarbicanWorkerImage = nil
38+
instance.Status.ContainerImages.BarbicanKeystoneListenerImage = nil
3639
return ctrl.Result{}, nil
3740
}
3841

@@ -155,3 +158,17 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
155158

156159
return ctrl.Result{}, nil
157160
}
161+
162+
// BarbicanImageMatch - return true if the Barbican images match on the ControlPlane and Version, or if Barbican is not enabled
163+
func BarbicanImageMatch(controlPlane *corev1beta1.OpenStackControlPlane, version *corev1beta1.OpenStackVersion) bool {
164+
165+
if controlPlane.Spec.Barbican.Enabled {
166+
if !stringPointersEqual(controlPlane.Status.ContainerImages.BarbicanAPIImage, version.Status.ContainerImages.BarbicanAPIImage) ||
167+
!stringPointersEqual(controlPlane.Status.ContainerImages.BarbicanWorkerImage, version.Status.ContainerImages.BarbicanWorkerImage) ||
168+
!stringPointersEqual(controlPlane.Status.ContainerImages.BarbicanKeystoneListenerImage, version.Status.ContainerImages.BarbicanKeystoneListenerImage) {
169+
return false
170+
}
171+
}
172+
173+
return true
174+
}

pkg/openstack/cinder.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
3434
}
3535
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneCinderReadyCondition)
3636
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneExposeCinderReadyCondition)
37+
instance.Status.ContainerImages.CinderAPIImage = nil
38+
instance.Status.ContainerImages.CinderSchedulerImage = nil
39+
instance.Status.ContainerImages.CinderBackupImage = nil
40+
instance.Status.ContainerImages.CinderVolumeImages = make(map[string]*string)
3741
return ctrl.Result{}, nil
3842
}
3943
Log := GetLogger(ctx)
@@ -183,3 +187,22 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
183187
return ctrl.Result{}, nil
184188

185189
}
190+
191+
// CinderImageMatch - return true if the Cinder images match on the ControlPlane and Version, or if Cinder is not enabled
192+
func CinderImageMatch(controlPlane *corev1beta1.OpenStackControlPlane, version *corev1beta1.OpenStackVersion) bool {
193+
194+
if controlPlane.Spec.Cinder.Enabled {
195+
if !stringPointersEqual(controlPlane.Status.ContainerImages.CinderAPIImage, version.Status.ContainerImages.CinderAPIImage) ||
196+
!stringPointersEqual(controlPlane.Status.ContainerImages.CinderSchedulerImage, version.Status.ContainerImages.CinderSchedulerImage) ||
197+
!stringPointersEqual(controlPlane.Status.ContainerImages.CinderBackupImage, version.Status.ContainerImages.CinderBackupImage) {
198+
return false
199+
}
200+
for name, img := range version.Status.ContainerImages.CinderVolumeImages {
201+
if !stringPointersEqual(controlPlane.Status.ContainerImages.CinderVolumeImages[name], img) {
202+
return false
203+
}
204+
}
205+
}
206+
207+
return true
208+
}

pkg/openstack/dataplane.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package openstack
2+
3+
import (
4+
"context"
5+
6+
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
7+
corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1"
8+
9+
dataplanev1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1"
10+
"sigs.k8s.io/controller-runtime/pkg/client"
11+
)
12+
13+
// GetDataplaneNodesets - returns the dataplanenodesets in the namespace of the controlplane
14+
func GetDataplaneNodesets(ctx context.Context, instance *corev1beta1.OpenStackControlPlane, helper *helper.Helper) (*dataplanev1.OpenStackDataPlaneNodeSetList, error) {
15+
// Get the dataplane nodesets
16+
dataplaneNodesets := &dataplanev1.OpenStackDataPlaneNodeSetList{}
17+
opts := []client.ListOption{
18+
client.InNamespace(instance.Namespace),
19+
}
20+
err := helper.GetClient().List(ctx, dataplaneNodesets, opts...)
21+
if err != nil {
22+
return nil, err
23+
}
24+
return dataplaneNodesets, nil
25+
}
26+
27+
func DataplaneNodesetsDeployedVersionIsSet(dataplaneNodesets *dataplanev1.OpenStackDataPlaneNodeSetList) bool {
28+
for _, nodeset := range dataplaneNodesets.Items {
29+
// FIXME: DeployedVersion on the DataplaneNodeset should be a string pointer to match how Controlplane implements this
30+
if nodeset.Status.DeployedVersion == "" {
31+
return false
32+
}
33+
}
34+
return true
35+
}
36+
37+
// DataplaneNodesetsOVNControllerImagesMatch returns true if OVNControllers are deployed on all nodesets
38+
func DataplaneNodesetsOVNControllerImagesMatch(version *corev1beta1.OpenStackVersion, dataplaneNodesets *dataplanev1.OpenStackDataPlaneNodeSetList) bool {
39+
for _, nodeset := range dataplaneNodesets.Items {
40+
if nodeset.Generation != nodeset.Status.ObservedGeneration {
41+
return false
42+
}
43+
// we only check nodesets if they deploy OVN
44+
if nodeset.Status.ContainerImages["OvnControllerImage"] != "" {
45+
if !nodeset.IsReady() {
46+
return false
47+
}
48+
if nodeset.Status.ContainerImages["OvnControllerImage"] != *version.Status.ContainerImages.OvnControllerImage {
49+
return false
50+
}
51+
}
52+
}
53+
return true
54+
}
55+
56+
// DataplaneNodesetsDeployed returns true if all nodesets are deployed with the latest version
57+
func DataplaneNodesetsDeployed(version *corev1beta1.OpenStackVersion, dataplaneNodesets *dataplanev1.OpenStackDataPlaneNodeSetList) bool {
58+
for _, nodeset := range dataplaneNodesets.Items {
59+
if nodeset.Generation != nodeset.Status.ObservedGeneration {
60+
return false
61+
}
62+
if !nodeset.IsReady() {
63+
return false
64+
}
65+
if nodeset.Status.DeployedVersion != version.Spec.TargetVersion {
66+
return false
67+
}
68+
69+
}
70+
return true
71+
}

pkg/openstack/designate.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
3434
}
3535
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneDesignateReadyCondition)
3636
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneExposeDesignateReadyCondition)
37+
instance.Status.ContainerImages.DesignateAPIImage = nil
38+
instance.Status.ContainerImages.DesignateCentralImage = nil
39+
instance.Status.ContainerImages.DesignateMdnsImage = nil
40+
instance.Status.ContainerImages.DesignateProducerImage = nil
41+
instance.Status.ContainerImages.DesignateWorkerImage = nil
42+
instance.Status.ContainerImages.DesignateBackendbind9Image = nil
43+
instance.Status.ContainerImages.DesignateUnboundImage = nil
3744
return ctrl.Result{}, nil
3845
}
3946

@@ -169,3 +176,21 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
169176
return ctrl.Result{}, nil
170177

171178
}
179+
180+
// DesignateImageMatch - return true if the Designate images match on the ControlPlane and Version, or if Designate is not enabled
181+
func DesignateImageMatch(controlPlane *corev1beta1.OpenStackControlPlane, version *corev1beta1.OpenStackVersion) bool {
182+
183+
if controlPlane.Spec.Designate.Enabled {
184+
if !stringPointersEqual(controlPlane.Status.ContainerImages.DesignateAPIImage, version.Status.ContainerImages.DesignateAPIImage) ||
185+
!stringPointersEqual(controlPlane.Status.ContainerImages.DesignateCentralImage, version.Status.ContainerImages.DesignateCentralImage) ||
186+
!stringPointersEqual(controlPlane.Status.ContainerImages.DesignateMdnsImage, version.Status.ContainerImages.DesignateMdnsImage) ||
187+
!stringPointersEqual(controlPlane.Status.ContainerImages.DesignateProducerImage, version.Status.ContainerImages.DesignateProducerImage) ||
188+
!stringPointersEqual(controlPlane.Status.ContainerImages.DesignateWorkerImage, version.Status.ContainerImages.DesignateWorkerImage) ||
189+
!stringPointersEqual(controlPlane.Status.ContainerImages.DesignateBackendbind9Image, version.Status.ContainerImages.DesignateBackendbind9Image) ||
190+
!stringPointersEqual(controlPlane.Status.ContainerImages.DesignateUnboundImage, version.Status.ContainerImages.DesignateUnboundImage) {
191+
return false
192+
}
193+
}
194+
195+
return true
196+
}

pkg/openstack/dnsmasq.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func ReconcileDNSMasqs(ctx context.Context, instance *corev1beta1.OpenStackContr
3030
return res, err
3131
}
3232
instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneDNSReadyCondition)
33+
instance.Status.ContainerImages.InfraDnsmasqImage = nil
3334
return ctrl.Result{}, nil
3435
}
3536

@@ -76,3 +77,14 @@ func ReconcileDNSMasqs(ctx context.Context, instance *corev1beta1.OpenStackContr
7677
return ctrl.Result{}, nil
7778

7879
}
80+
81+
// DnsmasqImageMatch - return true if the Dnsmasq images match on the ControlPlane and Version, or if Dnsmasq is not enabled
82+
func DnsmasqImageMatch(controlPlane *corev1beta1.OpenStackControlPlane, version *corev1beta1.OpenStackVersion) bool {
83+
84+
if controlPlane.Spec.DNS.Enabled {
85+
if !stringPointersEqual(controlPlane.Status.ContainerImages.InfraDnsmasqImage, version.Status.ContainerImages.InfraDnsmasqImage) {
86+
return false
87+
}
88+
}
89+
return true
90+
}

0 commit comments

Comments
 (0)