Files
oc-lib/models/booking/booking.go

129 lines
5.4 KiB
Go
Raw Normal View History

2024-08-12 14:18:13 +02:00
package booking
import (
"time"
2025-01-16 10:14:55 +01:00
"cloud.o-forge.io/core/oc-lib/models/common/enum"
2025-06-18 07:58:40 +02:00
"cloud.o-forge.io/core/oc-lib/models/common/models"
2024-08-12 14:18:13 +02:00
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
2024-08-12 14:18:13 +02:00
)
/*
* Booking is a struct that represents a booking
*/
2024-08-12 14:18:13 +02:00
type Booking struct {
2025-07-08 13:42:13 +02:00
utils.AbstractObject // AbstractObject contains the basic fields of an object (id, name)
PricedItem map[string]interface{} `json:"priced_item,omitempty" bson:"priced_item,omitempty"` // We need to add the validate:"required" tag once the pricing feature is implemented, removed to avoid handling the error
2025-06-18 07:58:40 +02:00
2025-07-08 13:42:13 +02:00
ResumeMetrics map[string]map[string]models.MetricResume `json:"resume_metrics,omitempty" bson:"resume_metrics,omitempty"`
2025-06-18 07:58:40 +02:00
ExecutionMetrics map[string][]models.MetricsSnapshot `json:"metrics,omitempty" bson:"metrics,omitempty"`
ExecutionsID string `json:"executions_id,omitempty" bson:"executions_id,omitempty" validate:"required"` // ExecutionsID is the ID of the executions
2026-01-13 16:04:31 +01:00
DestPeerID string `json:"dest_peer_id,omitempty" bson:"dest_peer_id,omitempty"` // DestPeerID is the ID of the destination peer
2025-06-18 07:58:40 +02:00
WorkflowID string `json:"workflow_id,omitempty" bson:"workflow_id,omitempty"` // WorkflowID is the ID of the workflow
ExecutionID string `json:"execution_id,omitempty" bson:"execution_id,omitempty" validate:"required"`
2026-03-16 10:49:39 +01:00
State enum.BookingStatus `json:"state" bson:"state"` // State is the state of the booking
2025-06-18 07:58:40 +02:00
ExpectedStartDate time.Time `json:"expected_start_date,omitempty" bson:"expected_start_date,omitempty" validate:"required"` // ExpectedStartDate is the expected start date of the booking
ExpectedEndDate *time.Time `json:"expected_end_date,omitempty" bson:"expected_end_date,omitempty" validate:"required"` // ExpectedEndDate is the expected end date of the booking
RealStartDate *time.Time `json:"real_start_date,omitempty" bson:"real_start_date,omitempty"` // RealStartDate is the real start date of the booking
RealEndDate *time.Time `json:"real_end_date,omitempty" bson:"real_end_date,omitempty"` // RealEndDate is the real end date of the booking
2025-01-13 12:25:57 +01:00
ResourceType tools.DataType `json:"resource_type,omitempty" bson:"resource_type,omitempty" validate:"required"` // ResourceType is the type of the resource
ResourceID string `json:"resource_id,omitempty" bson:"resource_id,omitempty" validate:"required"` // could be a Compute or a Storage
InstanceID string `json:"instance_id,omitempty" bson:"instance_id,omitempty" validate:"required"` // could be a Compute or a Storage
2026-03-16 08:52:31 +01:00
// Authorization: identifies who created this draft and the Check session it belongs to.
// Used to verify UPDATE and DELETE orders from remote schedulers.
SchedulerPeerID string `json:"scheduler_peer_id,omitempty" bson:"scheduler_peer_id,omitempty"`
2024-08-12 14:18:13 +02:00
}
2025-06-18 07:58:40 +02:00
func (b *Booking) CalcDeltaOfExecution() map[string]map[string]models.MetricResume {
m := map[string]map[string]models.MetricResume{}
for instance, snapshot := range b.ExecutionMetrics {
m[instance] = map[string]models.MetricResume{}
for _, metric := range snapshot {
for _, mm := range metric.Metrics {
if resume, ok := m[instance][mm.Name]; !ok {
m[instance][mm.Name] = models.MetricResume{
Delta: 0,
LastValue: mm.Value,
}
} else {
delta := resume.LastValue - mm.Value
if delta == 0 {
resume.Delta = delta
} else {
resume.Delta = (resume.Delta + delta) / 2
}
resume.LastValue = mm.Value
m[instance][mm.Name] = resume
}
}
}
}
return m
}
func (d *Booking) GetDelayForLaunch() time.Duration {
return d.RealStartDate.Sub(d.ExpectedStartDate)
}
func (d *Booking) GetDelayForFinishing() time.Duration {
2026-03-20 16:14:07 +01:00
if d.ExpectedEndDate == nil || d.RealEndDate == nil {
return time.Duration(0)
}
2026-03-20 16:14:07 +01:00
return d.RealEndDate.Sub(*d.ExpectedEndDate)
2024-08-12 14:18:13 +02:00
}
func (d *Booking) GetUsualDuration() time.Duration {
return d.ExpectedEndDate.Sub(d.ExpectedStartDate)
}
func (d *Booking) GetRealDuration() time.Duration {
if d.RealEndDate == nil || d.RealStartDate == nil {
return time.Duration(0)
}
return d.RealEndDate.Sub(*d.RealStartDate)
}
func (d *Booking) GetDelayOnDuration() time.Duration {
return d.GetRealDuration() - d.GetUsualDuration()
2024-08-12 14:18:13 +02:00
}
func (d *Booking) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor(request) // Create a new instance of the accessor
2024-08-12 14:18:13 +02:00
}
2024-12-04 12:14:55 +01:00
2026-01-13 16:04:31 +01:00
func (d *Booking) VerifyAuth(callName string, request *tools.APIRequest) bool {
2024-12-04 12:14:55 +01:00
return true
}
func (r *Booking) StoreDraftDefault() {
2026-03-16 10:59:31 +01:00
r.IsDraft = true
r.State = enum.DRAFT
}
func (r *Booking) CanUpdate(set utils.DBObject) (bool, utils.DBObject) {
2026-03-20 16:14:07 +01:00
incoming := set.(*Booking)
if !r.IsDraft && r.State != incoming.State || r.RealStartDate != incoming.RealStartDate || r.RealEndDate != incoming.RealEndDate {
patch := &Booking{
State: incoming.State,
RealStartDate: incoming.RealStartDate,
RealEndDate: incoming.RealEndDate,
}
// Auto-set RealStartDate when transitioning to STARTED and not already set
if r.State != enum.STARTED && incoming.State == enum.STARTED && patch.RealStartDate == nil {
now := time.Now()
patch.RealStartDate = &now
}
return true, patch
}
return r.IsDraft, set
}
func (r *Booking) CanDelete() bool {
return r.IsDraft // only draft bookings can be deleted
}