package models import ( "encoding/xml" "fmt" "strings" "cloud.o-forge.io/core/oc-catalog/models/rtype" "cloud.o-forge.io/core/oc-catalog/services" structtomap "github.com/Klathmon/StructToMap" "github.com/beego/beego/v2/core/logs" "go.mongodb.org/mongo-driver/bson/primitive" ) type ExecutionRequirementsModel struct { CPUs uint `json:"cpus" required:"true"` GPUs uint `json:"gpus" description:"Amount of GPUs needed"` RAM uint `json:"ram" required:"true" description:"Units in MB"` // We should check closely how to deal with storage, since they are independent models // but also part of a DataCenter // Storage uint `json:"storage" description:"Units in MB"` Parallel bool `json:"parallel"` ScalingModel uint `json:"scaling_model"` DiskIO string `json:"disk_io"` } type RepositoryModel struct { Credentials string `json:"credentials"` Url string `json:"url"` } type ComputingNEWModel struct { Name string `json:"name,omitempty" required:"true" validate:"required" description:"Name of the computing"` Description string `json:"description,omitempty" required:"true"` ShortDescription string `json:"short_description,omitempty" required:"true" validate:"required"` Logo string `json:"logo,omitempty" required:"true" validate:"required"` Type string `json:"type,omitempty" required:"true"` Owner string `json:"owner,omitempty"` License string `json:"license,omitempty"` Price uint `json:"price,omitempty"` ExecutionRequirements ExecutionRequirementsModel `json:"execution_requirements,omitempty"` Dinputs []string `json:"dinputs,omitempty"` // Possibly redundant with Links object in oc-schedule Doutputs []string `json:"doutputs,omitempty"` // Possibly redundant with Links objects in oc-schedule Image string `json:"image,omitempty"` Command string `json:"command,omitempty"` Arguments []string `json:"arguments,omitempty"` Environment []string `json:"environment,omitempty"` Ports []string `json:"ports,omitempty"` // CustomDeployment string `json:"custom_deployment,omitempty"` // Repository RepositoryModel `json:"repository,omitempty"` } type ComputingModel struct { ID string `json:"ID" bson:"_id" required:"true" example:"5099803df3f4948bd2f98391"` ComputingNEWModel `bson:",inline"` } func (model ComputingModel) getRtype() rtype.Rtype { return rtype.COMPUTING } func (model ComputingModel) getName() string { return model.Name } // A user can have multiple workload project with the same model. We must distinguish what is // the model and what is the user object type ComputingObject struct { ReferenceID primitive.ObjectID `json:"referenceID" description:"Computing model ID"` Inputs []string `json:"inputs"` Outputs []string `json:"outputs"` Image string `json:"image,omitempty"` Command string `json:"command,omitempty"` Arguments []string `json:"arguments,omitempty"` Environment []string `json:"environment,omitempty"` Ports []string `json:"ports,omitempty"` DataCenterID string `json:"datacenterID" description:"Datacenter where the computing will be executed"` } func (obj ComputingObject) getHost() *string { return nil // Host is DC only attribute } func (obj *ComputingObject) setReference(rID primitive.ObjectID) { obj.ReferenceID = rID } func (obj ComputingObject) getReference() primitive.ObjectID { return obj.ReferenceID } func (obj ComputingObject) getRtype() rtype.Rtype { return rtype.COMPUTING } func (obj ComputingObject) getModel() (ret ResourceModel, err error) { var ret2 ComputingModel res := services.MngoCollComputing.FindOne(services.MngoCtx, primitive.M{"_id": obj.ReferenceID}, ) if err = res.Err(); err != nil { return } err = res.Decode(&ret2) return ret2, err } func (obj ComputingObject) getName() (name *string) { aa, err := obj.getModel() if err != nil { logs.Warn(err) return } name2 := aa.getName() return &name2 } func (obj ComputingObject) isLinked(rObjID string) LinkingState { if contains(obj.Inputs, rObjID) { return INPUT } if contains(obj.Outputs, rObjID) { return OUTPUT } return NO_LINK } func (obj *ComputingObject) addLink(direction LinkingState, rID string) { switch direction { case INPUT: obj.Inputs = append(obj.Inputs, rID) case OUTPUT: obj.Outputs = append(obj.Outputs, rID) } } func GetOneComputing(ID string) (object *ComputingModel, err error) { obj, err := getOneResourceByID(ID, rtype.COMPUTING) if err != nil { return object, err } object = obj.(*ComputingModel) return object, err } func GetMultipleComputing(IDs []string) (object *[]ComputingModel, err error) { objArray, err := getMultipleResourceByIDs(IDs, rtype.COMPUTING) if err != nil { return nil, err } object = objArray.(*[]ComputingModel) return object, err } func PostOneComputing(obj ComputingNEWModel) (ID string, err error) { return postOneResource(obj, rtype.COMPUTING) } func (obj *ComputingObject) AddUserInput(inputs []xml.Attr){ logs.Alert("AddUserInput() is going to throw some alerts while mxGraph GUI is not updated to adapt the inputs to the componant") // So far only a few input to handle so a switch with a case for each type of attribute // is enough, to prevent too much complexity for _, j := range(inputs){ setting, _ := structtomap.Convert(j) // fmt.Println(strings.ToLower(setting["Name"])) name := setting["Name"].(xml.Name).Local value := setting["Value"] switch name { case "command": obj.Command = value.(string) case "args": empty, sliced_arguments := getSliceSettings(value.(string)) if (!empty){ obj.Arguments = sliced_arguments } case "env" : empty, sliced_arguments := getSliceSettings(value.(string)) if (!empty){ obj.Environment = sliced_arguments } default: logs.Alert(fmt.Printf("%s is not an attribute of computing componants", name)) } } } func getSliceSettings(string_to_parse string)(empty bool, sliced_string []string){ if len(string_to_parse) == 0 { return true, nil } empty = false sliced_string = strings.Split(string_to_parse," ") return }