light modification

This commit is contained in:
mr 2025-01-15 10:56:44 +01:00
parent ad69c04951
commit be38030395
14 changed files with 208 additions and 218 deletions

View File

@ -0,0 +1,15 @@
package enum
type InfrastructureType int
const (
DOCKER InfrastructureType = iota
KUBERNETES
SLURM
HW
CONDOR
)
func (t InfrastructureType) String() string {
return [...]string{"DOCKER", "KUBERNETES", "SLURM", "HW", "CONDOR"}[t]
}

View File

@ -1,4 +1,4 @@
package common package enum
type ScheduledType int type ScheduledType int

View File

@ -1,4 +1,4 @@
package common package enum
type StorageSize int type StorageSize int

View File

@ -1,4 +1,4 @@
package common package models
type Container struct { type Container struct {
Image string `json:"image,omitempty" bson:"image,omitempty"` // Image is the container image TEMPO Image string `json:"image,omitempty" bson:"image,omitempty"` // Image is the container image TEMPO

View File

@ -1,4 +1,4 @@
package common package models
// CPU is a struct that represents a CPU // CPU is a struct that represents a CPU
type CPU struct { type CPU struct {
@ -18,17 +18,3 @@ type GPU struct {
MemoryGb float64 `bson:"memory,omitempty" json:"memory,omitempty" description:"Units in MB"` MemoryGb float64 `bson:"memory,omitempty" json:"memory,omitempty" description:"Units in MB"`
Cores map[string]int `bson:"cores,omitempty" json:"cores,omitempty"` Cores map[string]int `bson:"cores,omitempty" json:"cores,omitempty"`
} }
type InfrastructureType int
const (
DOCKER InfrastructureType = iota
KUBERNETES
SLURM
HW
CONDOR
)
func (t InfrastructureType) String() string {
return [...]string{"DOCKER", "KUBERNETES", "SLURM", "HW", "CONDOR"}[t]
}

42
models/common/planner.go Normal file
View File

@ -0,0 +1,42 @@
package common
import (
"time"
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/tools"
)
func GetPlannerNearestStart(start time.Time, planned map[tools.DataType][]pricing.PricedItemITF, request *tools.APIRequest) float64 {
near := float64(10000000000) // set a high value
for _, items := range planned { // loop through the planned items
for _, priced := range items { // loop through the priced items
if priced.GetLocationStart() == nil { // if the start is nil,
continue // skip the iteration
}
newS := priced.GetLocationStart() // get the start
if newS.Sub(start).Seconds() < near { // if the difference between the start and the new start is less than the nearest start
near = newS.Sub(start).Seconds()
}
}
}
return near
}
func GetPlannerLongestTime(end *time.Time, planned map[tools.DataType][]pricing.PricedItemITF, request *tools.APIRequest) float64 {
if end == nil {
return -1
}
longestTime := float64(0)
for _, priced := range planned[tools.PROCESSING_RESOURCE] {
if priced.GetLocationEnd() == nil {
continue
}
newS := priced.GetLocationEnd()
if longestTime < newS.Sub(*end).Seconds() {
longestTime = newS.Sub(*end).Seconds()
}
// get the nearest start from start var
}
return longestTime
}

View File

@ -115,10 +115,10 @@ func (o *Order) draftStoreFromModel(scheduler *workflow_execution.WorkflowSchedu
// set the name of the order // set the name of the order
resourcesByPeer := map[string][]pricing.PricedItemITF{} // create a map of resources by peer resourcesByPeer := map[string][]pricing.PricedItemITF{} // create a map of resources by peer
processings := scheduler.Workflow.GetPricedItem(scheduler.Workflow.IsProcessing, request) // get the processing items processings := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsProcessing, request) // get the processing items
datas := scheduler.Workflow.GetPricedItem(scheduler.Workflow.IsData, request) // get the data items datas := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsData, request) // get the data items
storages := scheduler.Workflow.GetPricedItem(scheduler.Workflow.IsStorage, request) // get the storage items storages := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsStorage, request) // get the storage items
workflows := scheduler.Workflow.GetPricedItem(scheduler.Workflow.IsWorkflow, request) // get the workflow items workflows := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsWorkflow, request) // get the workflow items
for _, items := range []map[string]pricing.PricedItemITF{processings, datas, storages, workflows} { for _, items := range []map[string]pricing.PricedItemITF{processings, datas, storages, workflows} {
for _, item := range items { for _, item := range items {
if _, ok := resourcesByPeer[item.GetCreatorID()]; !ok { if _, ok := resourcesByPeer[item.GetCreatorID()]; !ok {

View File

@ -5,7 +5,8 @@ import (
"strings" "strings"
"time" "time"
"cloud.o-forge.io/core/oc-lib/models/common" "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" "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/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
@ -18,7 +19,7 @@ import (
type ComputeResource struct { type ComputeResource struct {
AbstractIntanciatedResource[*ComputeResourceInstance] AbstractIntanciatedResource[*ComputeResourceInstance]
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 common.InfrastructureType `json:"infrastructure,omitempty" bson:"infrastructure,omitempty"` Infrastructure enum.InfrastructureType `json:"infrastructure,omitempty" bson:"infrastructure,omitempty"`
} }
func (d *ComputeResource) GetAccessor(request *tools.APIRequest) utils.Accessor { func (d *ComputeResource) GetAccessor(request *tools.APIRequest) utils.Accessor {
@ -27,6 +28,9 @@ func (d *ComputeResource) GetAccessor(request *tools.APIRequest) utils.Accessor
func (abs *ComputeResource) ConvertToPricedResource( func (abs *ComputeResource) ConvertToPricedResource(
t tools.DataType, request *tools.APIRequest) pricing.PricedItemITF { t tools.DataType, request *tools.APIRequest) pricing.PricedItemITF {
if t != tools.COMPUTE_RESOURCE {
return nil
}
p := abs.AbstractIntanciatedResource.ConvertToPricedResource(t, request) p := abs.AbstractIntanciatedResource.ConvertToPricedResource(t, request)
priced := p.(*PricedResource) priced := p.(*PricedResource)
return &PricedComputeResource{ return &PricedComputeResource{
@ -37,7 +41,7 @@ func (abs *ComputeResource) ConvertToPricedResource(
type ComputeNode struct { type ComputeNode struct {
Name string `json:"name,omitempty" bson:"name,omitempty"` Name string `json:"name,omitempty" bson:"name,omitempty"`
Quantity int64 `json:"quantity" bson:"quantity" default:"1"` Quantity int64 `json:"quantity" bson:"quantity" default:"1"`
RAM *common.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM 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 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 GPUs map[string]int64 `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs key is model
} }
@ -47,8 +51,8 @@ type ComputeResourceInstance struct {
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]*common.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]*common.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 []*ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"` Nodes []*ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"`
} }

View File

@ -43,6 +43,9 @@ func (d *DataResource) GetAccessor(request *tools.APIRequest) utils.Accessor {
func (abs *DataResource) ConvertToPricedResource( func (abs *DataResource) ConvertToPricedResource(
t tools.DataType, request *tools.APIRequest) pricing.PricedItemITF { t tools.DataType, request *tools.APIRequest) pricing.PricedItemITF {
if t != tools.DATA_RESOURCE {
return nil
}
p := abs.AbstractIntanciatedResource.ConvertToPricedResource(t, request) p := abs.AbstractIntanciatedResource.ConvertToPricedResource(t, request)
priced := p.(*PricedResource) priced := p.(*PricedResource)
return &PricedDataResource{ return &PricedDataResource{

View File

@ -3,16 +3,17 @@ package resources
import ( import (
"time" "time"
"cloud.o-forge.io/core/oc-lib/models/common" "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" "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/models/utils"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
) )
type ProcessingUsage struct { type ProcessingUsage struct {
CPUs map[string]*common.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]*common.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
RAM *common.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM RAM *models.RAM `bson:"ram,omitempty" json:"ram,omitempty"` // RAM is the RAM
StorageGb float64 `bson:"storage,omitempty" json:"storage,omitempty"` // Storage is the storage StorageGb float64 `bson:"storage,omitempty" json:"storage,omitempty"` // Storage is the storage
Hypothesis string `bson:"hypothesis,omitempty" json:"hypothesis,omitempty"` Hypothesis string `bson:"hypothesis,omitempty" json:"hypothesis,omitempty"`
@ -25,13 +26,13 @@ type ProcessingUsage struct {
*/ */
type ProcessingResource struct { type ProcessingResource struct {
AbstractIntanciatedResource[*ResourceInstance[*ResourcePartnerShip[*ProcessingResourcePricingProfile]]] AbstractIntanciatedResource[*ResourceInstance[*ResourcePartnerShip[*ProcessingResourcePricingProfile]]]
Infrastructure common.InfrastructureType `json:"infrastructure,omitempty" bson:"infrastructure,omitempty"` Infrastructure enum.InfrastructureType `json:"infrastructure,omitempty" bson:"infrastructure,omitempty"`
IsService bool `json:"is_service,omitempty" bson:"is_service,omitempty"` // IsService is a flag that indicates if the processing is a service IsService bool `json:"is_service,omitempty" bson:"is_service,omitempty"` // IsService is a flag that indicates if the processing is a service
Usage *ProcessingUsage `bson:"usage,omitempty" json:"usage,omitempty"` // Usage is the usage of the processing Usage *ProcessingUsage `bson:"usage,omitempty" json:"usage,omitempty"` // Usage is the usage of the processing
OpenSource bool `json:"open_source" bson:"open_source" default:"false"` OpenSource bool `json:"open_source" bson:"open_source" default:"false"`
License string `json:"license,omitempty" bson:"license,omitempty"` License string `json:"license,omitempty" bson:"license,omitempty"`
Maturity string `json:"maturity,omitempty" bson:"maturity,omitempty"` Maturity string `json:"maturity,omitempty" bson:"maturity,omitempty"`
Container *common.Container `json:"container,omitempty" bson:"container,omitempty"` // Container is the container Container *models.Container `json:"container,omitempty" bson:"container,omitempty"` // Container is the container
} }
type PricedProcessingResource struct { type PricedProcessingResource struct {

View File

@ -33,10 +33,6 @@ type AbstractResource struct {
SelectedInstanceIndex *int `json:"selected_instance_index,omitempty" bson:"selected_instance_index,omitempty"` // SelectedInstance is the selected instance SelectedInstanceIndex *int `json:"selected_instance_index,omitempty" bson:"selected_instance_index,omitempty"` // SelectedInstance is the selected instance
} }
func (ao *AbstractResource) GetAccessor(request *tools.APIRequest) utils.Accessor {
return nil
}
func (r *AbstractResource) StoreDraftDefault() { func (r *AbstractResource) StoreDraftDefault() {
r.IsDraft = true r.IsDraft = true
} }

View File

@ -4,7 +4,7 @@ import (
"errors" "errors"
"time" "time"
"cloud.o-forge.io/core/oc-lib/models/common" "cloud.o-forge.io/core/oc-lib/models/common/enum"
"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/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"
@ -17,7 +17,7 @@ import (
type StorageResource struct { type StorageResource struct {
AbstractIntanciatedResource[*StorageResourceInstance] // AbstractResource contains the basic fields of an object (id, name) AbstractIntanciatedResource[*StorageResourceInstance] // AbstractResource contains the basic fields of an object (id, name)
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
StorageType common.StorageType `bson:"storage_type,omitempty" json:"storage_type,omitempty"` // Type is the type of the storage StorageType enum.StorageType `bson:"storage_type,omitempty" json:"storage_type,omitempty"` // 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
} }
@ -25,11 +25,23 @@ func (d *StorageResource) GetAccessor(request *tools.APIRequest) utils.Accessor
return NewAccessor[*StorageResource](tools.STORAGE_RESOURCE, request, func() utils.DBObject { return &StorageResource{} }) // Create a new instance of the accessor return NewAccessor[*StorageResource](tools.STORAGE_RESOURCE, request, func() utils.DBObject { return &StorageResource{} }) // Create a new instance of the accessor
} }
func (abs *StorageResource) ConvertToPricedResource(
t tools.DataType, request *tools.APIRequest) pricing.PricedItemITF {
if t != tools.STORAGE_RESOURCE {
return nil
}
p := abs.AbstractIntanciatedResource.ConvertToPricedResource(t, request)
priced := p.(*PricedResource)
return &PricedStorageResource{
PricedResource: *priced,
}
}
type StorageResourceInstance struct { type StorageResourceInstance struct {
ResourceInstance[*StorageResourcePartnership] ResourceInstance[*StorageResourcePartnership]
Local bool `bson:"local" json:"local"` Local bool `bson:"local" json:"local"`
SecurityLevel string `bson:"security_level,omitempty" json:"security_level,omitempty"` SecurityLevel string `bson:"security_level,omitempty" json:"security_level,omitempty"`
SizeType common.StorageSize `bson:"size_type" json:"size_type" default:"0"` // SizeType is the type of the storage size 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 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 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 Redundancy string `bson:"redundancy,omitempty" json:"redundancy,omitempty"` // Redundancy is the redundancy of the storage

View File

@ -14,6 +14,26 @@ type Graph struct {
Links []GraphLink `bson:"links" json:"links" default:"{}" validate:"required"` // Links is the list of links between elements in the graph Links []GraphLink `bson:"links" json:"links" default:"{}" validate:"required"` // Links is the list of links between elements in the graph
} }
func (wf *Graph) IsProcessing(item GraphItem) bool {
return item.Processing != nil
}
func (wf *Graph) IsCompute(item GraphItem) bool {
return item.Compute != nil
}
func (wf *Graph) IsData(item GraphItem) bool {
return item.Data != nil
}
func (wf *Graph) IsStorage(item GraphItem) bool {
return item.Storage != nil
}
func (wf *Graph) IsWorkflow(item GraphItem) bool {
return item.Workflow != nil
}
func (g *Graph) GetAverageTimeRelatedToProcessingActivity(start time.Time, processings []*resources.ProcessingResource, resource resources.ResourceInterface, func (g *Graph) GetAverageTimeRelatedToProcessingActivity(start time.Time, processings []*resources.ProcessingResource, resource resources.ResourceInterface,
f func(GraphItem) resources.ResourceInterface, request *tools.APIRequest) (float64, float64) { f func(GraphItem) resources.ResourceInterface, request *tools.APIRequest) (float64, float64) {
nearestStart := float64(10000000000) nearestStart := float64(10000000000)

View File

@ -2,10 +2,10 @@ package workflow
import ( import (
"errors" "errors"
"fmt"
"time" "time"
"cloud.o-forge.io/core/oc-lib/models/collaborative_area/shallow_collaborative_area" "cloud.o-forge.io/core/oc-lib/models/collaborative_area/shallow_collaborative_area"
"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/common/pricing"
"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" "cloud.o-forge.io/core/oc-lib/models/resources"
@ -15,24 +15,23 @@ import (
) )
/* /*
* AbstractWorkflow is a struct that represents a workflow for resource or native workflow * Workflow is a struct that represents a workflow
* Warning: there is 2 types of workflows, the resource workflow and the native workflow * it defines the native workflow
* native workflow is the one that you create to schedule an execution
* resource workflow is the one that is created to set our native workflow in catalog
*/ */
type AbstractWorkflow struct { type Workflow struct {
utils.AbstractObject // AbstractObject contains the basic fields of an object (id, name)
resources.ResourceSet resources.ResourceSet
Graph *graph.Graph `bson:"graph,omitempty" json:"graph,omitempty"` // Graph UI & logic representation of the workflow Graph *graph.Graph `bson:"graph,omitempty" json:"graph,omitempty"` // Graph UI & logic representation of the workflow
ScheduleActive bool `json:"schedule_active" bson:"schedule_active"` // ScheduleActive is a flag that indicates if the schedule is active, if not the workflow is not scheduled and no execution or booking will be set ScheduleActive bool `json:"schedule_active" bson:"schedule_active"` // ScheduleActive is a flag that indicates if the schedule is active, if not the workflow is not scheduled and no execution or booking will be set
// Schedule *WorkflowSchedule `bson:"schedule,omitempty" json:"schedule,omitempty"` // Schedule is the schedule of the workflow // Schedule *WorkflowSchedule `bson:"schedule,omitempty" json:"schedule,omitempty"` // Schedule is the schedule of the workflow
Shared []string `json:"shared,omitempty" bson:"shared,omitempty"` // Shared is the ID of the shared workflow Shared []string `json:"shared,omitempty" bson:"shared,omitempty"` // Shared is the ID of the shared workflow // AbstractWorkflow contains the basic fields of a workflow
} }
func (d *Workflow) GetAccessor(request *tools.APIRequest) utils.Accessor { func (d *Workflow) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor(request) // Create a new instance of the accessor return NewAccessor(request) // Create a new instance of the accessor
} }
func (w *AbstractWorkflow) GetGraphItems(f func(item graph.GraphItem) bool) (list_datas []graph.GraphItem) { func (w *Workflow) GetGraphItems(f func(item graph.GraphItem) bool) (list_datas []graph.GraphItem) {
for _, item := range w.Graph.Items { for _, item := range w.Graph.Items {
if f(item) { if f(item) {
list_datas = append(list_datas, item) list_datas = append(list_datas, item)
@ -41,18 +40,7 @@ func (w *AbstractWorkflow) GetGraphItems(f func(item graph.GraphItem) bool) (lis
return return
} }
func (w *AbstractWorkflow) GetResources(f func(item graph.GraphItem) bool) map[string]resources.ResourceInterface { func (w *Workflow) GetPricedItem(f func(item graph.GraphItem) bool, request *tools.APIRequest) map[string]pricing.PricedItemITF {
list_datas := map[string]resources.ResourceInterface{}
for _, item := range w.Graph.Items {
if f(item) {
_, res := item.GetResource()
list_datas[res.GetID()] = res
}
}
return list_datas
}
func (w *AbstractWorkflow) GetPricedItem(f func(item graph.GraphItem) bool, request *tools.APIRequest) map[string]pricing.PricedItemITF {
list_datas := map[string]pricing.PricedItemITF{} list_datas := map[string]pricing.PricedItemITF{}
for _, item := range w.Graph.Items { for _, item := range w.Graph.Items {
if f(item) { if f(item) {
@ -64,7 +52,7 @@ func (w *AbstractWorkflow) GetPricedItem(f func(item graph.GraphItem) bool, requ
return list_datas return list_datas
} }
func (w *AbstractWorkflow) GetByRelatedProcessing(processingID string, g func(item graph.GraphItem) bool) []resources.ResourceInterface { func (w *Workflow) GetByRelatedProcessing(processingID string, g func(item graph.GraphItem) bool) []resources.ResourceInterface {
storages := []resources.ResourceInterface{} storages := []resources.ResourceInterface{}
for _, link := range w.Graph.Links { for _, link := range w.Graph.Links {
nodeID := link.Destination.ID nodeID := link.Destination.ID
@ -85,43 +73,6 @@ func (w *AbstractWorkflow) GetByRelatedProcessing(processingID string, g func(it
return storages return storages
} }
func (wf *AbstractWorkflow) IsProcessing(item graph.GraphItem) bool {
return item.Processing != nil
}
func (wf *AbstractWorkflow) IsCompute(item graph.GraphItem) bool {
return item.Compute != nil
}
func (wf *AbstractWorkflow) IsData(item graph.GraphItem) bool {
return item.Data != nil
}
func (wf *AbstractWorkflow) IsStorage(item graph.GraphItem) bool {
return item.Storage != nil
}
func (wf *AbstractWorkflow) IsWorkflow(item graph.GraphItem) bool {
return item.Workflow != nil
}
/*
* Workflow is a struct that represents a workflow
* it defines the native workflow
*/
type Workflow struct {
utils.AbstractObject // AbstractObject contains the basic fields of an object (id, name)
AbstractWorkflow // AbstractWorkflow contains the basic fields of a workflow
}
func (w *Workflow) getPricedItem(item graph.GraphItem, request *tools.APIRequest) pricing.PricedItemITF {
dt, res := item.GetResource()
if dt == tools.INVALID {
return nil
}
return res.ConvertToPricedResource(dt, request)
}
func (ao *Workflow) VerifyAuth(request *tools.APIRequest) bool { func (ao *Workflow) VerifyAuth(request *tools.APIRequest) bool {
isAuthorized := false isAuthorized := false
if len(ao.Shared) > 0 { if len(ao.Shared) > 0 {
@ -166,123 +117,83 @@ func (wfa *Workflow) CheckBooking(caller *tools.HTTPCaller) (bool, error) {
} }
func (wf *Workflow) Planify(start time.Time, end *time.Time, request *tools.APIRequest) (float64, map[tools.DataType][]pricing.PricedItemITF, *Workflow, error) { func (wf *Workflow) Planify(start time.Time, end *time.Time, request *tools.APIRequest) (float64, map[tools.DataType][]pricing.PricedItemITF, *Workflow, error) {
processings := []*resources.ProcessingResource{}
priceds := map[tools.DataType][]pricing.PricedItemITF{} priceds := map[tools.DataType][]pricing.PricedItemITF{}
priceds[tools.PROCESSING_RESOURCE] = []pricing.PricedItemITF{} ps, priceds, err := plan[*resources.ProcessingResource](tools.PROCESSING_RESOURCE, wf, priceds, request, wf.Graph.IsProcessing,
for _, item := range wf.GetGraphItems(wf.IsProcessing) { func(res resources.ResourceInterface, priced pricing.PricedItemITF) (time.Time, float64) {
dt, realItem := item.GetResource() return start.Add(time.Duration(wf.Graph.GetAverageTimeProcessingBeforeStart(0, res.GetID(), request)) * time.Second), priced.GetExplicitDurationInS()
if realItem == nil { }, func(started time.Time, duration float64) time.Time {
return 0, priceds, nil, errors.New("could not load the processing resource") return started.Add(time.Duration(duration))
})
if err != nil {
return 0, priceds, nil, err
} }
priced := realItem.ConvertToPricedResource(dt, request) if _, priceds, err = plan[resources.ResourceInterface](tools.DATA_RESOURCE, wf, priceds, request, wf.Graph.IsData,
timeFromStartS := wf.Graph.GetAverageTimeProcessingBeforeStart(0, realItem.GetID(), request) func(res resources.ResourceInterface, priced pricing.PricedItemITF) (time.Time, float64) {
started := start.Add(time.Duration(timeFromStartS) * time.Second) return start, 0
priced.SetLocationStart(started) }, func(started time.Time, duration float64) time.Time {
priced.SetLocationEnd(started.Add(time.Duration(priced.GetExplicitDurationInS()))) return *end
processings = append(processings, realItem.(*resources.ProcessingResource)) }); err != nil {
priceds[tools.PROCESSING_RESOURCE] = append(priceds[tools.PROCESSING_RESOURCE], priced) return 0, priceds, nil, err
} }
priceds[tools.DATA_RESOURCE] = []pricing.PricedItemITF{} for k, f := range map[tools.DataType]func(graph.GraphItem) bool{tools.STORAGE_RESOURCE: wf.Graph.IsStorage, tools.COMPUTE_RESOURCE: wf.Graph.IsCompute} {
for _, item := range wf.GetGraphItems(wf.IsData) { if _, priceds, err = plan[resources.ResourceInterface](k, wf, priceds, request, f,
dt, realItem := item.GetResource() func(res resources.ResourceInterface, priced pricing.PricedItemITF) (time.Time, float64) {
if realItem == nil { nearestStart, longestDuration := wf.Graph.GetAverageTimeRelatedToProcessingActivity(start, ps, res, func(i graph.GraphItem) (r resources.ResourceInterface) {
continue
}
priced := realItem.ConvertToPricedResource(dt, request)
priced.SetLocationStart(start)
priced.SetLocationEnd(*end)
priceds[tools.PROCESSING_RESOURCE] = append(priceds[tools.PROCESSING_RESOURCE], priced)
}
for _, f := range []func(graph.GraphItem) bool{wf.IsStorage, wf.IsCompute} {
for _, item := range wf.GetGraphItems(f) {
dt, r := item.GetResource()
if r == nil {
continue
}
if priceds[dt] == nil {
priceds[dt] = []pricing.PricedItemITF{}
}
priced := r.ConvertToPricedResource(dt, request)
nearestStart, longestDuration := wf.Graph.GetAverageTimeRelatedToProcessingActivity(start, processings, r,
func(i graph.GraphItem) resources.ResourceInterface {
if f(i) { if f(i) {
_, r := i.GetResource() _, r = i.GetResource()
}
return r return r
} else {
return nil
}
}, request) }, request)
started := start.Add(time.Duration(nearestStart) * time.Second) return start.Add(time.Duration(nearestStart) * time.Second), longestDuration
priced.SetLocationStart(started) }, func(started time.Time, duration float64) time.Time {
if longestDuration >= 0 { return started.Add(time.Duration(duration))
priced.SetLocationEnd(started.Add(time.Duration(longestDuration))) }); err != nil {
} return 0, priceds, nil, err
priceds[dt] = append(priceds[dt], priced)
} }
} }
longest := wf.getLongestTime(end, priceds, request) longest := common.GetPlannerLongestTime(end, priceds, request)
priceds[tools.WORKFLOW_RESOURCE] = []pricing.PricedItemITF{} if _, priceds, err = plan[resources.ResourceInterface](tools.WORKFLOW_RESOURCE, wf, priceds, request, wf.Graph.IsWorkflow,
for _, item := range wf.GetGraphItems(wf.IsWorkflow) { func(res resources.ResourceInterface, priced pricing.PricedItemITF) (time.Time, float64) {
access := NewAccessor(nil) start := start.Add(time.Duration(common.GetPlannerNearestStart(start, priceds, request)) * time.Second)
_, r := item.GetResource() longest := float64(-1)
if r == nil { r, code, err := res.GetAccessor(request).LoadOne(res.GetID())
return 0, priceds, nil, errors.New("could not load the workflow")
}
priced := r.ConvertToPricedResource(tools.WORKFLOW_RESOURCE, request)
res, code, err := access.LoadOne(r.GetID())
if code != 200 || err != nil { if code != 200 || err != nil {
return 0, priceds, nil, errors.New("could not load the workflow with id: " + fmt.Sprintf("%v", err.Error())) return start, longest
} }
neoLongest := float64(0) if neoLongest, _, _, err := r.(*Workflow).Planify(start, end, request); err != nil {
innerWF := res.(*Workflow) return start, longest
neoLongest, _, innerWF, err = innerWF.Planify(start, end, request) } else if neoLongest > longest {
if neoLongest > longest {
longest = neoLongest longest = neoLongest
} }
started := start.Add(time.Duration(wf.getNearestStart(start, priceds, request)) * time.Second) return start.Add(time.Duration(common.GetPlannerNearestStart(start, priceds, request)) * time.Second), longest
priced.SetLocationStart(started) }, func(start time.Time, longest float64) time.Time {
durationE := time.Duration(longest) return start.Add(time.Duration(longest) * time.Second)
if durationE < 0 { }); err != nil {
continue return 0, priceds, nil, err
}
ended := start.Add(durationE * time.Second)
priced.SetLocationEnd(ended)
priceds[tools.WORKFLOW_RESOURCE] = append(priceds[tools.WORKFLOW_RESOURCE], priced)
} }
return longest, priceds, wf, nil return longest, priceds, wf, nil
} }
func (wf *Workflow) getNearestStart(start time.Time, priceds map[tools.DataType][]pricing.PricedItemITF, request *tools.APIRequest) float64 { func plan[T resources.ResourceInterface](dt tools.DataType, wf *Workflow, priceds map[tools.DataType][]pricing.PricedItemITF, request *tools.APIRequest,
near := float64(10000000000) f func(graph.GraphItem) bool, start func(resources.ResourceInterface, pricing.PricedItemITF) (time.Time, float64), end func(time.Time, float64) time.Time) ([]T, map[tools.DataType][]pricing.PricedItemITF, error) {
for _, items := range priceds { resources := []T{}
for _, priced := range items { for _, item := range wf.GetGraphItems(f) {
if priced.GetLocationStart() == nil { if priceds[dt] == nil {
continue priceds[dt] = []pricing.PricedItemITF{}
} }
newS := priced.GetLocationStart() dt, realItem := item.GetResource()
if newS.Sub(start).Seconds() < near { if realItem == nil {
near = newS.Sub(start).Seconds() return resources, priceds, errors.New("could not load the processing resource")
} }
priced := realItem.ConvertToPricedResource(dt, request)
started, duration := start(realItem, priced)
priced.SetLocationStart(started)
if duration >= 0 {
priced.SetLocationEnd(end(started, duration))
} }
// get the nearest start from start var priced.SetLocationEnd(end(started, priced.GetExplicitDurationInS()))
resources = append(resources, realItem.(T))
priceds[dt] = append(priceds[dt], priced)
} }
return near return resources, priceds, nil
}
func (wf *Workflow) getLongestTime(end *time.Time, priceds map[tools.DataType][]pricing.PricedItemITF, request *tools.APIRequest) float64 {
if end == nil {
return -1
}
longestTime := float64(0)
for _, priced := range priceds[tools.PROCESSING_RESOURCE] {
if priced.GetLocationEnd() == nil {
continue
}
newS := priced.GetLocationEnd()
if longestTime < newS.Sub(*end).Seconds() {
longestTime = newS.Sub(*end).Seconds()
}
// get the nearest start from start var
}
return longestTime
} }