Live x Resource Synergy

This commit is contained in:
mr
2026-04-28 11:48:23 +02:00
parent e3fbe7688a
commit f926a42066
11 changed files with 124 additions and 194 deletions

View File

@@ -1,18 +1,13 @@
package live package live
import ( import (
"cloud.o-forge.io/core/oc-lib/models/resources"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
) )
type LiveInterface interface { type LiveInterface interface {
utils.DBObject utils.DBObject
IsCompatible(service map[string]interface{}) bool
GetMonitorPath() string GetMonitorPath() string
GetResourcesID() []string GetResourcesID() []string
SetResourcesID(string) SetResourcesID(string)
GetResourceAccessor(request *tools.APIRequest) utils.Accessor
GetResource() resources.ResourceInterface
GetResourceInstance() resources.ResourceInstanceITF
SetResourceInstance(res resources.ResourceInterface, i resources.ResourceInstanceITF) resources.ResourceInterface
} }

View File

@@ -3,7 +3,6 @@ package live
import ( import (
"slices" "slices"
"cloud.o-forge.io/core/oc-lib/models/resources"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
"github.com/biter777/countries" "github.com/biter777/countries"
@@ -32,13 +31,17 @@ type LiveCerts struct {
} }
// TODO in the future multiple type of certs depending of infra type // TODO in the future multiple type of certs depending of infra type
type GeoPoint struct {
Latitude float64 `json:"latitude,omitempty" bson:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty" bson:"longitude,omitempty"`
}
type AbstractLive struct { type AbstractLive struct {
utils.AbstractObject utils.AbstractObject
Certs LiveCerts `json:"certs,omitempty" bson:"certs,omitempty"` Certs LiveCerts `json:"certs,omitempty" bson:"certs,omitempty"`
MonitorPath string `json:"monitor_path,omitempty" bson:"monitor_path,omitempty"` MonitorPath string `json:"monitor_path,omitempty" bson:"monitor_path,omitempty"`
Location resources.GeoPoint `json:"location,omitempty" bson:"location,omitempty"` Location GeoPoint `json:"location,omitempty" bson:"location,omitempty"`
Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"` Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"`
AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"` AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"`
ResourcesID []string `json:"resources_id" bson:"resources_id"` ResourcesID []string `json:"resources_id" bson:"resources_id"`
@@ -71,9 +74,9 @@ func (d *AbstractLive) GetResourcesID() []string {
return d.ResourcesID return d.ResourcesID
} }
func (d *AbstractLive) SetResourcesID(id string) { func (d *AbstractLive) SetResourcesID(resourcesid string) {
if !slices.Contains(d.ResourcesID, id) { if slices.Contains(d.ResourcesID, resourcesid) {
d.ResourcesID = append(d.ResourcesID, id) d.ResourcesID = append(d.ResourcesID, resourcesid)
} }
} }

View File

@@ -3,7 +3,6 @@ package live
import ( import (
"cloud.o-forge.io/core/oc-lib/models/common/enum" "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/models"
"cloud.o-forge.io/core/oc-lib/models/resources"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
) )
@@ -12,39 +11,34 @@ import (
* LiveDatacenter is a struct that represents a compute units in your datacenters * LiveDatacenter is a struct that represents a compute units in your datacenters
*/ */
type ComputeNode struct {
Name string `json:"name,omitempty" bson:"name,omitempty"`
Quantity int64 `json:"quantity" bson:"quantity" default:"1"`
RAM *models.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM
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 LiveDatacenter struct { type LiveDatacenter struct {
AbstractLive AbstractLive
StorageType enum.StorageType `bson:"storage_type" json:"storage_type" default:"-1"` // Type is the type of the storage StorageType enum.StorageType `bson:"storage_type" json:"storage_type" default:"-1"` // Type is the type of the storage
Acronym string `bson:"acronym,omitempty" json:"acronym,omitempty"` // Acronym is the acronym of the storage Acronym string `bson:"acronym,omitempty" json:"acronym,omitempty"` // Acronym is the acronym of the storage
Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture
Infrastructure enum.InfrastructureType `json:"infrastructure" bson:"infrastructure" default:"-1"` // Infrastructure is the infrastructure Infrastructure enum.InfrastructureType `json:"infrastructure" bson:"infrastructure" default:"-1"` // Infrastructure is the infrastructure
Source string `json:"source,omitempty" bson:"source,omitempty"` // Source is the source of the resource Source string `json:"source,omitempty" bson:"source,omitempty"` // Source is the source of the resource
SecurityLevel string `json:"security_level,omitempty" bson:"security_level,omitempty"` SecurityLevel string `json:"security_level,omitempty" bson:"security_level,omitempty"`
PowerSources []string `json:"power_sources,omitempty" bson:"power_sources,omitempty"` PowerSources []string `json:"power_sources,omitempty" bson:"power_sources,omitempty"`
AnnualCO2Emissions float64 `json:"annual_co2_emissions,omitempty" bson:"co2_emissions,omitempty"` AnnualCO2Emissions float64 `json:"annual_co2_emissions,omitempty" bson:"co2_emissions,omitempty"`
CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs key is model 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 GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs key is model
Nodes []*resources.ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"` Nodes []*ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"`
}
func (r *LiveDatacenter) IsCompatible(service map[string]interface{}) bool {
return service["infrastructure"] == r.Infrastructure && service["architecture"] == r.Architecture
} }
func (d *LiveDatacenter) GetAccessor(request *tools.APIRequest) utils.Accessor { func (d *LiveDatacenter) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor[*LiveDatacenter](tools.LIVE_DATACENTER, request) // Create a new instance of the accessor return NewAccessor[*LiveDatacenter](tools.LIVE_DATACENTER, request) // Create a new instance of the accessor
} }
func (d *LiveDatacenter) GetResourceAccessor(request *tools.APIRequest) utils.Accessor {
return resources.NewAccessor[*resources.ComputeResource](tools.COMPUTE_RESOURCE, request)
}
func (d *LiveDatacenter) GetResource() resources.ResourceInterface {
return &resources.ComputeResource{}
}
func (d *LiveDatacenter) GetResourceInstance() resources.ResourceInstanceITF {
return &resources.ComputeResourceInstance{}
}
func (d *LiveDatacenter) SetResourceInstance(res resources.ResourceInterface, i resources.ResourceInstanceITF) resources.ResourceInterface {
r := res.(*resources.ComputeResource)
r.Instances = append(r.Instances, i.(*resources.ComputeResourceInstance))
return r
}

View File

@@ -1,9 +1,6 @@
package live package live
import ( import (
"encoding/json"
"errors"
"cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/logs" "cloud.o-forge.io/core/oc-lib/logs"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
@@ -32,67 +29,11 @@ func NewAccessor[T LiveInterface](t tools.DataType, request *tools.APIRequest) *
} }
return &LiveDatacenter{} return &LiveDatacenter{}
}, },
NotImplemented: []string{"CopyOne"},
}, },
} }
} }
/*
* Nothing special here, just the basic CRUD operations
*/
func (a *liveMongoAccessor[T]) CopyOne(data utils.DBObject) (utils.DBObject, int, error) {
// is a publisher... that become a resources.
if data.IsDrafted() {
return nil, 422, errors.New("can't publish a drafted compute units")
}
live := data.(T)
/*if live.GetMonitorPath() == "" || live.GetID() != "" {
return nil, 422, errors.New("publishing is only allowed is it can be monitored and be accessible")
}*/
if res, code, err := a.LoadOne(live.GetID()); err != nil {
return nil, code, err
} else {
live = res.(T)
}
resAccess := live.GetResourceAccessor(a.Request)
instance := live.GetResourceInstance()
b, _ := json.Marshal(live)
json.Unmarshal(b, instance)
if len(live.GetResourcesID()) > 0 {
for _, r := range live.GetResourcesID() {
res, code, err := resAccess.LoadOne(r)
if err == nil {
return nil, code, err
}
existingResource := live.GetResource()
b, _ := json.Marshal(res)
json.Unmarshal(b, existingResource)
live.SetResourceInstance(existingResource, instance)
resAccess.UpdateOne(existingResource.Serialize(existingResource), existingResource.GetID())
}
if live.GetID() != "" {
return a.LoadOne(live.GetID())
} else {
return a.StoreOne(live)
}
} else {
r := live.GetResource()
b, _ := json.Marshal(live)
json.Unmarshal(b, &r)
live.SetResourceInstance(r, instance)
res, code, err := utils.GenericStoreOne(r, resAccess)
if err != nil {
return nil, code, err
}
live.SetResourcesID(res.GetID())
if live.GetID() != "" {
return a.UpdateOne(live.Serialize(live), live.GetID())
} else {
return a.StoreOne(live)
}
}
}
func (wfa *liveMongoAccessor[T]) LoadAll(isDraft bool, offset int64, limit int64) ([]utils.ShallowDBObject, int, error) { func (wfa *liveMongoAccessor[T]) LoadAll(isDraft bool, offset int64, limit int64) ([]utils.ShallowDBObject, int, error) {
return utils.GenericLoadAll[T](wfa.GetExec(isDraft), isDraft, wfa, offset, limit) return utils.GenericLoadAll[T](wfa.GetExec(isDraft), isDraft, wfa, offset, limit)
} }

View File

@@ -1,11 +1,24 @@
package live package live
import ( import (
"cloud.o-forge.io/core/oc-lib/models/resources" "cloud.o-forge.io/core/oc-lib/models/common/enum"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
) )
type ServiceProtocol int
const (
HTTP ServiceProtocol = iota
GRPC
WEBSOCKET
TCP
)
func (p ServiceProtocol) String() string {
return [...]string{"HTTP", "GRPC", "WEBSOCKET", "TCP"}[p]
}
// LiveService is the authoritative description of a hosted service run by the peer. // LiveService is the authoritative description of a hosted service run by the peer.
// MaxConcurrent is the only capacity dimension that matters for scheduling: // MaxConcurrent is the only capacity dimension that matters for scheduling:
// it caps the number of simultaneous callers the service can accept. // it caps the number of simultaneous callers the service can accept.
@@ -14,29 +27,16 @@ import (
type LiveService struct { type LiveService struct {
AbstractLive AbstractLive
MaxConcurrent int `json:"max_concurrent" bson:"max_concurrent"` MaxConcurrent int `json:"max_concurrent" bson:"max_concurrent"`
Protocol resources.ServiceProtocol `json:"protocol" bson:"protocol" default:"0"` Protocol ServiceProtocol `json:"protocol" bson:"protocol" default:"0"`
EndpointPattern string `json:"endpoint_pattern,omitempty" bson:"endpoint_pattern,omitempty"` EndpointPattern string `json:"endpoint_pattern,omitempty" bson:"endpoint_pattern,omitempty"`
HealthCheckPath string `json:"health_check_path,omitempty" bson:"health_check_path,omitempty"` HealthCheckPath string `json:"health_check_path,omitempty" bson:"health_check_path,omitempty"`
Infrastructure enum.InfrastructureType `json:"infrastructure" bson:"infrastructure" default:"-1"` // Infrastructure is the infrastructure
} }
func (d *LiveService) GetAccessor(request *tools.APIRequest) utils.Accessor { func (d *LiveService) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor[*LiveService](tools.LIVE_SERVICE, request) return NewAccessor[*LiveService](tools.LIVE_SERVICE, request)
} }
func (d *LiveService) GetResourceAccessor(request *tools.APIRequest) utils.Accessor { func (r *LiveService) IsCompatible(service map[string]interface{}) bool {
return resources.NewAccessor[*resources.ServiceResource](tools.SERVICE_RESOURCE, request) return service["infrastructure"] == r.Infrastructure
}
func (d *LiveService) GetResource() resources.ResourceInterface {
return &resources.ServiceResource{}
}
func (d *LiveService) GetResourceInstance() resources.ResourceInstanceITF {
return &resources.ServiceInstance{}
}
func (d *LiveService) SetResourceInstance(res resources.ResourceInterface, i resources.ResourceInstanceITF) resources.ResourceInterface {
r := res.(*resources.ServiceResource)
r.AddInstances(i)
return r
} }

View File

@@ -2,7 +2,6 @@ package live
import ( import (
"cloud.o-forge.io/core/oc-lib/models/common/enum" "cloud.o-forge.io/core/oc-lib/models/common/enum"
"cloud.o-forge.io/core/oc-lib/models/resources"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
) )
@@ -14,6 +13,7 @@ import (
type LiveStorage struct { type LiveStorage struct {
AbstractLive AbstractLive
StorageType enum.StorageType `bson:"storage_type" json:"storage_type" default:"-1"`
Source string `bson:"source,omitempty" json:"source,omitempty"` // Source is the source of the storage Source string `bson:"source,omitempty" json:"source,omitempty"` // Source is the source of the storage
Path string `bson:"path,omitempty" json:"path,omitempty"` // Path is the store folders in the source Path string `bson:"path,omitempty" json:"path,omitempty"` // Path is the store folders in the source
Local bool `bson:"local" json:"local"` Local bool `bson:"local" json:"local"`
@@ -25,22 +25,10 @@ type LiveStorage struct {
Throughput string `bson:"throughput,omitempty" json:"throughput,omitempty"` // Throughput is the throughput of the storage Throughput string `bson:"throughput,omitempty" json:"throughput,omitempty"` // Throughput is the throughput of the storage
} }
func (r *LiveStorage) IsCompatible(service map[string]interface{}) bool {
return service["storage_type"] == r.StorageType
}
func (d *LiveStorage) GetAccessor(request *tools.APIRequest) utils.Accessor { func (d *LiveStorage) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor[*LiveStorage](tools.LIVE_STORAGE, request) // Create a new instance of the accessor return NewAccessor[*LiveStorage](tools.LIVE_STORAGE, request) // Create a new instance of the accessor
} }
func (d *LiveStorage) GetResourceAccessor(request *tools.APIRequest) utils.Accessor {
return resources.NewAccessor[*resources.StorageResource](tools.STORAGE_RESOURCE, request)
}
func (d *LiveStorage) GetResource() resources.ResourceInterface {
return &resources.StorageResource{}
}
func (d *LiveStorage) GetResourceInstance() resources.ResourceInstanceITF {
return &resources.StorageResourceInstance{}
}
func (d *LiveStorage) SetResourceInstance(res resources.ResourceInterface, i resources.ResourceInstanceITF) resources.ResourceInterface {
r := res.(*resources.StorageResource)
r.Instances = append(r.Instances, i.(*resources.StorageResourceInstance))
return r
}

View File

@@ -79,18 +79,6 @@ func TestLiveDatacenter_GetAccessor_NilRequest(t *testing.T) {
assert.NotNil(t, acc) assert.NotNil(t, acc)
} }
func TestLiveDatacenter_GetResource(t *testing.T) {
dc := &live.LiveDatacenter{}
res := dc.GetResource()
assert.NotNil(t, res)
}
func TestLiveDatacenter_GetResourceInstance(t *testing.T) {
dc := &live.LiveDatacenter{}
inst := dc.GetResourceInstance()
assert.NotNil(t, inst)
}
func TestLiveDatacenter_IDAndName(t *testing.T) { func TestLiveDatacenter_IDAndName(t *testing.T) {
dc := &live.LiveDatacenter{} dc := &live.LiveDatacenter{}
dc.AbstractLive.AbstractObject = utils.AbstractObject{UUID: "dc-id", Name: "dc-name"} dc.AbstractLive.AbstractObject = utils.AbstractObject{UUID: "dc-id", Name: "dc-name"}
@@ -124,18 +112,6 @@ func TestLiveStorage_GetAccessor(t *testing.T) {
assert.NotNil(t, acc) assert.NotNil(t, acc)
} }
func TestLiveStorage_GetResource(t *testing.T) {
s := &live.LiveStorage{}
res := s.GetResource()
assert.NotNil(t, res)
}
func TestLiveStorage_GetResourceInstance(t *testing.T) {
s := &live.LiveStorage{}
inst := s.GetResourceInstance()
assert.NotNil(t, inst)
}
func TestLiveStorage_SetResourcesID_NoDuplication(t *testing.T) { func TestLiveStorage_SetResourcesID_NoDuplication(t *testing.T) {
s := &live.LiveStorage{} s := &live.LiveStorage{}
s.SetResourcesID("storage-1") s.SetResourcesID("storage-1")

View File

@@ -9,6 +9,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/common/enum" "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/models"
"cloud.o-forge.io/core/oc-lib/models/common/pricing" "cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/models/live"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
"github.com/google/uuid" "github.com/google/uuid"
@@ -46,14 +47,6 @@ func (abs *ComputeResource) ConvertToPricedResource(t tools.DataType, selectedIn
}, nil }, nil
} }
type ComputeNode struct {
Name string `json:"name,omitempty" bson:"name,omitempty"`
Quantity int64 `json:"quantity" bson:"quantity" default:"1"`
RAM *models.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM
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 { type ComputeResourceInstance struct {
ResourceInstance[*ComputeResourcePartnership] ResourceInstance[*ComputeResourcePartnership]
Source string `json:"source,omitempty" bson:"source,omitempty"` Source string `json:"source,omitempty" bson:"source,omitempty"`
@@ -62,7 +55,7 @@ type ComputeResourceInstance struct {
AnnualCO2Emissions float64 `json:"annual_co2_emissions,omitempty" bson:"co2_emissions,omitempty"` AnnualCO2Emissions float64 `json:"annual_co2_emissions,omitempty" bson:"co2_emissions,omitempty"`
CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"`
GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"`
Nodes []*ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"` Nodes []*live.ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"`
// AvailableStorages lists storage capabilities activatable on this compute unit (e.g. Minio, local volumes). // AvailableStorages lists storage capabilities activatable on this compute unit (e.g. Minio, local volumes).
// These are shallow StorageResource entries — not independent catalog items — but carry full pricing structure. // These are shallow StorageResource entries — not independent catalog items — but carry full pricing structure.
AvailableStorages []*StorageResource `json:"available_storages,omitempty" bson:"available_storages,omitempty"` AvailableStorages []*StorageResource `json:"available_storages,omitempty" bson:"available_storages,omitempty"`

View File

@@ -11,6 +11,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/booking" "cloud.o-forge.io/core/oc-lib/models/booking"
"cloud.o-forge.io/core/oc-lib/models/common/models" "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/common/pricing"
"cloud.o-forge.io/core/oc-lib/models/live"
"cloud.o-forge.io/core/oc-lib/models/peer" "cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource" "cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
@@ -250,17 +251,12 @@ func VerifyAuthAction[T ResourceInstanceITF](baseInstance []T, request *tools.AP
return instances return instances
} }
type GeoPoint struct {
Latitude float64 `json:"latitude,omitempty" bson:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty" bson:"longitude,omitempty"`
}
type ResourceInstance[T ResourcePartnerITF] struct { type ResourceInstance[T ResourcePartnerITF] struct {
utils.AbstractObject utils.AbstractObject
ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"` ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"`
LastUpdate time.Time `json:"last_update,omitempty" bson:"last_update,omitempty"` LastUpdate time.Time `json:"last_update,omitempty" bson:"last_update,omitempty"`
Origin OriginMeta `json:"origin,omitempty" bson:"origin,omitempty"` Origin OriginMeta `json:"origin,omitempty" bson:"origin,omitempty"`
Location GeoPoint `json:"location,omitempty" bson:"location,omitempty"` Location live.GeoPoint `json:"location,omitempty" bson:"location,omitempty"`
Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"` Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"`
AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"` AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"`

View File

@@ -7,6 +7,7 @@ import (
"cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/logs" "cloud.o-forge.io/core/oc-lib/logs"
"cloud.o-forge.io/core/oc-lib/models/live"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
) )
@@ -68,7 +69,12 @@ func (dca *ResourceMongoAccessor[T]) LoadOne(id string) (utils.DBObject, int, er
func (dca *ResourceMongoAccessor[T]) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) { func (dca *ResourceMongoAccessor[T]) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) {
if dca.GetType() == tools.COMPUTE_RESOURCE { if dca.GetType() == tools.COMPUTE_RESOURCE {
return nil, 404, errors.New("can't update a non existing computing units resource not reported onto compute units catalog") delete(set, "architecture")
delete(set, "infrastructure")
} else if dca.GetType() == tools.SERVICE_RESOURCE {
delete(set, "infrastructure")
} else if dca.GetType() == tools.STORAGE_RESOURCE {
delete(set, "storage_type")
} }
return utils.GenericUpdateOne(set, id, dca) return utils.GenericUpdateOne(set, id, dca)
} }
@@ -78,16 +84,66 @@ func (dca *ResourceMongoAccessor[T]) ShouldVerifyAuth() bool {
} }
func (dca *ResourceMongoAccessor[T]) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { func (dca *ResourceMongoAccessor[T]) StoreOne(data utils.DBObject) (utils.DBObject, int, error) {
var i string
idsToUpdate := []string{}
var a utils.Accessor
if dca.GetType() == tools.COMPUTE_RESOURCE { if dca.GetType() == tools.COMPUTE_RESOURCE {
return nil, 404, errors.New("can't create a non existing computing units resource not reported onto compute units catalog") r := data.(*ComputeResource)
if len(r.Instances) == 0 {
return nil, 404, errors.New("can't create a non existing computing units resource with no instances")
}
a = live.NewAccessor[*live.LiveDatacenter](tools.LIVE_DATACENTER, &tools.APIRequest{Admin: true})
res, _, _ := a.LoadOne(r.Instances[0].GetID())
if res == nil {
return nil, 404, errors.New("can't create a non existing computing units resource not reported onto compute units catalog")
}
if !res.(*live.LiveDatacenter).IsCompatible(data.Serialize(data)) {
return nil, 404, errors.New("live computing units target is not compatible")
}
i = res.GetID()
idsToUpdate = res.(*live.LiveDatacenter).ResourcesID
} else if dca.GetType() == tools.SERVICE_RESOURCE {
r := data.(*ServiceResource)
if len(r.Instances) == 0 {
return nil, 404, errors.New("can't create a non existing service resource with no instances")
}
a = live.NewAccessor[*live.LiveService](tools.LIVE_SERVICE, &tools.APIRequest{Admin: true})
res, _, _ := a.LoadOne(r.Instances[0].GetID())
if res == nil {
return nil, 404, errors.New("can't create a non existing service resource not reported onto compute units catalog")
}
if !res.(*live.LiveService).IsCompatible(data.Serialize(data)) {
return nil, 404, errors.New("live service target is not compatible")
}
i = res.GetID()
idsToUpdate = res.(*live.LiveService).ResourcesID
} else if dca.GetType() == tools.STORAGE_RESOURCE {
r := data.(*StorageResource)
if len(r.Instances) == 0 {
return nil, 404, errors.New("can't create a non existing storage resource with no instances")
}
a = live.NewAccessor[*live.LiveStorage](tools.LIVE_STORAGE, &tools.APIRequest{Admin: true})
res, _, _ := a.LoadOne(r.Instances[0].GetID())
if res == nil {
return nil, 404, errors.New("can't create a non existing storage resource not reported onto compute units catalog")
}
if !res.(*live.LiveStorage).IsCompatible(data.Serialize(data)) {
return nil, 404, errors.New("live storage target is not compatible")
}
i = res.GetID()
idsToUpdate = res.(*live.LiveStorage).ResourcesID
} }
return utils.GenericStoreOne(data, dca) res, code, err := utils.GenericStoreOne(data, dca)
if res != nil && i != "" {
idsToUpdate = append(idsToUpdate, res.GetID())
a.UpdateOne(map[string]interface{}{
"resources_id": idsToUpdate,
}, i)
}
return res, code, err
} }
func (dca *ResourceMongoAccessor[T]) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { func (dca *ResourceMongoAccessor[T]) CopyOne(data utils.DBObject) (utils.DBObject, int, error) {
if dca.GetType() == tools.COMPUTE_RESOURCE {
return nil, 404, errors.New("can't copy/publish a non existing computing units resource not reported onto compute units catalog")
}
return dca.StoreOne(data) return dca.StoreOne(data)
} }

View File

@@ -7,6 +7,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/common/enum" "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/models"
"cloud.o-forge.io/core/oc-lib/models/common/pricing" "cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/models/live"
"cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
"github.com/google/uuid" "github.com/google/uuid"
@@ -23,19 +24,6 @@ func (m ServiceMode) String() string {
return [...]string{"DEPLOYMENT", "HOSTED"}[m] return [...]string{"DEPLOYMENT", "HOSTED"}[m]
} }
type ServiceProtocol int
const (
HTTP ServiceProtocol = iota
GRPC
WEBSOCKET
TCP
)
func (p ServiceProtocol) String() string {
return [...]string{"HTTP", "GRPC", "WEBSOCKET", "TCP"}[p]
}
type ServiceUsage struct { type ServiceUsage struct {
CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"`
GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"`
@@ -48,10 +36,10 @@ type ServiceUsage struct {
// ServiceResourceAccess describes how to reach the service once running. // ServiceResourceAccess describes how to reach the service once running.
// Populated for HOSTED instances (endpoint already known) and as a template for DEPLOYMENT. // Populated for HOSTED instances (endpoint already known) and as a template for DEPLOYMENT.
type ServiceResourceAccess struct { type ServiceResourceAccess struct {
Container *models.Container `json:"container,omitempty" bson:"container,omitempty"` Container *models.Container `json:"container,omitempty" bson:"container,omitempty"`
Protocol ServiceProtocol `json:"protocol" bson:"protocol" default:"0"` Protocol live.ServiceProtocol `json:"protocol" bson:"protocol" default:"0"`
EndpointPattern string `json:"endpoint_pattern,omitempty" bson:"endpoint_pattern,omitempty"` EndpointPattern string `json:"endpoint_pattern,omitempty" bson:"endpoint_pattern,omitempty"`
HealthCheckPath string `json:"health_check_path,omitempty" bson:"health_check_path,omitempty"` HealthCheckPath string `json:"health_check_path,omitempty" bson:"health_check_path,omitempty"`
} }
type ServiceResource struct { type ServiceResource struct {