168 lines
6.4 KiB
Go
168 lines
6.4 KiB
Go
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
|
|
}
|