Live Structure
This commit is contained in:
parent
2c8dcbe93d
commit
cd177bd779
@ -18,7 +18,7 @@ import (
|
||||
"cloud.o-forge.io/core/oc-lib/models/booking"
|
||||
"cloud.o-forge.io/core/oc-lib/models/collaborative_area"
|
||||
"cloud.o-forge.io/core/oc-lib/models/collaborative_area/rules/rule"
|
||||
"cloud.o-forge.io/core/oc-lib/models/compute_units"
|
||||
"cloud.o-forge.io/core/oc-lib/models/live"
|
||||
"cloud.o-forge.io/core/oc-lib/models/order"
|
||||
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||
"cloud.o-forge.io/core/oc-lib/models/resources"
|
||||
@ -54,7 +54,7 @@ const (
|
||||
RULE = tools.RULE
|
||||
BOOKING = tools.BOOKING
|
||||
ORDER = tools.ORDER
|
||||
COMPUTE_UNITS = tools.COMPUTE_UNITS
|
||||
LIVE_DATACENTER = tools.LIVE_DATACENTER
|
||||
PURCHASE_RESOURCE = tools.PURCHASE_RESOURCE
|
||||
)
|
||||
|
||||
@ -569,9 +569,16 @@ func (l *LibData) ToOrder() *order.Order {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LibData) ToComputeUnits() *compute_units.ComputeUnits {
|
||||
if l.Data.GetAccessor(nil).GetType() == tools.COMPUTE_UNITS {
|
||||
return l.Data.(*compute_units.ComputeUnits)
|
||||
func (l *LibData) ToLiveDatacenter() *live.LiveDatacenter {
|
||||
if l.Data.GetAccessor(nil).GetType() == tools.LIVE_DATACENTER {
|
||||
return l.Data.(*live.LiveDatacenter)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LibData) ToLiveStorage() *live.LiveStorage {
|
||||
if l.Data.GetAccessor(nil).GetType() == tools.LIVE_STORAGE {
|
||||
return l.Data.(*live.LiveStorage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -15,9 +15,9 @@ type billMongoAccessor struct {
|
||||
func NewAccessor(request *tools.APIRequest) *billMongoAccessor {
|
||||
return &billMongoAccessor{
|
||||
AbstractAccessor: utils.AbstractAccessor{
|
||||
Logger: logs.CreateLogger(tools.COMPUTE_UNITS.String()), // Create a logger with the data type
|
||||
Logger: logs.CreateLogger(tools.LIVE_DATACENTER.String()), // Create a logger with the data type
|
||||
Request: request,
|
||||
Type: tools.COMPUTE_UNITS,
|
||||
Type: tools.LIVE_DATACENTER,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
package compute_units
|
||||
|
||||
import (
|
||||
"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/resources"
|
||||
"cloud.o-forge.io/core/oc-lib/models/utils"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
"github.com/biter777/countries"
|
||||
)
|
||||
|
||||
/*
|
||||
* ComputeUnits is a struct that represents a compute units in your datacenters
|
||||
*/
|
||||
|
||||
type ComputeUnitsCerts struct {
|
||||
Host string `json:"host,omitempty" bson:"host,omitempty"`
|
||||
Port string `json:"port,omitempty" bson:"port,omitempty"`
|
||||
|
||||
// for now only Kubernetes
|
||||
CAData string `json:"ca_data,omitempty" bson:"ca_data,omitempty"`
|
||||
CertData string `json:"cert_data,omitempty" bson:"cert_data,omitempty"`
|
||||
KeyData string `json:"key_data,omitempty" bson:"key_data,omitempty"`
|
||||
}
|
||||
|
||||
// TODO in the future multiple type of certs depending of infra type
|
||||
|
||||
type ComputeUnits struct {
|
||||
utils.AbstractObject
|
||||
Certs ComputeUnitsCerts `json:"certs,omitempty" bson:"certs,omitempty"`
|
||||
|
||||
MonitorPath string `json:"monitor_path,omitempty" bson:"monitor_path,omitempty"`
|
||||
Location resources.GeoPoint `json:"location,omitempty" bson:"location,omitempty"`
|
||||
Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"`
|
||||
AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"`
|
||||
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
|
||||
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"`
|
||||
PowerSources []string `json:"power_sources,omitempty" bson:"power_sources,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
|
||||
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"`
|
||||
ResourceID string `json:"resource_id" bson:"resource_id"`
|
||||
}
|
||||
|
||||
func (r *ComputeUnits) StoreDraftDefault() {
|
||||
r.IsDraft = true
|
||||
}
|
||||
|
||||
func (r *ComputeUnits) CanDelete() bool {
|
||||
return r.IsDraft // only draft ComputeUnits can be deleted
|
||||
}
|
||||
|
||||
func (d *ComputeUnits) GetAccessor(request *tools.APIRequest) utils.Accessor {
|
||||
return NewAccessor(request) // Create a new instance of the accessor
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
package compute_units
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||
"cloud.o-forge.io/core/oc-lib/logs"
|
||||
"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/tools"
|
||||
)
|
||||
|
||||
type computeUnitsMongoAccessor struct {
|
||||
utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller)
|
||||
}
|
||||
|
||||
// New creates a new instance of the computeUnitsMongoAccessor
|
||||
func NewAccessor(request *tools.APIRequest) *computeUnitsMongoAccessor {
|
||||
return &computeUnitsMongoAccessor{
|
||||
AbstractAccessor: utils.AbstractAccessor{
|
||||
Logger: logs.CreateLogger(tools.COMPUTE_UNITS.String()), // Create a logger with the data type
|
||||
Request: request,
|
||||
Type: tools.COMPUTE_UNITS,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing special here, just the basic CRUD operations
|
||||
*/
|
||||
func (a *computeUnitsMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) {
|
||||
return utils.GenericDeleteOne(id, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) {
|
||||
// should verify if a source is existing...
|
||||
return utils.GenericUpdateOne(set, id, a, &ComputeUnits{})
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) {
|
||||
return utils.GenericStoreOne(data.(*ComputeUnits), a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) 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")
|
||||
}
|
||||
computeUnits := data.(*ComputeUnits)
|
||||
if computeUnits.MonitorPath == "" || computeUnits.GetID() != "" {
|
||||
return nil, 422, errors.New("publishing is only allowed is it can be monitored and be accessible")
|
||||
}
|
||||
if res, code, err := a.LoadOne(computeUnits.GetID()); err != nil {
|
||||
return nil, code, err
|
||||
} else {
|
||||
computeUnits = res.(*ComputeUnits)
|
||||
}
|
||||
resAccess := resources.NewAccessor[*resources.ComputeResource](tools.COMPUTE_RESOURCE, a.Request, func() utils.DBObject { return &resources.ComputeResource{} })
|
||||
var instance *resources.ComputeResourceInstance
|
||||
b, _ := json.Marshal(computeUnits)
|
||||
json.Unmarshal(b, instance)
|
||||
|
||||
if computeUnits.ResourceID != "" {
|
||||
// TODO dependent of a existing resource
|
||||
res, code, err := resAccess.LoadOne(computeUnits.ResourceID)
|
||||
if err == nil {
|
||||
return nil, code, err
|
||||
}
|
||||
existingComputeResource := res.(*resources.ComputeResource)
|
||||
if existingComputeResource.Architecture != computeUnits.Architecture || existingComputeResource.Infrastructure != computeUnits.Infrastructure {
|
||||
return nil, 422, errors.New("should be same architecture & infrastructure from the resource")
|
||||
}
|
||||
existingComputeResource.Instances = append(existingComputeResource.Instances, instance)
|
||||
return resAccess.UpdateOne(existingComputeResource, existingComputeResource.UUID)
|
||||
} else {
|
||||
var r resources.ComputeResource
|
||||
b, _ := json.Marshal(computeUnits)
|
||||
json.Unmarshal(b, &r)
|
||||
r.Instances = append(r.Instances, instance)
|
||||
res, code, err := resAccess.StoreOne(&r)
|
||||
if err != nil {
|
||||
return nil, code, err
|
||||
}
|
||||
computeUnits.ResourceID = res.GetID()
|
||||
return a.UpdateOne(computeUnits, computeUnits.GetID())
|
||||
}
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) {
|
||||
return utils.GenericLoadOne[*ComputeUnits](id, func(d utils.DBObject) (utils.DBObject, int, error) {
|
||||
return d, 200, nil
|
||||
}, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) LoadAll(isDraft bool) ([]utils.ShallowDBObject, int, error) {
|
||||
return utils.GenericLoadAll[*ComputeUnits](a.getExec(), isDraft, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) Search(filters *dbs.Filters, search string, isDraft bool) ([]utils.ShallowDBObject, int, error) {
|
||||
return utils.GenericSearch[*ComputeUnits](filters, search, (&ComputeUnits{}).GetObjectFilters(search), a.getExec(), isDraft, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor) getExec() func(utils.DBObject) utils.ShallowDBObject {
|
||||
return func(d utils.DBObject) utils.ShallowDBObject {
|
||||
return d
|
||||
}
|
||||
}
|
14
models/live/interfaces.go
Executable file
14
models/live/interfaces.go
Executable file
@ -0,0 +1,14 @@
|
||||
package live
|
||||
|
||||
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/tools"
|
||||
)
|
||||
|
||||
type LiveInterface interface {
|
||||
GetResourceAccessor(request *tools.APIRequest) utils.Accessor
|
||||
GetResource() resources.ResourceInterface
|
||||
GetResourceInstance() resources.ResourceInstanceITF
|
||||
SetResourceInstance(res resources.ResourceInterface, i resources.ResourceInstanceITF) resources.ResourceInterface
|
||||
}
|
55
models/live/live.go
Normal file
55
models/live/live.go
Normal file
@ -0,0 +1,55 @@
|
||||
package live
|
||||
|
||||
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/tools"
|
||||
"github.com/biter777/countries"
|
||||
)
|
||||
|
||||
/*
|
||||
* LiveDatacenter is a struct that represents a compute units in your datacenters
|
||||
*/
|
||||
type Credentials struct {
|
||||
Login string `json:"login,omitempty" bson:"login,omitempty"`
|
||||
Pass string `json:"password,omitempty" bson:"password,omitempty"`
|
||||
Token string `json:"token,omitempty" bson:"token,omitempty"`
|
||||
}
|
||||
|
||||
type Certs struct {
|
||||
AuthorityCertificate string `json:"authority_certificate,omitempty" bson:"authority_certificate,omitempty"`
|
||||
ClientCertificate string `json:"client_certificate,omitempty" bson:"client_certificate,omitempty"`
|
||||
}
|
||||
|
||||
type LiveCerts struct {
|
||||
Host string `json:"host,omitempty" bson:"host,omitempty"`
|
||||
Port string `json:"port,omitempty" bson:"port,omitempty"`
|
||||
|
||||
Certificates *Certs `json:"certs,omitempty" bson:"certs,omitempty"`
|
||||
Credentials *Credentials `json:"creds,omitempty" bson:"creds,omitempty"`
|
||||
}
|
||||
|
||||
// TODO in the future multiple type of certs depending of infra type
|
||||
|
||||
type AbstractLive struct {
|
||||
utils.AbstractObject
|
||||
Certs LiveCerts `json:"certs,omitempty" bson:"certs,omitempty"`
|
||||
|
||||
MonitorPath string `json:"monitor_path,omitempty" bson:"monitor_path,omitempty"`
|
||||
Location resources.GeoPoint `json:"location,omitempty" bson:"location,omitempty"`
|
||||
Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"`
|
||||
AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"`
|
||||
ResourcesID []string `json:"resources_id" bson:"resources_id"`
|
||||
}
|
||||
|
||||
func (r *AbstractLive) GetResourceType() tools.DataType {
|
||||
return tools.INVALID
|
||||
}
|
||||
|
||||
func (r *AbstractLive) StoreDraftDefault() {
|
||||
r.IsDraft = true
|
||||
}
|
||||
|
||||
func (r *AbstractLive) CanDelete() bool {
|
||||
return r.IsDraft // only draft ComputeUnits can be deleted
|
||||
}
|
50
models/live/live_datacenter.go
Normal file
50
models/live/live_datacenter.go
Normal file
@ -0,0 +1,50 @@
|
||||
package live
|
||||
|
||||
import (
|
||||
"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/resources"
|
||||
"cloud.o-forge.io/core/oc-lib/models/utils"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
)
|
||||
|
||||
/*
|
||||
* LiveDatacenter is a struct that represents a compute units in your datacenters
|
||||
*/
|
||||
|
||||
type LiveDatacenter struct {
|
||||
AbstractLive
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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"`
|
||||
PowerSources []string `json:"power_sources,omitempty" bson:"power_sources,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
|
||||
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"`
|
||||
}
|
||||
|
||||
func (d *LiveDatacenter) GetAccessor(request *tools.APIRequest) utils.Accessor {
|
||||
return NewAccessor[*LiveDatacenter](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() utils.DBObject { return &resources.ComputeResource{} })
|
||||
}
|
||||
|
||||
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
|
||||
}
|
122
models/live/live_mongo_accessor.go
Normal file
122
models/live/live_mongo_accessor.go
Normal file
@ -0,0 +1,122 @@
|
||||
package live
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"slices"
|
||||
|
||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||
"cloud.o-forge.io/core/oc-lib/logs"
|
||||
"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/tools"
|
||||
)
|
||||
|
||||
type computeUnitsMongoAccessor[T LiveInterface] struct {
|
||||
utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller)
|
||||
}
|
||||
|
||||
// New creates a new instance of the computeUnitsMongoAccessor
|
||||
func NewAccessor[T LiveInterface](request *tools.APIRequest) *computeUnitsMongoAccessor[T] {
|
||||
return &computeUnitsMongoAccessor[T]{
|
||||
AbstractAccessor: utils.AbstractAccessor{
|
||||
Logger: logs.CreateLogger(tools.LIVE_DATACENTER.String()), // Create a logger with the data type
|
||||
Request: request,
|
||||
Type: tools.LIVE_DATACENTER,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing special here, just the basic CRUD operations
|
||||
*/
|
||||
func (a *computeUnitsMongoAccessor[T]) DeleteOne(id string) (utils.DBObject, int, error) {
|
||||
return utils.GenericDeleteOne(id, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[T]) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) {
|
||||
// should verify if a source is existing...
|
||||
return utils.GenericUpdateOne(set, id, a, &LiveDatacenter{})
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[T]) StoreOne(data utils.DBObject) (utils.DBObject, int, error) {
|
||||
return utils.GenericStoreOne(data.(*LiveDatacenter), a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[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")
|
||||
}
|
||||
datacenterUnits := data.(*LiveDatacenter)
|
||||
if datacenterUnits.MonitorPath == "" || datacenterUnits.GetID() != "" {
|
||||
return nil, 422, errors.New("publishing is only allowed is it can be monitored and be accessible")
|
||||
}
|
||||
if res, code, err := a.LoadOne(datacenterUnits.GetID()); err != nil {
|
||||
return nil, code, err
|
||||
} else {
|
||||
datacenterUnits = res.(*LiveDatacenter)
|
||||
}
|
||||
resAccess := datacenterUnits.GetResourceAccessor(a.Request)
|
||||
instance := datacenterUnits.GetResourceInstance()
|
||||
b, _ := json.Marshal(datacenterUnits)
|
||||
json.Unmarshal(b, instance)
|
||||
|
||||
if len(datacenterUnits.ResourcesID) > 0 {
|
||||
for _, r := range datacenterUnits.ResourcesID {
|
||||
// TODO dependent of a existing resource
|
||||
res, code, err := resAccess.LoadOne(r)
|
||||
if err == nil {
|
||||
return nil, code, err
|
||||
}
|
||||
existingComputeResource := res.(*resources.ComputeResource)
|
||||
if existingComputeResource.Architecture != datacenterUnits.Architecture || existingComputeResource.Infrastructure != datacenterUnits.Infrastructure {
|
||||
return nil, 422, errors.New("should be same architecture & infrastructure from the resource")
|
||||
}
|
||||
datacenterUnits.SetResourceInstance(existingComputeResource, instance)
|
||||
resAccess.UpdateOne(existingComputeResource, existingComputeResource.UUID)
|
||||
}
|
||||
if datacenterUnits.GetID() != "" {
|
||||
return a.LoadOne(datacenterUnits.GetID())
|
||||
} else {
|
||||
return a.StoreOne(datacenterUnits)
|
||||
}
|
||||
} else {
|
||||
r := datacenterUnits.GetResource()
|
||||
b, _ := json.Marshal(datacenterUnits)
|
||||
json.Unmarshal(b, &r)
|
||||
datacenterUnits.SetResourceInstance(r, instance)
|
||||
res, code, err := resAccess.StoreOne(r)
|
||||
if err != nil {
|
||||
return nil, code, err
|
||||
}
|
||||
if !slices.Contains(datacenterUnits.ResourcesID, res.GetID()) {
|
||||
datacenterUnits.ResourcesID = append(datacenterUnits.ResourcesID, res.GetID())
|
||||
}
|
||||
if datacenterUnits.GetID() != "" {
|
||||
return a.UpdateOne(datacenterUnits, datacenterUnits.GetID())
|
||||
} else {
|
||||
return a.StoreOne(datacenterUnits)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[T]) LoadOne(id string) (utils.DBObject, int, error) {
|
||||
return utils.GenericLoadOne[*LiveDatacenter](id, func(d utils.DBObject) (utils.DBObject, int, error) {
|
||||
return d, 200, nil
|
||||
}, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[T]) LoadAll(isDraft bool) ([]utils.ShallowDBObject, int, error) {
|
||||
return utils.GenericLoadAll[*LiveDatacenter](a.getExec(), isDraft, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[T]) Search(filters *dbs.Filters, search string, isDraft bool) ([]utils.ShallowDBObject, int, error) {
|
||||
return utils.GenericSearch[*LiveDatacenter](filters, search, (&LiveDatacenter{}).GetObjectFilters(search), a.getExec(), isDraft, a)
|
||||
}
|
||||
|
||||
func (a *computeUnitsMongoAccessor[T]) getExec() func(utils.DBObject) utils.ShallowDBObject {
|
||||
return func(d utils.DBObject) utils.ShallowDBObject {
|
||||
return d
|
||||
}
|
||||
}
|
46
models/live/live_storage.go
Normal file
46
models/live/live_storage.go
Normal file
@ -0,0 +1,46 @@
|
||||
package live
|
||||
|
||||
import (
|
||||
"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/tools"
|
||||
)
|
||||
|
||||
/*
|
||||
* LiveStorage is a struct that represents a compute units in your datacenters
|
||||
*/
|
||||
|
||||
type LiveStorage struct {
|
||||
AbstractLive
|
||||
|
||||
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
|
||||
Local bool `bson:"local" json:"local"`
|
||||
SecurityLevel string `bson:"security_level,omitempty" json:"security_level,omitempty"`
|
||||
SizeType enum.StorageSize `bson:"size_type" json:"size_type" default:"0"` // SizeType is the type of the storage size
|
||||
SizeGB int64 `bson:"size,omitempty" json:"size,omitempty"` // Size is the size of the storage
|
||||
Encryption bool `bson:"encryption,omitempty" json:"encryption,omitempty"` // Encryption is a flag that indicates if the storage is encrypted
|
||||
Redundancy string `bson:"redundancy,omitempty" json:"redundancy,omitempty"` // Redundancy is the redundancy of the storage
|
||||
Throughput string `bson:"throughput,omitempty" json:"throughput,omitempty"` // Throughput is the throughput of the storage
|
||||
}
|
||||
|
||||
func (d *LiveStorage) GetAccessor(request *tools.APIRequest) utils.Accessor {
|
||||
return NewAccessor[*LiveStorage](request) // Create a new instance of the accessor
|
||||
}
|
||||
func (d *LiveStorage) GetResourceAccessor(request *tools.APIRequest) utils.Accessor {
|
||||
return resources.NewAccessor[*resources.ComputeResource](tools.STORAGE_RESOURCE, request, func() utils.DBObject { return &resources.StorageResource{} })
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@ -3,7 +3,7 @@ package models
|
||||
import (
|
||||
"cloud.o-forge.io/core/oc-lib/logs"
|
||||
"cloud.o-forge.io/core/oc-lib/models/bill"
|
||||
"cloud.o-forge.io/core/oc-lib/models/compute_units"
|
||||
"cloud.o-forge.io/core/oc-lib/models/live/live_datacenter"
|
||||
"cloud.o-forge.io/core/oc-lib/models/order"
|
||||
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
@ -40,7 +40,7 @@ var ModelsCatalog = map[string]func() utils.DBObject{
|
||||
tools.WORKSPACE_HISTORY.String(): func() utils.DBObject { return &w3.WorkspaceHistory{} },
|
||||
tools.ORDER.String(): func() utils.DBObject { return &order.Order{} },
|
||||
tools.PURCHASE_RESOURCE.String(): func() utils.DBObject { return &purchase_resource.PurchaseResource{} },
|
||||
tools.COMPUTE_UNITS.String(): func() utils.DBObject { return &compute_units.ComputeUnits{} },
|
||||
tools.LIVE_DATACENTER.String(): func() utils.DBObject { return &live_datacenter.LiveDatacenter{} },
|
||||
tools.BILL.String(): func() utils.DBObject { return &bill.Bill{} },
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ func (p *Peer) IsMySelf() (bool, string) {
|
||||
}
|
||||
|
||||
// LaunchPeerExecution launches an execution on a peer
|
||||
func (p *Peer) LaunchPeerExecution(peerID string, dataID string, dt tools.DataType, method tools.METHOD, body interface{}, caller *tools.HTTPCaller) (*PeerExecution, error) {
|
||||
func (p *Peer) LaunchPeerExecution(peerID string, dataID string, dt tools.DataType, method tools.METHOD, body interface{}, caller *tools.HTTPCaller) (map[string]interface{}, error) {
|
||||
p.UUID = peerID
|
||||
return cache.LaunchPeerExecution(peerID, dataID, dt, method, body, caller) // Launch the execution on the peer through the cache
|
||||
}
|
||||
|
@ -50,11 +50,11 @@ func (p *PeerCache) checkPeerStatus(peerID string, appName string) (*Peer, bool)
|
||||
// LaunchPeerExecution launches an execution on a peer
|
||||
// The method contacts the path described by : peer.Url + datatype path (from enums) + replacement of id by dataID
|
||||
func (p *PeerCache) LaunchPeerExecution(peerID string, dataID string,
|
||||
dt tools.DataType, method tools.METHOD, body interface{}, caller tools.HTTPCallerITF) (*PeerExecution, error) {
|
||||
dt tools.DataType, method tools.METHOD, body interface{}, caller tools.HTTPCallerITF) (map[string]interface{}, error) {
|
||||
fmt.Println("Launching peer execution on", caller.GetUrls(), dt, method)
|
||||
methods := caller.GetUrls()[dt] // Get the methods url of the data type
|
||||
if m, ok := methods[method]; !ok || m == "" {
|
||||
return nil, errors.New("Requested method " + method.String() + " not declared in HTTPCaller")
|
||||
return map[string]interface{}{}, errors.New("Requested method " + method.String() + " not declared in HTTPCaller")
|
||||
}
|
||||
path := methods[method] // Get the path corresponding to the action we want to execute
|
||||
path = strings.ReplaceAll(path, ":id", dataID) // Replace the id in the path in case of a DELETE / UPDATE method (it's a standard naming in OC)
|
||||
@ -72,10 +72,10 @@ func (p *PeerCache) LaunchPeerExecution(peerID string, dataID string,
|
||||
}
|
||||
mypeer.AddExecution(*pexec)
|
||||
NewShallowAccessor().UpdateOne(mypeer, peerID) // Update the peer in the db
|
||||
return nil, errors.New("peer is " + peerID + " not reachable")
|
||||
return map[string]interface{}{}, errors.New("peer is " + peerID + " not reachable")
|
||||
} else {
|
||||
if mypeer == nil {
|
||||
return nil, errors.New("peer " + peerID + " not found")
|
||||
return map[string]interface{}{}, errors.New("peer " + peerID + " not found")
|
||||
}
|
||||
// If the peer is reachable, launch the execution
|
||||
url = p.urlFormat((mypeer.Url), dt) + path // Format the URL
|
||||
@ -86,11 +86,11 @@ func (p *PeerCache) LaunchPeerExecution(peerID string, dataID string,
|
||||
go p.Exec(v.Url, tools.ToMethod(v.Method), v.Body, caller)
|
||||
}
|
||||
}
|
||||
return nil, p.Exec(url, method, body, caller) // Execute the method
|
||||
return p.Exec(url, method, body, caller) // Execute the method
|
||||
}
|
||||
|
||||
// exec executes the method on the peer
|
||||
func (p *PeerCache) Exec(url string, method tools.METHOD, body interface{}, caller tools.HTTPCallerITF) error {
|
||||
func (p *PeerCache) Exec(url string, method tools.METHOD, body interface{}, caller tools.HTTPCallerITF) (map[string]interface{}, error) {
|
||||
var b []byte
|
||||
var err error
|
||||
if method == tools.POST { // Execute the POST method if it's a POST method
|
||||
@ -102,16 +102,16 @@ func (p *PeerCache) Exec(url string, method tools.METHOD, body interface{}, call
|
||||
if method == tools.DELETE { // Execute the DELETE method if it's a DELETE method
|
||||
b, err = caller.CallDelete(url, "")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
err = json.Unmarshal(b, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
return m, err
|
||||
}
|
||||
if e, ok := m["error"]; ok && e != "<nil>" && e != "" { // Check if there is an error in the response
|
||||
return errors.New(fmt.Sprintf("%v", m["error"]))
|
||||
return m, errors.New(fmt.Sprintf("%v", m["error"]))
|
||||
}
|
||||
return nil
|
||||
return m, nil
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func TestExecSuccess(t *testing.T) {
|
||||
data, _ := json.Marshal(response)
|
||||
|
||||
caller.On("CallPost", url, "", mock.Anything).Return(data, nil)
|
||||
err := cache.Exec(url, tools.POST, map[string]string{"key": "value"}, caller)
|
||||
_, err := cache.Exec(url, tools.POST, map[string]string{"key": "value"}, caller)
|
||||
assert.NoError(t, err)
|
||||
caller.AssertExpectations(t)
|
||||
}
|
||||
@ -71,7 +71,7 @@ func TestExecReturnsErrorField(t *testing.T) {
|
||||
data, _ := json.Marshal(response)
|
||||
|
||||
caller.On("CallPost", url, "", mock.Anything).Return(data, nil)
|
||||
err := cache.Exec(url, tools.POST, map[string]string{"key": "value"}, caller)
|
||||
_, err := cache.Exec(url, tools.POST, map[string]string{"key": "value"}, caller)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "something failed", err.Error())
|
||||
}
|
||||
@ -81,7 +81,7 @@ func TestExecInvalidJSON(t *testing.T) {
|
||||
caller := &MockHTTPCaller{}
|
||||
url := "http://mockpeer/resource"
|
||||
caller.On("CallPost", url, "", mock.Anything).Return([]byte("{invalid json}"), nil)
|
||||
err := cache.Exec(url, tools.POST, map[string]string{"key": "value"}, caller)
|
||||
_, err := cache.Exec(url, tools.POST, map[string]string{"key": "value"}, caller)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid character")
|
||||
}
|
||||
|
@ -143,11 +143,6 @@ type GeoPoint struct {
|
||||
Longitude float64 `json:"longitude,omitempty" bson:"longitude,omitempty"`
|
||||
}
|
||||
|
||||
type Credentials struct {
|
||||
Login string `json:"login,omitempty" bson:"login,omitempty"`
|
||||
Pass string `json:"password,omitempty" bson:"password,omitempty"`
|
||||
}
|
||||
|
||||
type ResourceInstance[T ResourcePartnerITF] struct {
|
||||
utils.AbstractObject
|
||||
Location GeoPoint `json:"location,omitempty" bson:"location,omitempty"`
|
||||
|
@ -17,7 +17,11 @@ type ResourceMongoAccessor[T ResourceInterface] struct {
|
||||
|
||||
// New creates a new instance of the computeMongoAccessor
|
||||
func NewAccessor[T ResourceInterface](t tools.DataType, request *tools.APIRequest, g func() utils.DBObject) *ResourceMongoAccessor[T] {
|
||||
if !slices.Contains([]tools.DataType{tools.COMPUTE_RESOURCE, tools.STORAGE_RESOURCE, tools.PROCESSING_RESOURCE, tools.WORKFLOW_RESOURCE, tools.DATA_RESOURCE}, t) {
|
||||
if !slices.Contains([]tools.DataType{
|
||||
tools.COMPUTE_RESOURCE, tools.STORAGE_RESOURCE,
|
||||
tools.PROCESSING_RESOURCE, tools.WORKFLOW_RESOURCE,
|
||||
tools.DATA_RESOURCE,
|
||||
}, t) {
|
||||
return nil
|
||||
}
|
||||
return &ResourceMongoAccessor[T]{
|
||||
|
@ -43,7 +43,6 @@ func (abs *StorageResource) ConvertToPricedResource(t tools.DataType, request *t
|
||||
|
||||
type StorageResourceInstance struct {
|
||||
ResourceInstance[*StorageResourcePartnership]
|
||||
Credentials *Credentials `json:"credentials,omitempty" bson:"credentials,omitempty"`
|
||||
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
|
||||
Local bool `bson:"local" json:"local"`
|
||||
@ -56,7 +55,6 @@ type StorageResourceInstance struct {
|
||||
}
|
||||
|
||||
func (ri *StorageResourceInstance) ClearEnv() {
|
||||
ri.Credentials = nil
|
||||
ri.Env = []models.Param{}
|
||||
ri.Inputs = []models.Param{}
|
||||
ri.Outputs = []models.Param{}
|
||||
|
@ -39,7 +39,6 @@ func TestStorageResource_ConvertToPricedResource_InvalidType(t *testing.T) {
|
||||
|
||||
func TestStorageResourceInstance_ClearEnv(t *testing.T) {
|
||||
inst := &resources.StorageResourceInstance{
|
||||
Credentials: &resources.Credentials{Login: "test"},
|
||||
ResourceInstance: resources.ResourceInstance[*resources.StorageResourcePartnership]{
|
||||
Env: []models.Param{{Attr: "A"}},
|
||||
Inputs: []models.Param{{Attr: "B"}},
|
||||
@ -48,7 +47,6 @@ func TestStorageResourceInstance_ClearEnv(t *testing.T) {
|
||||
}
|
||||
|
||||
inst.ClearEnv()
|
||||
assert.Nil(t, inst.Credentials)
|
||||
assert.Empty(t, inst.Env)
|
||||
assert.Empty(t, inst.Inputs)
|
||||
assert.Empty(t, inst.Outputs)
|
||||
|
@ -43,6 +43,10 @@ func (ri *AbstractObject) GetAccessor(request *tools.APIRequest) Accessor {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AbstractObject) SetID(id string) {
|
||||
r.UUID = id
|
||||
}
|
||||
|
||||
func (r *AbstractObject) GenerateID() {
|
||||
if r.UUID == "" {
|
||||
r.UUID = uuid.New().String()
|
||||
|
@ -18,6 +18,7 @@ type ShallowDBObject interface {
|
||||
// DBObject is an interface that defines the basic methods for a DBObject
|
||||
type DBObject interface {
|
||||
GenerateID()
|
||||
SetID(id string)
|
||||
GetID() string
|
||||
GetName() string
|
||||
IsDrafted() bool
|
||||
|
@ -101,10 +101,6 @@ func (ws *WorkflowSchedule) GetBuyAndBook(wfID string, request *tools.APIRequest
|
||||
}
|
||||
}
|
||||
|
||||
if err := ws.GenerateOrder(purchased, bookings, request); err != nil {
|
||||
return false, wf, execs, purchased, bookings, err
|
||||
}
|
||||
|
||||
return true, wf, execs, purchased, bookings, nil
|
||||
}
|
||||
|
||||
@ -189,6 +185,12 @@ func (ws *WorkflowSchedule) Schedules(wfID string, request *tools.APIRequest) (*
|
||||
for _, purchase := range purchases {
|
||||
go ws.CallDatacenter(purchase, purchase.DestPeerID, tools.PURCHASE_RESOURCE, request, errCh, &m)
|
||||
}
|
||||
for i := 0; i < len(purchases); i++ {
|
||||
if err := <-errCh; err != nil {
|
||||
return ws, wf, executions, errors.New("could not launch the peer execution : " + fmt.Sprintf("%v", err))
|
||||
}
|
||||
}
|
||||
|
||||
errCh = make(chan error, len(bookings))
|
||||
|
||||
for _, booking := range bookings {
|
||||
@ -201,6 +203,10 @@ func (ws *WorkflowSchedule) Schedules(wfID string, request *tools.APIRequest) (*
|
||||
}
|
||||
}
|
||||
|
||||
if err := ws.GenerateOrder(purchases, bookings, request); err != nil {
|
||||
return ws, wf, executions, err
|
||||
}
|
||||
|
||||
fmt.Println("Schedules")
|
||||
for _, exec := range executions {
|
||||
err := exec.PurgeDraft(request)
|
||||
@ -222,9 +228,12 @@ func (ws *WorkflowSchedule) CallDatacenter(purchase utils.DBObject, destPeerID s
|
||||
return
|
||||
}
|
||||
m.Unlock()
|
||||
if _, err = (&peer.Peer{}).LaunchPeerExecution(destPeerID, "", dt, tools.POST, purchase.Serialize(purchase), &c); err != nil {
|
||||
if res, err := (&peer.Peer{}).LaunchPeerExecution(destPeerID, "", dt, tools.POST, purchase.Serialize(purchase), &c); err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
} else {
|
||||
data := res["data"].(map[string]interface{})
|
||||
purchase.SetID(fmt.Sprintf("%v", data["id"]))
|
||||
}
|
||||
errCh <- nil
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ const (
|
||||
ADMIRALTY_SECRET
|
||||
ADMIRALTY_KUBECONFIG
|
||||
ADMIRALTY_NODES
|
||||
COMPUTE_UNITS
|
||||
LIVE_DATACENTER
|
||||
LIVE_STORAGE
|
||||
BILL
|
||||
)
|
||||
|
||||
@ -69,6 +70,7 @@ var DefaultAPI = [...]string{
|
||||
ADMIRALTY_KUBECONFIGAPI,
|
||||
ADMIRALTY_NODESAPI,
|
||||
DATACENTERAPI,
|
||||
DATACENTERAPI,
|
||||
NOAPI,
|
||||
}
|
||||
|
||||
@ -96,7 +98,8 @@ var Str = [...]string{
|
||||
"admiralty_secret",
|
||||
"admiralty_kubeconfig",
|
||||
"admiralty_node",
|
||||
"compute_units",
|
||||
"live_datacenter",
|
||||
"live_storage",
|
||||
"bill",
|
||||
}
|
||||
|
||||
@ -120,5 +123,6 @@ func (d DataType) EnumIndex() int {
|
||||
func DataTypeList() []DataType {
|
||||
return []DataType{DATA_RESOURCE, PROCESSING_RESOURCE, STORAGE_RESOURCE, COMPUTE_RESOURCE, WORKFLOW_RESOURCE,
|
||||
WORKFLOW, WORKFLOW_EXECUTION, WORKSPACE, PEER, COLLABORATIVE_AREA, RULE, BOOKING, WORKFLOW_HISTORY, WORKSPACE_HISTORY,
|
||||
ORDER, PURCHASE_RESOURCE, ADMIRALTY_SOURCE, ADMIRALTY_TARGET, ADMIRALTY_SECRET, ADMIRALTY_KUBECONFIG, ADMIRALTY_NODES, COMPUTE_UNITS, BILL}
|
||||
ORDER, PURCHASE_RESOURCE, ADMIRALTY_SOURCE, ADMIRALTY_TARGET, ADMIRALTY_SECRET, ADMIRALTY_KUBECONFIG, ADMIRALTY_NODES,
|
||||
LIVE_DATACENTER, LIVE_STORAGE, BILL}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user