Skip to content

Commit 1aec52b

Browse files
Upgrade to latest hypervisor crd (#581)
This upgrade is necessary, because we changed the allocation and capacity types from a generic `map[string]resource.Quantity` to `map[hv1.ResourceName]resource.Quantity`. In addition, this upgrade also makes use of the `hv1.ResourceName` api inside our Reservation CRD. See: cobaltcore-dev/openstack-hypervisor-operator#257 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized resource naming to a strongly-typed format across scheduling and reservation logic, improving type safety and consistency for capacity, allocation and reservation handling. * **Chores** * Bumped the OpenStack Hypervisor Operator dependency to the newer release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent eceedce commit 1aec52b

20 files changed

Lines changed: 288 additions & 322 deletions

api/v1alpha1/reservation_types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package v1alpha1
55

66
import (
7+
hv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
78
"k8s.io/apimachinery/pkg/api/resource"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
)
@@ -44,7 +45,7 @@ type CommittedResourceAllocation struct {
4445

4546
// Resources consumed by this instance.
4647
// +kubebuilder:validation:Required
47-
Resources map[string]resource.Quantity `json:"resources"`
48+
Resources map[hv1.ResourceName]resource.Quantity `json:"resources"`
4849
}
4950

5051
// CommittedResourceReservationSpec defines the spec fields specific to committed resource reservations.
@@ -99,7 +100,7 @@ type ReservationSpec struct {
99100

100101
// Resources to reserve for this instance.
101102
// +kubebuilder:validation:Optional
102-
Resources map[string]resource.Quantity `json:"resources,omitempty"`
103+
Resources map[hv1.ResourceName]resource.Quantity `json:"resources,omitempty"`
103104

104105
// StartTime is the time when the reservation becomes active.
105106
// +kubebuilder:validation:Optional

api/v1alpha1/zz_generated.deepcopy.go

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

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/cobaltcore-dev/cortex
33
go 1.26
44

55
require (
6-
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260313132145-05f22f69d9fd
6+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260316070528-80f53bbce409
77
github.com/go-gorp/gorp v2.2.0+incompatible
88
github.com/gophercloud/gophercloud/v2 v2.11.1
99
github.com/ironcore-dev/ironcore v0.2.4

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
2222
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
2323
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260313132145-05f22f69d9fd h1:IzxramZZRC/9FtQQqpbgf8KIpH4soD9cliCFs2+zPd4=
2424
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260313132145-05f22f69d9fd/go.mod h1:b0KmJdxvRI8UXlGe8cRm5BD8Tm2WhF7zSKMSIRGyVL4=
25+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260316070528-80f53bbce409 h1:hiTMLk6JZsmFF+ECBJnOVcDAw2d+iCXhk4eDvVpYHYM=
26+
github.com/cobaltcore-dev/openstack-hypervisor-operator v0.0.0-20260316070528-80f53bbce409/go.mod h1:b0KmJdxvRI8UXlGe8cRm5BD8Tm2WhF7zSKMSIRGyVL4=
2527
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
2628
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
2729
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=

internal/knowledge/kpis/plugins/compute/resource_capacity_kvm_test.go

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ func TestKVMResourceCapacityKPI_Collect(t *testing.T) {
5858
},
5959
},
6060
Status: hv1.HypervisorStatus{
61-
Capacity: map[string]resource.Quantity{
62-
"cpu": resource.MustParse("128"),
63-
"memory": resource.MustParse("512Gi"),
61+
Capacity: map[hv1.ResourceName]resource.Quantity{
62+
hv1.ResourceCPU: resource.MustParse("128"),
63+
hv1.ResourceMemory: resource.MustParse("512Gi"),
6464
},
65-
Allocation: map[string]resource.Quantity{
66-
"cpu": resource.MustParse("64"),
67-
"memory": resource.MustParse("256Gi"),
65+
Allocation: map[hv1.ResourceName]resource.Quantity{
66+
hv1.ResourceCPU: resource.MustParse("64"),
67+
hv1.ResourceMemory: resource.MustParse("256Gi"),
6868
},
6969
Traits: []string{},
7070
},
@@ -148,13 +148,13 @@ func TestKVMResourceCapacityKPI_Collect(t *testing.T) {
148148
},
149149
},
150150
Status: hv1.HypervisorStatus{
151-
Capacity: map[string]resource.Quantity{
152-
"cpu": resource.MustParse("256"),
153-
"memory": resource.MustParse("1Ti"),
151+
Capacity: map[hv1.ResourceName]resource.Quantity{
152+
hv1.ResourceCPU: resource.MustParse("256"),
153+
hv1.ResourceMemory: resource.MustParse("1Ti"),
154154
},
155-
Allocation: map[string]resource.Quantity{
156-
"cpu": resource.MustParse("128"),
157-
"memory": resource.MustParse("512Gi"),
155+
Allocation: map[hv1.ResourceName]resource.Quantity{
156+
hv1.ResourceCPU: resource.MustParse("128"),
157+
hv1.ResourceMemory: resource.MustParse("512Gi"),
158158
},
159159
Traits: []string{
160160
"CUSTOM_HW_SAPPHIRE_RAPIDS",
@@ -209,13 +209,13 @@ func TestKVMResourceCapacityKPI_Collect(t *testing.T) {
209209
},
210210
},
211211
Status: hv1.HypervisorStatus{
212-
Capacity: map[string]resource.Quantity{
213-
"cpu": resource.MustParse("64"),
214-
"memory": resource.MustParse("256Gi"),
212+
Capacity: map[hv1.ResourceName]resource.Quantity{
213+
hv1.ResourceCPU: resource.MustParse("64"),
214+
hv1.ResourceMemory: resource.MustParse("256Gi"),
215215
},
216-
Allocation: map[string]resource.Quantity{
217-
"cpu": resource.MustParse("32"),
218-
"memory": resource.MustParse("128Gi"),
216+
Allocation: map[hv1.ResourceName]resource.Quantity{
217+
hv1.ResourceCPU: resource.MustParse("32"),
218+
hv1.ResourceMemory: resource.MustParse("128Gi"),
219219
},
220220
Traits: []string{
221221
"CUSTOM_DECOMMISSIONING",
@@ -255,13 +255,13 @@ func TestKVMResourceCapacityKPI_Collect(t *testing.T) {
255255
},
256256
},
257257
Status: hv1.HypervisorStatus{
258-
Capacity: map[string]resource.Quantity{
259-
"cpu": resource.MustParse("100"),
260-
"memory": resource.MustParse("200Gi"),
258+
Capacity: map[hv1.ResourceName]resource.Quantity{
259+
hv1.ResourceCPU: resource.MustParse("100"),
260+
hv1.ResourceMemory: resource.MustParse("200Gi"),
261261
},
262-
Allocation: map[string]resource.Quantity{
263-
"cpu": resource.MustParse("50"),
264-
"memory": resource.MustParse("100Gi"),
262+
Allocation: map[hv1.ResourceName]resource.Quantity{
263+
hv1.ResourceCPU: resource.MustParse("50"),
264+
hv1.ResourceMemory: resource.MustParse("100Gi"),
265265
},
266266
Traits: []string{},
267267
},
@@ -274,13 +274,13 @@ func TestKVMResourceCapacityKPI_Collect(t *testing.T) {
274274
},
275275
},
276276
Status: hv1.HypervisorStatus{
277-
Capacity: map[string]resource.Quantity{
278-
"cpu": resource.MustParse("200"),
279-
"memory": resource.MustParse("400Gi"),
277+
Capacity: map[hv1.ResourceName]resource.Quantity{
278+
hv1.ResourceCPU: resource.MustParse("200"),
279+
hv1.ResourceMemory: resource.MustParse("400Gi"),
280280
},
281-
Allocation: map[string]resource.Quantity{
282-
"cpu": resource.MustParse("150"),
283-
"memory": resource.MustParse("300Gi"),
281+
Allocation: map[hv1.ResourceName]resource.Quantity{
282+
hv1.ResourceCPU: resource.MustParse("150"),
283+
hv1.ResourceMemory: resource.MustParse("300Gi"),
284284
},
285285
Traits: []string{"CUSTOM_HW_SAPPHIRE_RAPIDS"},
286286
},
@@ -332,9 +332,9 @@ func TestKVMResourceCapacityKPI_Collect(t *testing.T) {
332332
},
333333
},
334334
Status: hv1.HypervisorStatus{
335-
Capacity: map[string]resource.Quantity{
336-
"cpu": resource.MustParse("96"),
337-
"memory": resource.MustParse("384Gi"),
335+
Capacity: map[hv1.ResourceName]resource.Quantity{
336+
hv1.ResourceCPU: resource.MustParse("96"),
337+
hv1.ResourceMemory: resource.MustParse("384Gi"),
338338
},
339339
// No Allocation field - simulating missing data
340340
Allocation: nil,

internal/scheduling/nova/integration_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ func newHypervisor(name, cpuCap, cpuAlloc, memCap, memAlloc string) *hv1.Hypervi
4848
Name: name,
4949
},
5050
Status: hv1.HypervisorStatus{
51-
Capacity: map[string]resource.Quantity{
52-
"cpu": resource.MustParse(cpuCap),
53-
"memory": resource.MustParse(memCap),
51+
Capacity: map[hv1.ResourceName]resource.Quantity{
52+
hv1.ResourceCPU: resource.MustParse(cpuCap),
53+
hv1.ResourceMemory: resource.MustParse(memCap),
5454
},
55-
Allocation: map[string]resource.Quantity{
56-
"cpu": resource.MustParse(cpuAlloc),
57-
"memory": resource.MustParse(memAlloc),
55+
Allocation: map[hv1.ResourceName]resource.Quantity{
56+
hv1.ResourceCPU: resource.MustParse(cpuAlloc),
57+
hv1.ResourceMemory: resource.MustParse(memAlloc),
5858
},
5959
},
6060
}
@@ -68,9 +68,9 @@ func newCommittedReservation(name, targetHost, observedHost, projectID, flavorNa
6868
Spec: v1alpha1.ReservationSpec{
6969
Type: v1alpha1.ReservationTypeCommittedResource,
7070
TargetHost: targetHost,
71-
Resources: map[string]resource.Quantity{
72-
"cpu": resource.MustParse(cpu),
73-
"memory": resource.MustParse(memory),
71+
Resources: map[hv1.ResourceName]resource.Quantity{
72+
hv1.ResourceCPU: resource.MustParse(cpu),
73+
hv1.ResourceMemory: resource.MustParse(memory),
7474
},
7575
CommittedResourceReservation: &v1alpha1.CommittedResourceReservationSpec{
7676
ProjectID: projectID,
@@ -100,9 +100,9 @@ func newFailoverReservation(name, targetHost, resourceGroup, cpu, memory string,
100100
Spec: v1alpha1.ReservationSpec{
101101
Type: v1alpha1.ReservationTypeFailover,
102102
TargetHost: targetHost,
103-
Resources: map[string]resource.Quantity{
104-
"cpu": resource.MustParse(cpu),
105-
"memory": resource.MustParse(memory),
103+
Resources: map[hv1.ResourceName]resource.Quantity{
104+
hv1.ResourceCPU: resource.MustParse(cpu),
105+
hv1.ResourceMemory: resource.MustParse(memory),
106106
},
107107
FailoverReservation: &v1alpha1.FailoverReservationSpec{
108108
ResourceGroup: resourceGroup,

internal/scheduling/nova/plugins/filters/filter_has_enough_capacity.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (s *FilterHasEnoughCapacity) Run(traceLog *slog.Logger, request api.Externa
4545
result := s.IncludeAllHostsFromRequest(request)
4646

4747
// This map holds the free resources per host.
48-
freeResourcesByHost := make(map[string]map[string]resource.Quantity)
48+
freeResourcesByHost := make(map[string]map[hv1.ResourceName]resource.Quantity)
4949

5050
// The hypervisor resource auto-discovers its current utilization.
5151
// We can use the hypervisor status to calculate the total capacity
@@ -145,7 +145,7 @@ func (s *FilterHasEnoughCapacity) Run(traceLog *slog.Logger, request api.Externa
145145

146146
// For CR reservations with allocations, calculate remaining (unallocated) resources to block.
147147
// This prevents double-blocking of resources already consumed by running instances.
148-
var resourcesToBlock map[string]resource.Quantity
148+
var resourcesToBlock map[hv1.ResourceName]resource.Quantity
149149
if reservation.Spec.Type == v1alpha1.ReservationTypeCommittedResource &&
150150
// if the reservation is not being migrated, block only unused resources
151151
reservation.Spec.TargetHost == reservation.Status.Host &&
@@ -154,7 +154,7 @@ func (s *FilterHasEnoughCapacity) Run(traceLog *slog.Logger, request api.Externa
154154
len(reservation.Spec.CommittedResourceReservation.Allocations) > 0 &&
155155
len(reservation.Status.CommittedResourceReservation.Allocations) > 0 {
156156
// Start with full reservation resources
157-
resourcesToBlock = make(map[string]resource.Quantity)
157+
resourcesToBlock = make(map[hv1.ResourceName]resource.Quantity)
158158
for k, v := range reservation.Spec.Resources {
159159
resourcesToBlock[k] = v.DeepCopy()
160160
}

internal/scheduling/nova/plugins/filters/filter_has_enough_capacity_test.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ func newHypervisor(name, cpuCap, cpuAlloc, memCap, memAlloc string) *hv1.Hypervi
3939
Name: name,
4040
},
4141
Status: hv1.HypervisorStatus{
42-
Capacity: map[string]resource.Quantity{
43-
"cpu": resource.MustParse(cpuCap),
44-
"memory": resource.MustParse(memCap),
42+
Capacity: map[hv1.ResourceName]resource.Quantity{
43+
hv1.ResourceCPU: resource.MustParse(cpuCap),
44+
hv1.ResourceMemory: resource.MustParse(memCap),
4545
},
46-
Allocation: map[string]resource.Quantity{
47-
"cpu": resource.MustParse(cpuAlloc),
48-
"memory": resource.MustParse(memAlloc),
46+
Allocation: map[hv1.ResourceName]resource.Quantity{
47+
hv1.ResourceCPU: resource.MustParse(cpuAlloc),
48+
hv1.ResourceMemory: resource.MustParse(memAlloc),
4949
},
5050
},
5151
}
@@ -64,9 +64,9 @@ func newCommittedReservation(
6464
Spec: v1alpha1.ReservationSpec{
6565
Type: v1alpha1.ReservationTypeCommittedResource,
6666
TargetHost: targetHost,
67-
Resources: map[string]resource.Quantity{
68-
"cpu": resource.MustParse(cpu),
69-
"memory": resource.MustParse(memory),
67+
Resources: map[hv1.ResourceName]resource.Quantity{
68+
hv1.ResourceCPU: resource.MustParse(cpu),
69+
hv1.ResourceMemory: resource.MustParse(memory),
7070
},
7171
CommittedResourceReservation: &v1alpha1.CommittedResourceReservationSpec{
7272
ProjectID: projectID,
@@ -104,9 +104,9 @@ func newFailoverReservation(name, targetHost, cpu, memory string, allocations ma
104104
Spec: v1alpha1.ReservationSpec{
105105
Type: v1alpha1.ReservationTypeFailover,
106106
TargetHost: targetHost,
107-
Resources: map[string]resource.Quantity{
108-
"cpu": resource.MustParse(cpu),
109-
"memory": resource.MustParse(memory),
107+
Resources: map[hv1.ResourceName]resource.Quantity{
108+
hv1.ResourceCPU: resource.MustParse(cpu),
109+
hv1.ResourceMemory: resource.MustParse(memory),
110110
},
111111
FailoverReservation: &v1alpha1.FailoverReservationSpec{
112112
ResourceGroup: "m1.large",
@@ -150,9 +150,9 @@ func crSpecAllocs(vms ...crVmAlloc) map[string]v1alpha1.CommittedResourceAllocat
150150
for _, v := range vms {
151151
allocs[v.uuid] = v1alpha1.CommittedResourceAllocation{
152152
CreationTimestamp: metav1.Now(),
153-
Resources: map[string]resource.Quantity{
154-
"cpu": resource.MustParse(v.cpu),
155-
"memory": resource.MustParse(v.mem),
153+
Resources: map[hv1.ResourceName]resource.Quantity{
154+
hv1.ResourceCPU: resource.MustParse(v.cpu),
155+
hv1.ResourceMemory: resource.MustParse(v.mem),
156156
},
157157
}
158158
}

internal/scheduling/nova/plugins/weighers/kvm_binpack.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
api "github.com/cobaltcore-dev/cortex/api/external/nova"
1414
"github.com/cobaltcore-dev/cortex/internal/scheduling/lib"
1515
hv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
16-
corev1 "k8s.io/api/core/v1"
1716
"k8s.io/apimachinery/pkg/api/resource"
1817
)
1918

@@ -23,17 +22,17 @@ type KVMBinpackStepOpts struct {
2322
// node's resource utilizations after placing the VM.
2423
// If a resource is not specified, is ignored in the score calculation
2524
// (equivalent to a weight of 0).
26-
ResourceWeights map[corev1.ResourceName]float64 `json:"resourceWeights"`
25+
ResourceWeights map[hv1.ResourceName]float64 `json:"resourceWeights"`
2726
}
2827

2928
// Validate the options to ensure they are correct before running the weigher.
3029
func (o KVMBinpackStepOpts) Validate() error {
3130
if len(o.ResourceWeights) == 0 {
3231
return errors.New("at least one resource weight must be specified")
3332
}
34-
supportedResources := []corev1.ResourceName{
35-
corev1.ResourceMemory,
36-
corev1.ResourceCPU,
33+
supportedResources := []hv1.ResourceName{
34+
hv1.ResourceMemory,
35+
hv1.ResourceCPU,
3736
}
3837
for resourceName, value := range o.ResourceWeights {
3938
if !slices.Contains(supportedResources, resourceName) {
@@ -94,7 +93,7 @@ func (s *KVMBinpackStep) Run(traceLog *slog.Logger, request api.ExternalSchedule
9493
var totalWeightedUtilization, totalWeight float64
9594

9695
for resourceName, weight := range s.Options.ResourceWeights {
97-
capacity, ok := hv.Status.Capacity[resourceName.String()]
96+
capacity, ok := hv.Status.Capacity[resourceName]
9897
if !ok {
9998
traceLog.Warn("no capacity in status, skipping",
10099
"host", host, "resource", resourceName)
@@ -105,7 +104,7 @@ func (s *KVMBinpackStep) Run(traceLog *slog.Logger, request api.ExternalSchedule
105104
"host", host, "resource", resourceName)
106105
continue
107106
}
108-
allocation, ok := hv.Status.Allocation[resourceName.String()]
107+
allocation, ok := hv.Status.Allocation[resourceName]
109108
if !ok {
110109
traceLog.Warn("no allocation in status, skipping",
111110
"host", host, "resource", resourceName)
@@ -138,15 +137,15 @@ func (s *KVMBinpackStep) Run(traceLog *slog.Logger, request api.ExternalSchedule
138137
}
139138

140139
// calcVMResources calculates the total resource requests for the VM to be scheduled.
141-
func (s *KVMBinpackStep) calcVMResources(req api.ExternalSchedulerRequest) map[corev1.ResourceName]resource.Quantity {
142-
resources := make(map[corev1.ResourceName]resource.Quantity)
140+
func (s *KVMBinpackStep) calcVMResources(req api.ExternalSchedulerRequest) map[hv1.ResourceName]resource.Quantity {
141+
resources := make(map[hv1.ResourceName]resource.Quantity)
143142
resourcesMemBytes := int64(req.Spec.Data.Flavor.Data.MemoryMB * 1_000_000) //nolint:gosec // memory values are bounded by Nova
144143
resourcesMemBytes *= int64(req.Spec.Data.NumInstances) //nolint:gosec // instance count is bounded by Nova
145-
resources[corev1.ResourceMemory] = *resource.
144+
resources[hv1.ResourceMemory] = *resource.
146145
NewQuantity(resourcesMemBytes, resource.DecimalSI)
147146
resourcesCPU := int64(req.Spec.Data.Flavor.Data.VCPUs) //nolint:gosec // vCPU values are bounded by Nova
148147
resourcesCPU *= int64(req.Spec.Data.NumInstances) //nolint:gosec // instance count is bounded by Nova
149-
resources[corev1.ResourceCPU] = *resource.
148+
resources[hv1.ResourceCPU] = *resource.
150149
NewQuantity(resourcesCPU, resource.DecimalSI)
151150
return resources
152151
}

0 commit comments

Comments
 (0)