Skip to content

Commit 733c59b

Browse files
committed
Change HypervisorStatus.Aggregates to be name & uuid
This is a breaking change, but shows the clear relationship between UUIDs and names.
1 parent 05ba895 commit 733c59b

File tree

15 files changed

+278
-90
lines changed

15 files changed

+278
-90
lines changed

api/v1/hypervisor_types.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ type Instance struct {
155155
Active bool `json:"active"`
156156
}
157157

158+
// Aggregate represents an OpenStack aggregate with its name and UUID.
159+
type Aggregate struct {
160+
// Name is the name of the aggregate.
161+
Name string `json:"name"`
162+
163+
// UUID is the unique identifier of the aggregate.
164+
UUID string `json:"uuid"`
165+
}
166+
158167
type HyperVisorUpdateStatus struct {
159168
// +kubebuilder:default:=false
160169
// Represents a running Operating System update.
@@ -351,12 +360,8 @@ type HypervisorStatus struct {
351360
// Traits are the applied traits of the hypervisor.
352361
Traits []string `json:"traits,omitempty"`
353362

354-
// Aggregates are the applied aggregates of the hypervisor.
355-
Aggregates []string `json:"aggregates,omitempty"`
356-
357-
// +kubebuilder:default:={}
358-
// The UUIDs of the aggregates are used to apply aggregates to the hypervisor.
359-
AggregateUUIDs []string `json:"aggregateUUIDs,omitempty"`
363+
// Aggregates are the applied aggregates of the hypervisor with their names and UUIDs.
364+
Aggregates []Aggregate `json:"aggregates,omitempty"`
360365

361366
// InternalIP is the internal IP address of the hypervisor.
362367
InternalIP string `json:"internalIp,omitempty"`

api/v1/zz_generated.deepcopy.go

Lines changed: 16 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applyconfigurations/api/v1/aggregate.go

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applyconfigurations/api/v1/hypervisorstatus.go

Lines changed: 6 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applyconfigurations/utils.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/openstack-hypervisor-operator/crds/hypervisor-crd.yaml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,23 @@ spec:
200200
status:
201201
description: HypervisorStatus defines the observed state of Hypervisor
202202
properties:
203-
aggregateUUIDs:
204-
default: []
205-
description: The UUIDs of the aggregates are used to apply aggregates
206-
to the hypervisor.
207-
items:
208-
type: string
209-
type: array
210203
aggregates:
211-
description: Aggregates are the applied aggregates of the hypervisor.
204+
description: Aggregates are the applied aggregates of the hypervisor
205+
with their names and UUIDs.
212206
items:
213-
type: string
207+
description: Aggregate represents an OpenStack aggregate with its
208+
name and UUID.
209+
properties:
210+
name:
211+
description: Name is the name of the aggregate.
212+
type: string
213+
uuid:
214+
description: UUID is the unique identifier of the aggregate.
215+
type: string
216+
required:
217+
- name
218+
- uuid
219+
type: object
214220
type: array
215221
allocation:
216222
additionalProperties:

config/crd/bases/kvm.cloud.sap_hypervisors.yaml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -201,17 +201,23 @@ spec:
201201
status:
202202
description: HypervisorStatus defines the observed state of Hypervisor
203203
properties:
204-
aggregateUUIDs:
205-
default: []
206-
description: The UUIDs of the aggregates are used to apply aggregates
207-
to the hypervisor.
208-
items:
209-
type: string
210-
type: array
211204
aggregates:
212-
description: Aggregates are the applied aggregates of the hypervisor.
205+
description: Aggregates are the applied aggregates of the hypervisor
206+
with their names and UUIDs.
213207
items:
214-
type: string
208+
description: Aggregate represents an OpenStack aggregate with its
209+
name and UUID.
210+
properties:
211+
name:
212+
description: Name is the name of the aggregate.
213+
type: string
214+
uuid:
215+
description: UUID is the unique identifier of the aggregate.
216+
type: string
217+
required:
218+
- name
219+
- uuid
220+
type: object
215221
type: array
216222
allocation:
217223
additionalProperties:

internal/controller/aggregates_controller.go

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"context"
2222
"errors"
2323
"fmt"
24-
"slices"
2524

2625
corev1 "k8s.io/api/core/v1"
2726
"k8s.io/apimachinery/pkg/api/equality"
@@ -66,11 +65,17 @@ func (ac *AggregatesController) Reconcile(ctx context.Context, req ctrl.Request)
6665
}
6766

6867
base := hv.DeepCopy()
69-
desiredAggregates, desiredCondition := ac.determineDesiredState(hv)
68+
desiredAggregateNames, desiredCondition := ac.determineDesiredState(hv)
7069

71-
if !slices.Equal(desiredAggregates, hv.Status.Aggregates) {
70+
// Extract current aggregate names for comparison
71+
currentAggregateNames := make([]string, len(hv.Status.Aggregates))
72+
for i, agg := range hv.Status.Aggregates {
73+
currentAggregateNames[i] = agg.Name
74+
}
75+
76+
if !slicesEqualUnordered(desiredAggregateNames, currentAggregateNames) {
7277
// Apply aggregates to OpenStack and update status
73-
uuids, err := openstack.ApplyAggregates(ctx, ac.computeClient, hv.Name, desiredAggregates)
78+
aggregates, err := openstack.ApplyAggregates(ctx, ac.computeClient, hv.Name, desiredAggregateNames)
7479
if err != nil {
7580
// Set error condition
7681
condition := metav1.Condition{
@@ -89,8 +94,7 @@ func (ac *AggregatesController) Reconcile(ctx context.Context, req ctrl.Request)
8994
return ctrl.Result{}, err
9095
}
9196

92-
hv.Status.Aggregates = desiredAggregates
93-
hv.Status.AggregateUUIDs = uuids
97+
hv.Status.Aggregates = aggregates
9498
}
9599

96100
// Set the condition based on the determined desired state
@@ -123,8 +127,12 @@ func (ac *AggregatesController) determineDesiredState(hv *kvmv1.Hypervisor) ([]s
123127
Message: "Aggregates cleared due to termination after eviction",
124128
}
125129
}
126-
// Still evicting or eviction not started - keep current aggregates
127-
return hv.Status.Aggregates, metav1.Condition{
130+
// Still evicting or eviction not started - keep current aggregate names
131+
currentAggregateNames := make([]string, len(hv.Status.Aggregates))
132+
for i, agg := range hv.Status.Aggregates {
133+
currentAggregateNames[i] = agg.Name
134+
}
135+
return currentAggregateNames, metav1.Condition{
128136
Type: kvmv1.ConditionTypeAggregatesUpdated,
129137
Status: metav1.ConditionFalse,
130138
Reason: kvmv1.ConditionReasonEvictionInProgress,
@@ -166,6 +174,30 @@ func (ac *AggregatesController) determineDesiredState(hv *kvmv1.Hypervisor) ([]s
166174
}
167175
}
168176

177+
// slicesEqualUnordered compares two string slices without considering order.
178+
// Returns true if both slices contain the same elements, regardless of order.
179+
func slicesEqualUnordered(a, b []string) bool {
180+
if len(a) != len(b) {
181+
return false
182+
}
183+
184+
// Create a map to count occurrences in slice a
185+
counts := make(map[string]int)
186+
for _, s := range a {
187+
counts[s]++
188+
}
189+
190+
// Verify all elements in b exist in a with correct counts
191+
for _, s := range b {
192+
counts[s]--
193+
if counts[s] < 0 {
194+
return false
195+
}
196+
}
197+
198+
return true
199+
}
200+
169201
// SetupWithManager sets up the controller with the Manager.
170202
func (ac *AggregatesController) SetupWithManager(mgr ctrl.Manager) error {
171203
ctx := context.Background()

0 commit comments

Comments
 (0)