package resources import ( "errors" "strings" "time" "cloud.o-forge.io/core/oc-lib/models/common" "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" ) /* * ComputeResource is a struct that represents a compute resource * it defines the resource compute */ type ComputeResource struct { AbstractResource[*ComputeResourceInstance] Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture Infrastructure common.InfrastructureType `json:"infrastructure,omitempty" bson:"infrastructure,omitempty"` } func (d *ComputeResource) GetAccessor(request *tools.APIRequest) utils.Accessor { return NewAccessor[*ComputeResource](tools.COMPUTE_RESOURCE, request, func() utils.DBObject { return &ComputeResource{} }) } type ComputeResourceInstance struct { ResourceInstance[*ComputeResourcePartnership] SecurityLevel string `json:"security_level,omitempty" bson:"security_level,omitempty"` PowerSource string `json:"power_source,omitempty" bson:"power_source,omitempty"` CPUs map[string]*common.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs key is model GPUs map[string]*common.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs key is model RAM *common.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM } type ComputeResourcePartnership struct { ResourcePartnerShip[*ComputeResourcePricingProfile] MaxAllowedCPUsCores map[string]int `json:"allowed_cpus,omitempty" bson:"allowed_cpus,omitempty"` MaxAllowedGPUsMemoryGB map[string]float64 `json:"allowed_gpus,omitempty" bson:"allowed_gpus,omitempty"` MaxAllowedRAMSize float64 `json:"allowed_ram,omitempty" bson:"allowed_ram,omitempty"` } type ComputeResourcePricingProfileOptions struct { CPUCore int `json:"cpu_core" bson:"cpu_core" default:"1"` GPUMemoryGB float64 `json:"gpu_memory_gb" bson:"gpu_memory_gb" default:"1"` RAMSizeGB float64 `json:"ram_size_gb" bson:"ram_size_gb" default:"1"` } type ComputeResourcePricingProfile struct { pricing.ExploitPricingProfile[pricing.TimePricingStrategy] Options ComputeResourcePricingProfileOptions `json:"options,omitempty" bson:"options,omitempty"` // Options is the options of the pricing profile // ExploitPricingProfile is the pricing profile of a compute it means that we exploit the resource for an amount of continuous time OverrideCPUsPrices map[string]float64 `json:"cpus_prices,omitempty" bson:"cpus_prices,omitempty"` // CPUsPrices is the prices of the CPUs OverrideGPUsPrices map[string]float64 `json:"gpus_prices,omitempty" bson:"gpus_prices,omitempty"` // GPUsPrices is the prices of the GPUs OverrideRAMPrice float64 `json:"ram_price" bson:"ram_price" default:"-1"` // RAMPrice is the price of the RAM } // PROBLEM func (p *ComputeResourcePricingProfile) IsBuying() bool { return p.Pricing.BuyingStrategy != pricing.PAY_PER_USE } func (p *ComputeResourcePricingProfile) GetOverrideStrategyValue() int { return -1 } // NOT A PROPER QUANTITY // amountOfData is the number of CPUs, GPUs or RAM dependings on the params func (p *ComputeResourcePricingProfile) GetPrice(amountOfData float64, explicitDuration float64, start time.Time, end time.Time, request *tools.APIRequest, params ...string) (float64, error) { if len(params) < 1 { return 0, errors.New("params must be set") } pp := float64(0) model := params[1] if strings.Contains(params[0], "cpus") && len(params) > 1 { if _, ok := p.OverrideCPUsPrices[model]; ok { p.Pricing.Price = p.OverrideCPUsPrices[model] } r, err := p.Pricing.GetPrice(amountOfData/float64(p.Options.CPUCore), explicitDuration, start, &end) if err != nil { return 0, err } pp += r } if strings.Contains(params[0], "gpus") && len(params) > 1 { if _, ok := p.OverrideGPUsPrices[model]; ok { p.Pricing.Price = p.OverrideGPUsPrices[model] } r, err := p.Pricing.GetPrice(amountOfData/float64(p.Options.GPUMemoryGB), explicitDuration, start, &end) if err != nil { return 0, err } pp += r } if strings.Contains(params[0], "ram") { if p.OverrideRAMPrice >= 0 { p.Pricing.Price = p.OverrideRAMPrice } r, err := p.Pricing.GetPrice(float64(amountOfData)/p.Options.RAMSizeGB, explicitDuration, start, &end) if err != nil { return 0, err } pp += r } return pp, nil } type CustomizedComputeResource struct { AbstractCustomizedResource[*ComputeResourceInstance] CPUsLocated map[string]float64 `json:"cpus_in_use" bson:"cpus_in_use"` // CPUsInUse is the list of CPUs in use GPUsLocated map[string]float64 `json:"gpus_in_use" bson:"gpus_in_use"` // GPUsInUse is the list of GPUs in use RAMLocated float64 `json:"ram_in_use" bson:"ram_in_use"` // RAMInUse is the RAM in use } func (r *CustomizedComputeResource) GetType() tools.DataType { return tools.COMPUTE_RESOURCE } func (r *CustomizedComputeResource) GetPrice(request *tools.APIRequest) (float64, error) { if r.UsageStart == nil || r.UsageEnd == nil { return 0, errors.New("Usage start and end must be set") } partner := r.GetPartnership(request) if partner != nil && partner.GetPricing(r.SelectedPricing) != nil { return 0, errors.New("Pricing strategy not found") } pricing := partner.GetPricing(r.SelectedPricing) price := float64(0) for _, l := range []map[string]float64{r.CPUsLocated, r.GPUsLocated} { for model, amountOfData := range l { cpus, err := pricing.GetPrice(float64(amountOfData), r.ExplicitBookingDurationS, *r.UsageStart, *r.UsageEnd, request, "cpus", model) if err != nil { return 0, err } price += cpus } } ram, err := pricing.GetPrice(r.RAMLocated, r.ExplicitBookingDurationS, *r.UsageStart, *r.UsageEnd, request, "ram") if err != nil { return 0, err } price += ram return price, nil } /* * FillWithDefaultProcessingUsage fills the order item with the default processing usage * it depends on the processing usage only if nothing is set, during order */ func (i *CustomizedComputeResource) FillWithDefaultProcessingUsage(usage *ProcessingUsage) { for _, cpu := range usage.CPUs { if _, ok := i.CPUsLocated[cpu.Model]; !ok { i.CPUsLocated[cpu.Model] = 0 } if i.CPUsLocated[cpu.Model] < float64(cpu.Cores) { i.CPUsLocated[cpu.Model] = float64(cpu.Cores) } } for _, cpu := range usage.GPUs { i.GPUsLocated[cpu.Model] = 1 } i.RAMLocated = usage.RAM.SizeGb }