package booking import ( "time" "cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/models/common" "cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/tools" "go.mongodb.org/mongo-driver/bson/primitive" ) /* * Booking is a struct that represents a booking */ type Booking struct { utils.AbstractObject // AbstractObject contains the basic fields of an object (id, name) DestPeerID string `json:"dest_peer_id,omitempty"` // DestPeerID is the ID of the destination peer ExecutionID string `json:"execution_id,omitempty" bson:"execution_id,omitempty" validate:"required"` State common.ScheduledType `json:"state,omitempty" bson:"state,omitempty" validate:"required"` // State is the state of the booking 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 ResourceType tools.DataType `json:"resource_type,omitempty" bson:"resource_type,omitempty" validate:"required"` // ResourceType is the type of the resource ResourceID string `json:"compute_resource_id,omitempty" bson:"compute_resource_id,omitempty" validate:"required"` // could be a Compute or a Storage } // CheckBooking checks if a booking is possible on a specific compute resource func (wfa *Booking) Check(id string, start time.Time, end *time.Time, parrallelAllowed int) (bool, error) { // check if if end == nil { // if no end... then Book like a savage e := start.Add(time.Hour) end = &e } accessor := NewAccessor(nil) res, code, err := accessor.Search(&dbs.Filters{ And: map[string][]dbs.Filter{ // check if there is a booking on the same compute resource by filtering on the compute_resource_id, the state and the execution date "resource_id": {{Operator: dbs.EQUAL.String(), Value: id}}, "state": {{Operator: dbs.EQUAL.String(), Value: common.DRAFT.EnumIndex()}}, "expected_start_date": { {Operator: dbs.LTE.String(), Value: primitive.NewDateTimeFromTime(*end)}, {Operator: dbs.GTE.String(), Value: primitive.NewDateTimeFromTime(start)}, }, }, }, "", wfa.IsDraft) if code != 200 { return false, err } return len(res) <= parrallelAllowed, nil } func (d *Booking) GetDelayForLaunch() time.Duration { return d.RealStartDate.Sub(d.ExpectedStartDate) } func (d *Booking) GetDelayForFinishing() time.Duration { if d.ExpectedEndDate == nil { return time.Duration(0) } return d.RealEndDate.Sub(d.ExpectedStartDate) } 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() } func (d *Booking) GetName() string { return d.GetID() + "_" + d.ExpectedStartDate.String() } func (d *Booking) GetAccessor(request *tools.APIRequest) utils.Accessor { return NewAccessor(request) // Create a new instance of the accessor } func (d *Booking) VerifyAuth(request *tools.APIRequest) bool { return true } func (r *Booking) StoreDraftDefault() { r.IsDraft = true } func (r *Booking) CanUpdate(set utils.DBObject) (bool, utils.DBObject) { if !r.IsDraft && r.State != set.(*Booking).State || r.RealStartDate != set.(*Booking).RealStartDate || r.RealEndDate != set.(*Booking).RealEndDate { return true, &Booking{ State: set.(*Booking).State, RealStartDate: set.(*Booking).RealStartDate, RealEndDate: set.(*Booking).RealEndDate, } // only state can be updated } // TODO : HERE WE CAN HANDLE THE CASE WHERE THE BOOKING IS DELAYED OR EXCEEDING OR ending sooner return r.IsDraft, set } func (r *Booking) CanDelete() bool { return r.IsDraft // only draft bookings can be deleted }