Files
oc-lib/models/resources/compute.go

225 lines
8.8 KiB
Go
Raw Normal View History

2024-11-28 16:49:41 +01:00
package resources
2024-07-18 11:51:12 +02:00
import (
"errors"
"strings"
"time"
2025-01-15 10:56:44 +01:00
"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"
2024-07-18 13:35:14 +02:00
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
2026-01-12 11:59:05 +01:00
"github.com/google/uuid"
2024-07-18 11:51:12 +02:00
)
/*
2024-11-07 11:05:24 +01:00
* ComputeResource is a struct that represents a compute resource
* it defines the resource compute
*/
2024-11-07 11:05:24 +01:00
type ComputeResource struct {
2025-02-13 15:11:23 +01:00
AbstractInstanciatedResource[*ComputeResourceInstance]
2025-01-15 10:56:44 +01:00
Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture
2025-01-17 10:07:37 +01:00
Infrastructure enum.InfrastructureType `json:"infrastructure" bson:"infrastructure" default:"-1"` // Infrastructure is the infrastructure
}
2024-11-07 11:36:31 +01:00
func (d *ComputeResource) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor[*ComputeResource](tools.COMPUTE_RESOURCE, request, func() utils.DBObject { return &ComputeResource{} })
}
2024-11-07 11:36:31 +01:00
2025-01-20 13:26:30 +01:00
func (r *ComputeResource) GetType() string {
return tools.COMPUTE_RESOURCE.String()
}
2026-01-13 16:04:31 +01:00
func (abs *ComputeResource) ConvertToPricedResource(t tools.DataType, selectedInstance *int, selectedPartnership *int, selectedBuyingStrategy *int, selectedStrategy *int, selectedBookingModeIndex *int, request *tools.APIRequest) (pricing.PricedItemITF, error) {
2025-01-15 10:56:44 +01:00
if t != tools.COMPUTE_RESOURCE {
2026-01-13 16:04:31 +01:00
return nil, errors.New("not the proper type expected : cannot convert to priced resource : have " + t.String() + " wait Compute")
}
p, err := abs.AbstractInstanciatedResource.ConvertToPricedResource(t, selectedInstance, selectedPartnership, selectedBuyingStrategy, selectedStrategy, selectedBookingModeIndex, request)
if err != nil {
return nil, err
2025-01-15 10:56:44 +01:00
}
2025-01-15 09:20:26 +01:00
priced := p.(*PricedResource)
return &PricedComputeResource{
PricedResource: *priced,
2026-01-13 16:04:31 +01:00
}, nil
2025-01-15 09:20:26 +01:00
}
2025-01-14 11:28:16 +01:00
type ComputeNode struct {
Name string `json:"name,omitempty" bson:"name,omitempty"`
Quantity int64 `json:"quantity" bson:"quantity" default:"1"`
2025-01-15 10:56:44 +01:00
RAM *models.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM
2025-01-14 11:28:16 +01:00
CPUs map[string]int64 `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs key is model
GPUs map[string]int64 `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs key is model
}
type ComputeResourceInstance struct {
ResourceInstance[*ComputeResourcePartnership]
2025-02-13 15:11:23 +01:00
Source string `json:"source,omitempty" bson:"source,omitempty"` // Source is the source of the resource
2025-01-14 11:28:16 +01:00
SecurityLevel string `json:"security_level,omitempty" bson:"security_level,omitempty"`
PowerSources []string `json:"power_sources,omitempty" bson:"power_sources,omitempty"`
AnnualCO2Emissions float64 `json:"annual_co2_emissions,omitempty" bson:"co2_emissions,omitempty"`
2025-01-15 10:56:44 +01:00
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
2025-01-14 11:28:16 +01:00
Nodes []*ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"`
2024-07-18 11:51:12 +02:00
}
2026-01-12 11:59:05 +01:00
func NewComputeResourceInstance(name string, peerID string) ResourceInstanceITF {
return &ComputeResourceInstance{
ResourceInstance: ResourceInstance[*ComputeResourcePartnership]{
AbstractObject: utils.AbstractObject{
UUID: uuid.New().String(),
Name: name,
},
},
}
}
type ComputeResourcePartnership struct {
2025-01-22 13:18:14 +01:00
ResourcePartnerShip[*ComputeResourcePricingProfile]
2025-06-17 16:42:21 +02:00
MinGaranteedCPUsCores map[string]float64 `json:"garanteed_cpus,omitempty" bson:"garanteed_cpus,omitempty"`
2025-06-17 15:06:33 +02:00
MinGaranteedGPUsMemoryGB map[string]float64 `json:"garanteed_gpus,omitempty" bson:"garanteed_gpus,omitempty"`
MinGaranteedRAMSize float64 `json:"garanteed_ram,omitempty" bson:"garanteed_ram,omitempty"`
2025-06-17 16:42:21 +02:00
MaxAllowedCPUsCores map[string]float64 `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"`
2024-07-18 11:51:12 +02:00
}
2024-07-26 15:19:36 +02:00
type ComputeResourcePricingProfile struct {
2024-12-16 12:17:20 +01:00
pricing.ExploitPricingProfile[pricing.TimePricingStrategy]
// ExploitPricingProfile is the pricing profile of a compute it means that we exploit the resource for an amount of continuous time
2025-01-16 15:14:56 +01:00
CPUsPrices map[string]float64 `json:"cpus_prices,omitempty" bson:"cpus_prices,omitempty"` // CPUsPrices is the prices of the CPUs
GPUsPrices map[string]float64 `json:"gpus_prices,omitempty" bson:"gpus_prices,omitempty"` // GPUsPrices is the prices of the GPUs
RAMPrice float64 `json:"ram_price" bson:"ram_price" default:"-1"` // RAMPrice is the price of the RAM
2024-07-26 15:19:36 +02:00
}
2024-11-28 16:49:41 +01:00
2025-06-20 07:51:32 +02:00
func (p *ComputeResourcePricingProfile) IsPurchasable() bool {
return p.Pricing.BuyingStrategy != pricing.UNDEFINED_SUBSCRIPTION
}
2025-06-20 12:10:36 +02:00
func (p *ComputeResourcePricingProfile) GetPurchase() pricing.BuyingStrategy {
return p.Pricing.BuyingStrategy
}
2025-06-20 07:51:32 +02:00
func (p *ComputeResourcePricingProfile) IsBooked() bool {
if p.Pricing.BuyingStrategy == pricing.PERMANENT {
p.Pricing.BuyingStrategy = pricing.SUBSCRIPTION
}
return true
}
2024-11-28 16:49:41 +01:00
func (p *ComputeResourcePricingProfile) GetOverrideStrategyValue() int {
return -1
2024-11-28 16:49:41 +01:00
}
// NOT A PROPER QUANTITY
// amountOfData is the number of CPUs, GPUs or RAM dependings on the params
2026-01-13 16:04:31 +01:00
func (p *ComputeResourcePricingProfile) GetPriceHT(amountOfData float64, explicitDuration float64, start time.Time, end time.Time, variation []*pricing.PricingVariation, 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 {
2025-01-16 15:14:56 +01:00
if _, ok := p.CPUsPrices[model]; ok {
p.Pricing.Price = p.CPUsPrices[model]
}
2026-01-13 16:04:31 +01:00
r, err := p.Pricing.GetPriceHT(amountOfData, explicitDuration, start, &end, variation)
if err != nil {
return 0, err
}
pp += r
2024-11-28 16:49:41 +01:00
}
if strings.Contains(params[0], "gpus") && len(params) > 1 {
2025-01-16 15:14:56 +01:00
if _, ok := p.GPUsPrices[model]; ok {
p.Pricing.Price = p.GPUsPrices[model]
}
2026-01-13 16:04:31 +01:00
r, err := p.Pricing.GetPriceHT(amountOfData, explicitDuration, start, &end, variation)
if err != nil {
return 0, err
}
pp += r
}
if strings.Contains(params[0], "ram") {
2025-01-16 15:14:56 +01:00
if p.RAMPrice >= 0 {
p.Pricing.Price = p.RAMPrice
}
2026-01-13 16:04:31 +01:00
r, err := p.Pricing.GetPriceHT(float64(amountOfData), explicitDuration, start, &end, variation)
if err != nil {
return 0, err
}
pp += r
}
return pp, nil
}
2025-01-13 11:24:07 +01:00
type PricedComputeResource struct {
PricedResource
2024-11-28 16:49:41 +01:00
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
}
2025-01-13 11:24:07 +01:00
func (r *PricedComputeResource) GetType() tools.DataType {
return tools.COMPUTE_RESOURCE
}
2026-01-13 16:04:31 +01:00
func (r *PricedComputeResource) GetPriceHT() (float64, error) {
if r.BookingConfiguration == nil {
r.BookingConfiguration = &BookingConfiguration{}
}
2025-02-10 13:04:13 +01:00
now := time.Now()
2026-01-13 16:04:31 +01:00
if r.BookingConfiguration.UsageStart == nil {
r.BookingConfiguration.UsageStart = &now
}
2026-01-13 16:04:31 +01:00
if r.BookingConfiguration.UsageEnd == nil {
add := r.BookingConfiguration.UsageStart.Add(time.Duration(1 * time.Hour))
r.BookingConfiguration.UsageEnd = &add
}
2025-02-10 13:10:42 +01:00
if r.SelectedPricing == nil {
2025-06-20 12:10:36 +02:00
return 0, errors.New("pricing profile must be set on Priced Compute" + r.ResourceID)
2025-02-10 13:04:13 +01:00
}
2025-06-16 13:48:32 +02:00
pricing := r.SelectedPricing
price := float64(0)
for _, l := range []map[string]float64{r.CPUsLocated, r.GPUsLocated} {
for model, amountOfData := range l {
2026-01-13 16:04:31 +01:00
cpus, err := pricing.GetPriceHT(float64(amountOfData),
r.BookingConfiguration.ExplicitBookingDurationS, *r.BookingConfiguration.UsageStart,
*r.BookingConfiguration.UsageEnd, r.Variations, "cpus", model)
if err != nil {
return 0, err
}
price += cpus
}
}
2026-01-13 16:04:31 +01:00
ram, err := pricing.GetPriceHT(r.RAMLocated, r.BookingConfiguration.ExplicitBookingDurationS,
*r.BookingConfiguration.UsageStart, *r.BookingConfiguration.UsageEnd, r.Variations, "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
*/
2025-01-13 11:24:07 +01:00
func (i *PricedComputeResource) 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
2024-11-28 16:49:41 +01:00
}