Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 39 additions & 14 deletions api/v1alpha1/flavor_group_capacity_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ type FlavorGroupCapacitySpec struct {
AvailabilityZone string `json:"availabilityZone"`
}

// FlavorCapacityStatus holds per-flavor capacity numbers for one (flavor group × AZ) pair.
// FlavorCapacityStatus holds per-flavor scheduler probe results for one (flavor group × AZ) pair.
// These values come directly from scheduler probes and are independent of the cross-group
// capacity split (see FreeCapacity and ExclusivelyFreeCapacity on the parent status).
// "Placeable" means: if all remaining capacity in this AZ were used solely by this flavor,
// this is how many would fit. It does not account for competing flavor groups.
type FlavorCapacityStatus struct {
// FlavorName is the OpenStack flavor name (e.g. "hana-v2-small").
FlavorName string `json:"flavorName"`
Expand All @@ -37,11 +41,11 @@ type FlavorCapacityStatus struct {
// +kubebuilder:validation:Optional
PlaceableVMs int64 `json:"placeableVms,omitempty"`

// TotalCapacityHosts is the number of eligible hosts in an empty-datacenter scenario.
// TotalCapacityHosts is the number of eligible hosts assuming an empty datacenter.
// +kubebuilder:validation:Optional
TotalCapacityHosts int64 `json:"totalCapacityHosts,omitempty"`

// TotalCapacityVMSlots is the maximum number of VM slots in an empty-datacenter scenario.
// TotalCapacityVMSlots is the maximum number of VM slots assuming an empty datacenter.
// +kubebuilder:validation:Optional
TotalCapacityVMSlots int64 `json:"totalCapacityVmSlots,omitempty"`
}
Expand All @@ -57,14 +61,41 @@ type FlavorGroupCapacityStatus struct {
// +kubebuilder:validation:Optional
CommittedCapacity int64 `json:"committedCapacity,omitempty"`

// TotalCapacity is the total capacity of all eligible hosts in an empty-datacenter scenario.
// SmallestFlavorName is the name of the smallest flavor in this group, used as the
// slot unit for ExclusivelyFreeSlots and related capacity fields.
// +kubebuilder:validation:Optional
SmallestFlavorName string `json:"smallestFlavorName,omitempty"`

// TotalCapacity is the installed capacity across all eligible hosts in an empty-datacenter
// scenario, expressed as raw resource amounts (bytes for memory, count for cores).
// +kubebuilder:validation:Optional
TotalCapacity map[string]resource.Quantity `json:"totalCapacity,omitempty"`

// TotalInstances is the total number of VM instances running on hypervisors in this AZ,
// derived from Hypervisor CRD Status.Instances (not filtered by flavor group).
// FreeCapacity is the sum of remaining resources across all candidate hosts for this
// group given current allocations. Because groups can share hosts, the sum across groups
// may exceed actual installed capacity — this field reflects per-group availability
// before any cross-group fairness split.
// +kubebuilder:validation:Optional
FreeCapacity map[string]resource.Quantity `json:"freeCapacity,omitempty"`

// ExclusivelyFreeCapacity is the share of remaining resources fairly attributed to this
// group by the round-robin capacity split. The sum across all groups for an AZ never
// exceeds actual installed capacity.
// +kubebuilder:validation:Optional
TotalInstances int64 `json:"totalInstances,omitempty"`
ExclusivelyFreeCapacity map[string]resource.Quantity `json:"exclusivelyFreeCapacity,omitempty"`

// ExclusivelyFreeSlots is the number of smallest-flavor VM slots available from ExclusivelyFreeCapacity.
// +kubebuilder:validation:Optional
ExclusivelyFreeSlots int64 `json:"exclusivelyFreeSlots,omitempty"`

// RunningInstances is the number of VMs running in this (flavor group × AZ) whose
// flavor belongs to this group.
// +kubebuilder:validation:Optional
RunningInstances int64 `json:"runningInstances,omitempty"`

// RunningResources is the total resource consumption of running VMs, keyed by resource type.
// +kubebuilder:validation:Optional
RunningResources map[string]resource.Quantity `json:"runningResources,omitempty"`

// LastReconcileAt is the timestamp of the last successful reconcile.
// +kubebuilder:validation:Optional
Expand All @@ -80,7 +111,7 @@ type FlavorGroupCapacityStatus struct {
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:printcolumn:name="FlavorGroup",type="string",JSONPath=".spec.flavorGroup"
// +kubebuilder:printcolumn:name="AZ",type="string",JSONPath=".spec.availabilityZone"
// +kubebuilder:printcolumn:name="TotalInstances",type="integer",JSONPath=".status.totalInstances"
// +kubebuilder:printcolumn:name="Running",type="integer",JSONPath=".status.runningInstances"
// +kubebuilder:printcolumn:name="LastReconcile",type="date",JSONPath=".status.lastReconcileAt"
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status"

Expand All @@ -89,16 +120,10 @@ type FlavorGroupCapacityStatus struct {
// The capacity API reads these CRDs instead of probing the scheduler on each request.
type FlavorGroupCapacity struct {
metav1.TypeMeta `json:",inline"`

// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`

// spec defines the desired state of FlavorGroupCapacity
// +required
Spec FlavorGroupCapacitySpec `json:"spec"`

// status defines the observed state of FlavorGroupCapacity
// +optional
Status FlavorGroupCapacityStatus `json:"status,omitempty,omitzero"`
}
Expand Down
21 changes: 21 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ func main() {
setupLog.Error(err, "failed to register capacity monitor metrics, continuing without metrics")
}

capacityController := capacity.NewController(multiclusterClient, capacityConfig)
capacityController := capacity.NewController(multiclusterClient, capacityConfig, commitmentsVMSource)
if err := mgr.Add(manager.RunnableFunc(func(ctx context.Context) error {
return capacityController.Start(ctx)
})); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ spec:
- jsonPath: .spec.availabilityZone
name: AZ
type: string
- jsonPath: .status.totalInstances
name: TotalInstances
- jsonPath: .status.runningInstances
name: Running
type: integer
- jsonPath: .status.lastReconcileAt
name: LastReconcile
Expand Down Expand Up @@ -56,7 +56,7 @@ spec:
metadata:
type: object
spec:
description: spec defines the desired state of FlavorGroupCapacity
description: FlavorGroupCapacitySpec defines the desired state of FlavorGroupCapacity.
properties:
availabilityZone:
description: AvailabilityZone is the OpenStack AZ this capacity data
Expand All @@ -70,7 +70,7 @@ spec:
- flavorGroup
type: object
status:
description: status defines the observed state of FlavorGroupCapacity
description: FlavorGroupCapacityStatus defines the observed state of FlavorGroupCapacity.
properties:
committedCapacity:
description: |-
Expand Down Expand Up @@ -135,12 +135,33 @@ spec:
- type
type: object
type: array
exclusivelyFreeCapacity:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: |-
ExclusivelyFreeCapacity is the share of remaining resources fairly attributed to this
group by the round-robin capacity split. The sum across all groups for an AZ never
exceeds actual installed capacity.
type: object
exclusivelyFreeSlots:
description: ExclusivelyFreeSlots is the number of smallest-flavor
VM slots available from ExclusivelyFreeCapacity.
format: int64
type: integer
flavors:
description: Flavors holds per-flavor capacity data for all flavors
in the group.
items:
description: FlavorCapacityStatus holds per-flavor capacity numbers
for one (flavor group × AZ) pair.
description: |-
FlavorCapacityStatus holds per-flavor scheduler probe results for one (flavor group × AZ) pair.
These values come directly from scheduler probes and are independent of the cross-group
capacity split (see FreeCapacity and ExclusivelyFreeCapacity on the parent status).
"Placeable" means: if all remaining capacity in this AZ were used solely by this flavor,
this is how many would fit. It does not account for competing flavor groups.
properties:
flavorName:
description: FlavorName is the OpenStack flavor name (e.g. "hana-v2-small").
Expand All @@ -157,39 +178,68 @@ spec:
type: integer
totalCapacityHosts:
description: TotalCapacityHosts is the number of eligible hosts
in an empty-datacenter scenario.
assuming an empty datacenter.
format: int64
type: integer
totalCapacityVmSlots:
description: TotalCapacityVMSlots is the maximum number of VM
slots in an empty-datacenter scenario.
slots assuming an empty datacenter.
format: int64
type: integer
required:
- flavorName
type: object
type: array
freeCapacity:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: |-
FreeCapacity is the sum of remaining resources across all candidate hosts for this
group given current allocations. Because groups can share hosts, the sum across groups
may exceed actual installed capacity — this field reflects per-group availability
before any cross-group fairness split.
type: object
lastReconcileAt:
description: LastReconcileAt is the timestamp of the last successful
reconcile.
format: date-time
type: string
totalCapacity:
runningInstances:
description: |-
RunningInstances is the number of VMs running in this (flavor group × AZ) whose
flavor belongs to this group.
format: int64
type: integer
runningResources:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: TotalCapacity is the total capacity of all eligible hosts
in an empty-datacenter scenario.
description: RunningResources is the total resource consumption of
running VMs, keyed by resource type.
type: object
totalInstances:
smallestFlavorName:
description: |-
TotalInstances is the total number of VM instances running on hypervisors in this AZ,
derived from Hypervisor CRD Status.Instances (not filtered by flavor group).
format: int64
type: integer
SmallestFlavorName is the name of the smallest flavor in this group, used as the
slot unit for ExclusivelyFreeSlots and related capacity fields.
type: string
totalCapacity:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: |-
TotalCapacity is the installed capacity across all eligible hosts in an empty-datacenter
scenario, expressed as raw resource amounts (bytes for memory, count for cores).
type: object
type: object
required:
- spec
Expand Down
Loading