From 64ae7eeb4c041bf1da4b349e555d84557de2dcc3 Mon Sep 17 00:00:00 2001 From: pb Date: Mon, 15 Apr 2024 11:42:17 +0200 Subject: [PATCH] added links models to workflow --- models/links.go | 34 +++++++----- models/workflow.go | 134 +++++++++++++++++++++++++-------------------- 2 files changed, 95 insertions(+), 73 deletions(-) diff --git a/models/links.go b/models/links.go index 55bc8d9..5ad26f2 100644 --- a/models/links.go +++ b/models/links.go @@ -1,26 +1,34 @@ package models import ( - "fmt" - "reflect" + "cloud.o-forge.io/core/oc-catalog/models/rtype" ) type Link struct { - source string - destination string - dcLink bool + // ID primitive.ObjectID `json:"ID" bson:"_id" required:"true" example:"5099803df3f4948bd2f98391"` + Source string `json:"source" description:"id in the workflow of the source object"` + Destination string `json:"destination" description:"id in the workflow of the destination object"` + DCLink bool `json:"dcLink" description:"is this a link with a datacenter"` } -func NewLink(src interface{}, dst interface{}) (link Link) { - // Check type with reflect and get ID - typeSrc := reflect.TypeOf(src) - typeDst := reflect.TypeOf(dst) +// Use ResourceObject parameter to process certain components type differently +// and Id's to identify each component as a node in an oriented graph - fmt.Println("src is %s\ndst is %s",typeSrc,typeDst) +func NewLink(src ResourceObject, srcId string, dst ResourceObject, dstId string) (link Link) { + + link.Source = srcId + link.Destination = dstId + + if (src.getRtype() == rtype.DATACENTER || dst.getRtype() == rtype.DATACENTER){ + link.DCLink = true + + + } + return } -func (l *Link) AddLinkToDataCenter(component interface{}) { - // if the component has a DataCenter id attribute then add it (switch on type) -} +// So far only computing components expect the ID of the DC in their attributes +// func (l *Link) AddLinkToDataCenter(component models.ComputingModel) { +// } diff --git a/models/workflow.go b/models/workflow.go index 8a99b5d..1fecb71 100644 --- a/models/workflow.go +++ b/models/workflow.go @@ -52,10 +52,11 @@ const SchedulesDB = "schedules" type Workflow struct { // The key of the map is the ID of the object itself - Data map[string]DataObject `json:"data"` - Computing map[string]ComputingObject `json:"computing"` - Storage map[string]StorageObject `json:"storage"` - Datacenter map[string]DatacenterObject `json:"datacenter"` //TODO: Decide if there should be multiple objects of a datacenter + Data map[string]DataObject `json:"data"` + Computing map[string]ComputingObject `json:"computing"` + Storage map[string]StorageObject `json:"storage"` + Datacenter map[string]DatacenterObject `json:"datacenter"` //TODO: Decide if there should be multiple objects of a datacenter + Links map[string]Link `json:"link"` Schedules WorkflowSchedule `json:"schedules"` @@ -181,6 +182,13 @@ func (w *Workflow) AddObj(robj ResourceObject) *primitive.ObjectID { return &outputID } +func (w *Workflow) AddLinkToWorkflow (link Link, id string){ + if w.Links == nil { + w.Links = make(map[string]Link) + } + w.Links[id] = link +} + func (w *Workflow) UpdateDB(userID, workflowName string) error { _, err := services.MngoCollWorkspace.UpdateOne(services.MngoCtx, @@ -543,9 +551,7 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [ logs.Alert("Error creating links") return err, nil } - // Move the attribute of the object's tags into the mxCell's for an easier processing - // currentWorkflow.extractMxCell(xmlModel) targetWorkspaceWorkflow, err, mxissues := userWorkspace.ConsumeMxGraphModel(xmlModel) if err != nil { @@ -593,7 +599,6 @@ func FindSliceInSlice(slice1 []string, slice2 []string) (int, int, bool) { return -1, -1, false } -// TODO : correct this method to suppport mxcells with settings func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Workflow, err error, issues []error) { returned_wf = &Workflow{} @@ -648,62 +653,20 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor default: // Not root nor resource. Should be only links - sourceObj := returned_wf.GetResource(cell.Source) - targetObj := returned_wf.GetResource(cell.Target) - - link := NewLink(sourceObj,targetObj) - _ = link - - if sourceObj == nil || targetObj == nil { - if sourceObj == nil && targetObj == nil { - issues = append(issues, errors.New("Arrow "+cell.ID+" is alone")) - } else if sourceObj == nil { - issues = append(issues, errors.New("Arrow ("+cell.ID+") to "+*targetObj.getName()+" without parent")) - } else { - issues = append(issues, errors.New("Arrow "+cell.ID+" from "+*sourceObj.getName()+" without target")) - } - - // If is a invalid link, we can't save it in the DB - continue - } - - if sourceObj.getRtype() == rtype.DATACENTER || targetObj.getRtype() == rtype.DATACENTER { - var datacenter, datacenterLinked *string - - if sourceObj.getRtype() == rtype.DATACENTER { - datacenter = cell.Source - datacenterLinked = cell.Target - } else { - datacenter = cell.Target - datacenterLinked = cell.Source - } - - switch returned_wf.GetResource(datacenterLinked).getRtype() { - case rtype.COMPUTING: - computingObj := returned_wf.GetResource(datacenterLinked).(*ComputingObject) - - // We should always get a ID because we already registered resources and discarded which doesn't correspond to existent models - computingObj.DataCenterID = *datacenter - returned_wf.UpdateObj(computingObj, *datacenterLinked) - } - - } else { - targetObj.addLink(INPUT, *cell.Source) - returned_wf.UpdateObj(targetObj, *cell.Target) // save back - - // If we have a relationship of: - // Source ----> Target - // - // The Source will be in the INPUTs of the Target. - // But we also must make sure that the Target will be in the OUTPUTs of the Source - - sourceObj.addLink(OUTPUT, *cell.Target) - returned_wf.UpdateObj(sourceObj, *cell.Source) - } - + // If is a invalid link, we can't save it in the DB + // We should always get a ID because we already registered resources and discarded which doesn't correspond to existent models + // save back + // If we have a relationship of: + // Source ----> Target + // + // The Source will be in the INPUTs of the Target. + // But we also must make sure that the Target will be in the OUTPUTs of the Source + } } + issues = ws.CreateLinks(returned_wf,xmlmodel.Root.MxLink, issues) + dcslist := make(map[string]bool) dataslist := make(map[string]bool) // datalist := make(map[string]bool) @@ -856,6 +819,57 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor return } +func (w Workspace) CreateLinks(returned_wf *Workflow, links []MxLink, issues []error) []error { + + for _, link := range links { + sourceObj := returned_wf.GetResource(&link.Source) + targetObj := returned_wf.GetResource(&link.Target) + + link_object := NewLink(sourceObj,link.Source, targetObj, link.Target) + returned_wf.AddLinkToWorkflow(link_object,link.ID) + + if sourceObj == nil || targetObj == nil { + if sourceObj == nil && targetObj == nil { + issues = append(issues, errors.New("Arrow "+link.ID +" is alone")) + } else if sourceObj == nil { + issues = append(issues, errors.New("Arrow ("+link.ID+") to "+*targetObj.getName()+" without parent")) + } else { + issues = append(issues, errors.New("Arrow "+link.ID+" from "+*sourceObj.getName()+" without target")) + } + + } + + + // if sourceObj.getRtype() == rtype.DATACENTER || targetObj.getRtype() == rtype.DATACENTER { + // var datacenter, datacenterLinked *string + + // if sourceObj.getRtype() == rtype.DATACENTER { + // datacenter = &link.Source + // datacenterLinked = &link.Target + // } else { + // datacenter = &link.Target + // datacenterLinked = &link.Source + // } + + // switch returned_wf.GetResource(datacenterLinked).getRtype() { + // case rtype.COMPUTING: + // computingObj := returned_wf.GetResource(datacenterLinked).(*ComputingObject) + + // computingObj.DataCenterID = *datacenter + // returned_wf.UpdateObj(computingObj, *datacenterLinked) + // } + + // } else { + // targetObj.addLink(INPUT, *link.Source) + // returned_wf.UpdateObj(targetObj, *link.Target) + + // sourceObj.addLink(OUTPUT, *link.Target) + // returned_wf.UpdateObj(sourceObj, *link.Source) + // } + } + return issues +} + func sumExecutionReqs(exeqReq ...ExecutionRequirementsModel) (ret ExecutionRequirementsModel) { for _, v := range exeqReq { ret.CPUs += v.CPUs