diff --git a/api/v1alpha1/reservation_types.go b/api/v1alpha1/reservation_types.go index 4ec3ee9c5..f52797654 100644 --- a/api/v1alpha1/reservation_types.go +++ b/api/v1alpha1/reservation_types.go @@ -21,6 +21,9 @@ const ( ReservationTypeCommittedResource ReservationType = "CommittedResourceReservation" // ReservationTypeFailover is a reservation for failover capacity. ReservationTypeFailover ReservationType = "FailoverReservation" + // ReservationTypeInFlight is a reservation that blocks capacity for virtual + // machines that are currently being scheduled, to avoid double-booking. + ReservationTypeInFlight ReservationType = "InFlightReservation" ) // Label keys for Reservation metadata. @@ -35,6 +38,7 @@ const ( // Reservation type label values ReservationTypeLabelCommittedResource = "committed-resource" ReservationTypeLabelFailover = "failover" + ReservationTypeLabelInFlight = "in-flight" ) // Annotation keys for Reservation metadata. @@ -104,10 +108,30 @@ type FailoverReservationSpec struct { ResourceGroup string `json:"resourceGroup,omitempty"` } +// InFlightReservationSpec defines the nature and shape of the virtual machine +// that is expected to land on the designated reservation slot. This spec +// carries information needed for the scheduler to produce a valid placement +// for new virtual machines for the duration the virtual machine is still +// in buildup. +type InFlightReservationSpec struct { + // VMID is the OpenStack server uuid from Nova assigned to the virtual + // machine expected to land on this reservation slot. + VMID string `json:"vmID,omitempty"` + // UserID is the identifier of the user who owns the virtual machine. + UserID string `json:"userID,omitempty"` + // ProjectID is the identifier of the project/tenant that owns + // the virtual machine. + ProjectID string `json:"projectID,omitempty"` + // Intent defines which kind of virtual machine lifecycle operation + // triggered the placement of this in-flight reservation. + // +kubebuilder:validation:Optional + Intent SchedulingIntent `json:"intent"` +} + // ReservationSpec defines the desired state of Reservation. type ReservationSpec struct { // Type of reservation. - // +kubebuilder:validation:Enum=CommittedResourceReservation;FailoverReservation + // +kubebuilder:validation:Enum=CommittedResourceReservation;FailoverReservation;InFlightReservation // +kubebuilder:validation:Required Type ReservationType `json:"type"` @@ -148,6 +172,10 @@ type ReservationSpec struct { // Only used when Type is FailoverReservation. // +kubebuilder:validation:Optional FailoverReservation *FailoverReservationSpec `json:"failoverReservation,omitempty"` + + // InFlightReservation specifies which kind of virtual machine is expected + // to land on the reserved slot. Set when Type is InFlightReservation. + InFlightReservation *InFlightReservationSpec `json:"inFlightReservation,omitempty"` } const ( @@ -189,6 +217,10 @@ type FailoverReservationStatus struct { AcknowledgedAt *metav1.Time `json:"acknowledgedAt,omitempty"` } +// InFlightReservationStatus defines the status fields specific to +// in-flight reservations. +type InFlightReservationStatus struct{} // No captured state for now. + // ReservationStatus defines the observed state of Reservation. type ReservationStatus struct { // The current status conditions of the reservation. @@ -219,6 +251,11 @@ type ReservationStatus struct { // Only used when Type is FailoverReservation. // +kubebuilder:validation:Optional FailoverReservation *FailoverReservationStatus `json:"failoverReservation,omitempty"` + + // InFlightReservation contains status fields specific to in-flight reservations. + // Only used when Type is InFlightReservation. + // +kubebuilder:validation:Optional + InFlightReservation *InFlightReservationStatus `json:"inFlightReservation,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a98f0bfff..89fe75d93 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1000,6 +1000,36 @@ func (in *IdentityDatasource) DeepCopy() *IdentityDatasource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InFlightReservationSpec) DeepCopyInto(out *InFlightReservationSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InFlightReservationSpec. +func (in *InFlightReservationSpec) DeepCopy() *InFlightReservationSpec { + if in == nil { + return nil + } + out := new(InFlightReservationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InFlightReservationStatus) DeepCopyInto(out *InFlightReservationStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InFlightReservationStatus. +func (in *InFlightReservationStatus) DeepCopy() *InFlightReservationStatus { + if in == nil { + return nil + } + out := new(InFlightReservationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KPI) DeepCopyInto(out *KPI) { *out = *in @@ -1778,6 +1808,11 @@ func (in *ReservationSpec) DeepCopyInto(out *ReservationSpec) { *out = new(FailoverReservationSpec) **out = **in } + if in.InFlightReservation != nil { + in, out := &in.InFlightReservation, &out.InFlightReservation + *out = new(InFlightReservationSpec) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReservationSpec. @@ -1810,6 +1845,11 @@ func (in *ReservationStatus) DeepCopyInto(out *ReservationStatus) { *out = new(FailoverReservationStatus) (*in).DeepCopyInto(*out) } + if in.InFlightReservation != nil { + in, out := &in.InFlightReservation, &out.InFlightReservation + *out = new(InFlightReservationStatus) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReservationStatus. diff --git a/helm/library/cortex/files/crds/cortex.cloud_reservations.yaml b/helm/library/cortex/files/crds/cortex.cloud_reservations.yaml index b4c5bfa6f..85995dc62 100644 --- a/helm/library/cortex/files/crds/cortex.cloud_reservations.yaml +++ b/helm/library/cortex/files/crds/cortex.cloud_reservations.yaml @@ -173,6 +173,31 @@ spec: (e.g., "hana_medium_v2"). type: string type: object + inFlightReservation: + description: |- + InFlightReservation specifies which kind of virtual machine is expected + to land on the reserved slot. Set when Type is InFlightReservation. + properties: + intent: + description: |- + Intent defines which kind of virtual machine lifecycle operation + triggered the placement of this in-flight reservation. + type: string + projectID: + description: |- + ProjectID is the identifier of the project/tenant that owns + the virtual machine. + type: string + userID: + description: UserID is the identifier of the user who owns the + virtual machine. + type: string + vmID: + description: |- + VMID is the OpenStack server uuid from Nova assigned to the virtual + machine expected to land on this reservation slot. + type: string + type: object resources: additionalProperties: anyOf: @@ -203,6 +228,7 @@ spec: enum: - CommittedResourceReservation - FailoverReservation + - InFlightReservation type: string required: - type @@ -330,6 +356,11 @@ spec: - For Nova: the hypervisor hostname - For Pods: the node name type: string + inFlightReservation: + description: |- + InFlightReservation contains status fields specific to in-flight reservations. + Only used when Type is InFlightReservation. + type: object type: object required: - spec