bugfix empty workflow
This commit is contained in:
parent
9bd5be7758
commit
a1f04dc2f0
@ -52,11 +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
|
||||
Links map[string]Link `json:"link"`
|
||||
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"`
|
||||
|
||||
@ -78,7 +78,7 @@ type ResourceObject interface {
|
||||
|
||||
// This type allows to process computing and storage component
|
||||
// which can get input from the user
|
||||
type EditableResourceObject interface{
|
||||
type EditableResourceObject interface {
|
||||
ResourceObject
|
||||
addUserInput(map[string]interface{})
|
||||
}
|
||||
@ -119,13 +119,13 @@ func (w *Workflow) GetResource(rObjID *string) (retObj ResourceObject) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if storVal, ok := w.Data[*rObjID]; ok {
|
||||
retObj = &storVal
|
||||
if datVal, ok := w.Data[*rObjID]; ok {
|
||||
retObj = &datVal
|
||||
return
|
||||
}
|
||||
|
||||
if storVal, ok := w.Computing[*rObjID]; ok {
|
||||
retObj = &storVal
|
||||
if compVal, ok := w.Computing[*rObjID]; ok {
|
||||
retObj = &compVal
|
||||
return
|
||||
}
|
||||
|
||||
@ -134,8 +134,8 @@ func (w *Workflow) GetResource(rObjID *string) (retObj ResourceObject) {
|
||||
return
|
||||
}
|
||||
|
||||
if storVal, ok := w.Datacenter[*rObjID]; ok {
|
||||
retObj = &storVal
|
||||
if dcVal, ok := w.Datacenter[*rObjID]; ok {
|
||||
retObj = &dcVal
|
||||
return
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ func (w *Workflow) AddObj(robj ResourceObject) *primitive.ObjectID {
|
||||
return &outputID
|
||||
}
|
||||
|
||||
func (w *Workflow) AddLinkToWorkflow (link Link, id string){
|
||||
func (w *Workflow) AddLinkToWorkflow(link Link, id string) {
|
||||
if w.Links == nil {
|
||||
w.Links = make(map[string]Link)
|
||||
}
|
||||
@ -547,7 +547,6 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [
|
||||
}
|
||||
|
||||
xmlModel.createLinks()
|
||||
|
||||
|
||||
targetWorkspaceWorkflow, err, mxissues := userWorkspace.ConsumeMxGraphModel(xmlModel)
|
||||
if err != nil {
|
||||
@ -605,37 +604,38 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor
|
||||
return xmlmodel.Root.MxCell[i].RID != nil
|
||||
})
|
||||
|
||||
// Create the object and add it to the appropriate list
|
||||
// Create the object and add it to the appropriate list
|
||||
// for all the components with setting, which are identified
|
||||
// by a MxObject tag in the xml
|
||||
for _, object := range *xmlmodel.Root.MxObject{
|
||||
|
||||
resObj, err, mxissues := returned_wf.mxCellToComponent(object.MxCell,ws)
|
||||
if err != nil {
|
||||
issues = append(issues, mxissues...)
|
||||
}
|
||||
|
||||
// add the component to the worflow's attribute that stores
|
||||
// all components in a map[string]Component where the key
|
||||
// is the component's ID in the mxGraph and the value the Component object
|
||||
returned_wf.UpdateObj(resObj,object.ID)
|
||||
|
||||
// Construct the object corresponding to the componant's type and use its addUserInput method
|
||||
if(resObj.getRtype() == rtype.COMPUTING){
|
||||
comp_obj := returned_wf.GetResource(&object.ID).(*ComputingObject)
|
||||
comp_obj.AddUserInput(object.Settings)
|
||||
returned_wf.UpdateObj(comp_obj,object.ID)
|
||||
}
|
||||
// if(resObj.getRtype() == rtype.DATA){
|
||||
// }
|
||||
|
||||
}
|
||||
if ok := xmlmodel.Root.MxObject != nil; ok {
|
||||
for _, object := range *xmlmodel.Root.MxObject {
|
||||
|
||||
resObj, err, mxissues := returned_wf.mxCellToComponent(object.MxCell, ws)
|
||||
if err != nil {
|
||||
issues = append(issues, mxissues...)
|
||||
}
|
||||
|
||||
// add the component to the worflow's attribute that stores
|
||||
// all components in a map[string]Component where the key
|
||||
// is the component's ID in the mxGraph and the value the Component object
|
||||
returned_wf.UpdateObj(resObj, object.ID)
|
||||
|
||||
// Construct the object corresponding to the componant's type and use its addUserInput method
|
||||
if resObj.getRtype() == rtype.COMPUTING {
|
||||
comp_obj := returned_wf.GetResource(&object.ID).(*ComputingObject)
|
||||
comp_obj.AddUserInput(object.Settings)
|
||||
returned_wf.UpdateObj(comp_obj, object.ID)
|
||||
}
|
||||
// if(resObj.getRtype() == rtype.DATA){
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
for _, cell := range xmlmodel.Root.MxCell {
|
||||
|
||||
switch {
|
||||
case cell.RID != nil:
|
||||
resObj, err, mxissues := returned_wf.mxCellToComponent(cell,ws)
|
||||
resObj, err, mxissues := returned_wf.mxCellToComponent(cell, ws)
|
||||
if err != nil {
|
||||
issues = append(issues, mxissues...)
|
||||
}
|
||||
@ -674,63 +674,13 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor
|
||||
//
|
||||
// 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 = returned_wf.CreateLinks(xmlmodel.Root.MxLink, issues)
|
||||
issues = returned_wf.CheckLinks(issues)
|
||||
|
||||
// dcslist := make(map[string]bool)
|
||||
// dataslist := make(map[string]bool)
|
||||
// // datalist := make(map[string]bool)
|
||||
|
||||
|
||||
// // Test wether the computing components are linked with a DC
|
||||
// for _, comp := range returned_wf.Computing {
|
||||
// if comp.DataCenterID == "" {
|
||||
// issues = append(issues, errors.New("Computing "+*comp.getName()+" without a Datacenter"))
|
||||
// } else {
|
||||
// // If doesn't exist in the list, means is new element to register as used
|
||||
// dcslist[comp.DataCenterID] = true
|
||||
|
||||
// }
|
||||
|
||||
// for _, dcin := range comp.Inputs {
|
||||
// switch returned_wf.GetResource(&dcin).getRtype() {
|
||||
// case rtype.DATA:
|
||||
// dataslist[dcin] = true
|
||||
// }
|
||||
// }
|
||||
|
||||
// for _, dcout := range comp.Outputs {
|
||||
// switch returned_wf.GetResource(&dcout).getRtype() {
|
||||
// case rtype.DATA:
|
||||
// dataslist[dcout] = true
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// for _, storage_component := range returned_wf.Storage {
|
||||
// if storage_component.Inputs == nil && storage_component.Outputs == nil {
|
||||
// issues = append(issues, errors.New("Storage "+*storage_component.getName()+" without compatible inputs and outputs"))
|
||||
// }
|
||||
// }
|
||||
|
||||
// for dcID, dc_component := range returned_wf.Datacenter {
|
||||
// // if rID doesn't exist in the list, it means that it's not used
|
||||
// if _, ok := dcslist[dcID]; !ok {
|
||||
// issues = append(issues, errors.New("DC "+*dc_component.getName()+" not attached to any Computing"))
|
||||
// }
|
||||
// }
|
||||
|
||||
// for dcID, data_component := range returned_wf.Data {
|
||||
// // if rID doesn't exist in the list, it means that it's not used
|
||||
// if _, ok := dataslist[dcID]; !ok {
|
||||
// issues = append(issues, errors.New("Data "+*data_component.getName()+" not attached to any Computing"))
|
||||
// }
|
||||
// }
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// //
|
||||
@ -834,13 +784,13 @@ func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Wor
|
||||
}
|
||||
|
||||
func (w *Workflow) CreateLinks(links []MxLink, issues []error) []error {
|
||||
|
||||
for _, link := range links {
|
||||
if (len(link.Source) > 0 && len(link.Target) > 0){
|
||||
|
||||
for _, link := range links {
|
||||
if len(link.Source) > 0 && len(link.Target) > 0 {
|
||||
sourceObj := w.GetResource(&link.Source)
|
||||
targetObj := w.GetResource(&link.Target)
|
||||
link_object := NewLink(sourceObj,link.Source, targetObj, link.Target)
|
||||
w.AddLinkToWorkflow(link_object,link.ID)
|
||||
link_object := NewLink(sourceObj, link.Source, targetObj, link.Target)
|
||||
w.AddLinkToWorkflow(link_object, link.ID)
|
||||
} else {
|
||||
issues = append(issues, w.processLinkErrors(link))
|
||||
}
|
||||
@ -849,59 +799,58 @@ func (w *Workflow) CreateLinks(links []MxLink, issues []error) []error {
|
||||
}
|
||||
|
||||
func (w *Workflow) processLinkErrors(link MxLink) (issue error) {
|
||||
if len(link.Source) == 0 && len(link.Target) == 0 {
|
||||
issue = errors.New("Arrow "+link.ID+" is alone")
|
||||
} else if len(link.Source) == 0{
|
||||
if len(link.Source) == 0 && len(link.Target) == 0 {
|
||||
issue = errors.New("Arrow " + link.ID + " is alone")
|
||||
} else if len(link.Source) == 0 {
|
||||
targetObj := w.GetResource(&link.Target)
|
||||
issue = errors.New("Arrow ("+link.ID+") to "+*targetObj.getName()+" without parent")
|
||||
issue = errors.New("Arrow (" + link.ID + ") to " + *targetObj.getName() + " without parent")
|
||||
} else {
|
||||
sourceObj := w.GetResource(&link.Source)
|
||||
issue = errors.New("Arrow "+link.ID+" from "+*sourceObj.getName()+" without target")
|
||||
issue = errors.New("Arrow " + link.ID + " from " + *sourceObj.getName() + " without target")
|
||||
}
|
||||
|
||||
return issue
|
||||
}
|
||||
|
||||
func (w *Workflow) CheckLinks(issues []error) []error {
|
||||
|
||||
|
||||
// Check that storage components have a valid link
|
||||
for id, storage := range w.Storage {
|
||||
if(!w.IsComponentSrc(id) && !w.IsComponentDst(id)){
|
||||
if !w.IsComponentSrc(id) && !w.IsComponentDst(id) {
|
||||
issues = append(issues, errors.New("Storage "+*storage.getName()+" without compatible inputs and outputs"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check that data components are linked to a computing component
|
||||
for id, data := range w.Data {
|
||||
if(!w.HasLinkageToComputing(id)){
|
||||
if !w.HasLinkageToComputing(id) {
|
||||
issues = append(issues, errors.New("Data "+*data.getName()+" not attached to any Computing"))
|
||||
}
|
||||
}
|
||||
|
||||
// Check that DC is linked to a computing component
|
||||
for id, dc:= range w.Datacenter {
|
||||
if(!w.HasLinkageToComputing(id)){
|
||||
for id, dc := range w.Datacenter {
|
||||
if !w.HasLinkageToComputing(id) {
|
||||
issues = append(issues, errors.New("Datacenter "+*dc.getName()+" not attached to any Computing"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Check that all data computing components are linked to a DC
|
||||
for id,comp:= range w.Computing {
|
||||
if(!w.HasLinkageToDC(id)){
|
||||
for id, comp := range w.Computing {
|
||||
if !w.HasLinkageToDC(id) {
|
||||
issues = append(issues, errors.New("Computing "+*comp.getName()+" not attached to any datacenter"))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return issues
|
||||
}
|
||||
|
||||
|
||||
func (w *Workflow) IsComponentSrc(id string) bool {
|
||||
|
||||
for _, link := range w.Links{
|
||||
if(link.Source == id && link.Source != ""){
|
||||
|
||||
for _, link := range w.Links {
|
||||
if link.Source == id && link.Source != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -910,9 +859,9 @@ func (w *Workflow) IsComponentSrc(id string) bool {
|
||||
}
|
||||
|
||||
func (w *Workflow) IsComponentDst(id string) bool {
|
||||
|
||||
for _, link := range w.Links{
|
||||
if(link.Destination == id && link.Source != ""){
|
||||
|
||||
for _, link := range w.Links {
|
||||
if link.Destination == id && link.Source != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -923,10 +872,10 @@ func (w *Workflow) IsComponentDst(id string) bool {
|
||||
func (w *Workflow) HasLinkageToComputing(id string) bool {
|
||||
|
||||
for idComputing, _ := range w.Computing {
|
||||
if( (w.IsComponentSrc(id) && w.IsComponentDst(idComputing)) || (w.IsComponentSrc(idComputing) && w.IsComponentDst(id))){
|
||||
if (w.IsComponentSrc(id) && w.IsComponentDst(idComputing)) || (w.IsComponentSrc(idComputing) && w.IsComponentDst(id)) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
@ -934,8 +883,8 @@ func (w *Workflow) HasLinkageToComputing(id string) bool {
|
||||
|
||||
func (w *Workflow) HasLinkageToDC(id string) bool {
|
||||
|
||||
for _, link := range w.Links{
|
||||
if(link.Source == id && link.DCLink){
|
||||
for _, link := range w.Links {
|
||||
if link.Source == id && link.DCLink {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1124,15 +1073,15 @@ func CheckAndBookWorkflowSchedule(username, workflowName string, book bool) (myR
|
||||
SchedulesDB: ¤tWorkflow.Schedules}},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
logs.Critical("Internal error when updating in DB: " + err.Error())
|
||||
}
|
||||
|
||||
return myRet, nil
|
||||
}
|
||||
|
||||
// Not sure if this method handles error propagation well
|
||||
func (wf Workflow) mxCellToComponent(cell MxCell, ws Workspace) (resObj ResourceObject,err error, issues []error){
|
||||
// Not sure if this method handles error propagation well
|
||||
func (wf Workflow) mxCellToComponent(cell MxCell, ws Workspace) (resObj ResourceObject, err error, issues []error) {
|
||||
rType := ws.getRtype(*cell.RID)
|
||||
|
||||
if rType == rtype.INVALID {
|
||||
@ -1151,7 +1100,7 @@ func (wf Workflow) mxCellToComponent(cell MxCell, ws Workspace) (resObj Resource
|
||||
|
||||
resObj = wf.CreateResourceObject(rType)
|
||||
resObj.setReference(rIDObj)
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -236,6 +236,27 @@
|
||||
},
|
||||
"inputs": [],
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"name": "Mosquito server",
|
||||
"short_description": "open source message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1.",
|
||||
"logo": "./local_imgs/mosquitto-logo.png",
|
||||
"description": "A very long description of what this storage is",
|
||||
"type": "computing",
|
||||
"owner": "IRT",
|
||||
"price": 300,
|
||||
"license": "GPLv2",
|
||||
"execution_requirements": {
|
||||
"cpus": 1,
|
||||
"ram": 1024,
|
||||
"storage": 300,
|
||||
"gpus": 1,
|
||||
"disk_io": "30 MB/s",
|
||||
"parallel": true,
|
||||
"scaling_model": 2
|
||||
},
|
||||
"inputs": [],
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -273,22 +294,6 @@
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"URL" : ""
|
||||
},
|
||||
{
|
||||
"name": "Mosquito server",
|
||||
"short_description": "open source message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1.",
|
||||
"logo": "./local_imgs/mosquitto-logo.png",
|
||||
"description": "A very long description of what this storage is",
|
||||
"type": "storage",
|
||||
"DCacronym": "DC_myDC",
|
||||
"size": 40000,
|
||||
"encryption": false,
|
||||
"redundancy": "RAID5S",
|
||||
"throughput": "r:300,w:350",
|
||||
"bookingPrice": 90,
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"URL" : ""
|
||||
}
|
||||
]
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user