diff --git a/models/resources/service.go b/models/resources/service.go new file mode 100755 index 0000000..bec6556 --- /dev/null +++ b/models/resources/service.go @@ -0,0 +1,144 @@ +package resources + +import ( + "errors" + "time" + + "cloud.o-forge.io/core/oc-lib/models/common/enum" + "cloud.o-forge.io/core/oc-lib/models/common/models" + "cloud.o-forge.io/core/oc-lib/models/common/pricing" + "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/tools" + "github.com/google/uuid" +) + +type ServiceUsage struct { + CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs key is model + GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs key is model + RAM *models.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM + + StorageGb float64 `bson:"storage,omitempty" json:"storage,omitempty"` // Storage is the storage + Hypothesis string `bson:"hypothesis,omitempty" json:"hypothesis,omitempty"` + ScalingModel string `bson:"scaling_model,omitempty" json:"scaling_model,omitempty"` // ScalingModel is the scaling model +} + +/* +* ServiceResource is a struct that represents a processing resource +* it defines the resource processing + */ +type ServiceResource struct { + AbstractInstanciatedResource[*ServiceInstance] + IsEvent bool `json:"is_event,omitempty" bson:"is_event,omitempty"` + Infrastructure enum.InfrastructureType `json:"infrastructure" bson:"infrastructure" default:"-1"` // Infrastructure is the infrastructure + IsService bool `json:"is_service,omitempty" bson:"is_service,omitempty"` // IsService is a flag that indicates if the processing is a service + Usage *ServiceUsage `bson:"usage,omitempty" json:"usage,omitempty"` // Usage is the usage of the processing + OpenSource bool `json:"open_source" bson:"open_source" default:"false"` + License string `json:"license,omitempty" bson:"license,omitempty"` + Maturity string `json:"maturity,omitempty" bson:"maturity,omitempty"` +} + +func (r *ServiceResource) GetType() string { + return tools.PROCESSING_RESOURCE.String() +} + +type ServiceResourceAccess struct { + Container *models.Container `json:"container,omitempty" bson:"container,omitempty"` // Container is the container +} + +type ServiceInstance struct { + ResourceInstance[*ResourcePartnerShip[*ServiceResourcePricingProfile]] + Access *ServiceResourceAccess `json:"access,omitempty" bson:"access,omitempty"` // Access is the access + SizeGB int `json:"size_gb,omitempty" bson:"size_gb,omitempty"` + ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"` +} + +func NewServiceInstance(name string, peerID string) ResourceInstanceITF { + return &ServiceInstance{ + ResourceInstance: ResourceInstance[*ResourcePartnerShip[*ServiceResourcePricingProfile]]{ + AbstractObject: utils.AbstractObject{ + UUID: uuid.New().String(), + Name: name, + }, + }, + } +} + +type ServiceResourcePartnership struct { + ResourcePartnerShip[*ServiceResourcePricingProfile] +} + +type PricedServiceResource struct { + PricedResource[*ServiceResourcePricingProfile] + IsService bool +} + +func (r *PricedServiceResource) ensurePricing() { + if r.SelectedPricing == nil { + r.SelectedPricing = &ServiceResourcePricingProfile{} + } +} + +func (r *PricedServiceResource) IsPurchasable() bool { + r.ensurePricing() + return r.SelectedPricing.IsPurchasable() +} + +func (r *PricedServiceResource) IsBooked() bool { + r.ensurePricing() + return r.SelectedPricing.IsBooked() +} + +func (r *PricedServiceResource) GetPriceHT() (float64, error) { + r.ensurePricing() + return r.PricedResource.GetPriceHT() +} + +func (r *PricedServiceResource) GetType() tools.DataType { + return tools.PROCESSING_RESOURCE +} + +func (a *PricedServiceResource) GetExplicitDurationInS() float64 { + if a.BookingConfiguration == nil { + a.BookingConfiguration = &BookingConfiguration{} + } + if a.BookingConfiguration.ExplicitBookingDurationS == 0 { + if a.IsService || a.BookingConfiguration.UsageStart == nil { + if a.IsService { + return -1 + } + return (5 * time.Minute).Seconds() + } + return a.BookingConfiguration.UsageEnd.Sub(*a.BookingConfiguration.UsageStart).Seconds() + } + return a.BookingConfiguration.ExplicitBookingDurationS +} + +func (d *ServiceResource) GetAccessor(request *tools.APIRequest) utils.Accessor { + return NewAccessor[*ServiceResource](tools.PROCESSING_RESOURCE, request) // Create a new instance of the accessor +} + +func (abs *ServiceResource) ConvertToPricedResource(t tools.DataType, selectedInstance *int, selectedPartnership *int, selectedBuyingStrategy *int, selectedStrategy *int, selectedBookingModeIndex *int, request *tools.APIRequest) (pricing.PricedItemITF, error) { + if t != tools.PROCESSING_RESOURCE { + return nil, errors.New("not the proper type expected : cannot convert to priced resource : have " + t.String() + " wait Data") + } + p, err := ConvertToPricedResource[*DataResourcePricingProfile](t, selectedInstance, selectedPartnership, selectedBuyingStrategy, selectedStrategy, selectedBookingModeIndex, abs, request) + if err != nil { + return nil, err + } + priced := p.(*PricedResource[*DataResourcePricingProfile]) + return &PricedDataResource{ + PricedResource: *priced, + }, nil +} + +type ServiceResourcePricingProfile struct { + pricing.AccessPricingProfile[pricing.TimePricingStrategy] // AccessPricingProfile is the pricing profile of a data it means that we can access the data for an amount of time +} + +func (p *ServiceResourcePricingProfile) IsPurchasable() bool { + return p.Pricing.BuyingStrategy == pricing.PERMANENT +} + +func (p *ServiceResourcePricingProfile) IsBooked() bool { + return p.Pricing.BuyingStrategy != pricing.PERMANENT +} diff --git a/models/utils/common.go b/models/utils/common.go index 753abe6..5b152ab 100755 --- a/models/utils/common.go +++ b/models/utils/common.go @@ -17,6 +17,9 @@ type Owner struct { } func VerifyAccess(a Accessor, id string) error { + if a == nil { + return errors.New("no accessor to verify access") + } data, _, err := a.LoadOne(id) if err != nil { return err diff --git a/models/workflow/workflow_mongo_accessor.go b/models/workflow/workflow_mongo_accessor.go index 28df832..3686154 100644 --- a/models/workflow/workflow_mongo_accessor.go +++ b/models/workflow/workflow_mongo_accessor.go @@ -219,6 +219,8 @@ func (a *workflowMongoAccessor) verifyResource(obj utils.DBObject) utils.DBObjec access = resources.NewAccessor[*resources.WorkflowResource](t, a.GetRequest()) case tools.DATA_RESOURCE: access = resources.NewAccessor[*resources.DataResource](t, a.GetRequest()) + case tools.NATIVE_TOOL: + access = resources.NewAccessor[*resources.NativeTool](t, a.GetRequest()) default: wf.Graph.Clear(resource.GetID()) }