| @@ -449,6 +449,16 @@ type FlavorInfo struct { | |||||
| Desc string `json:"desc"` | Desc string `json:"desc"` | ||||
| } | } | ||||
| type ImageInfosModelArts struct { | |||||
| ImageInfo []*ImageInfoModelArts `json:"image_info"` | |||||
| } | |||||
| type ImageInfoModelArts struct { | |||||
| Id string `json:"id"` | |||||
| Value string `json:"value"` | |||||
| Desc string `json:"desc"` | |||||
| } | |||||
| type PoolInfos struct { | type PoolInfos struct { | ||||
| PoolInfo []*PoolInfo `json:"pool_info"` | PoolInfo []*PoolInfo `json:"pool_info"` | ||||
| } | } | ||||
| @@ -19,7 +19,8 @@ type CreateModelArtsNotebookForm struct { | |||||
| JobName string `form:"job_name" binding:"Required"` | JobName string `form:"job_name" binding:"Required"` | ||||
| Attachment string `form:"attachment"` | Attachment string `form:"attachment"` | ||||
| Description string `form:"description"` | Description string `form:"description"` | ||||
| Flavor string `form:"flavor"` | |||||
| Flavor string `form:"flavor" binding:"Required"` | |||||
| ImageId string `form:"image_id" binding:"Required"` | |||||
| } | } | ||||
| func (f *CreateModelArtsNotebookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | func (f *CreateModelArtsNotebookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | ||||
| @@ -2,6 +2,7 @@ package modelarts | |||||
| import ( | import ( | ||||
| "encoding/json" | "encoding/json" | ||||
| "errors" | |||||
| "fmt" | "fmt" | ||||
| "path" | "path" | ||||
| "strconv" | "strconv" | ||||
| @@ -15,8 +16,8 @@ import ( | |||||
| const ( | const ( | ||||
| //notebook | //notebook | ||||
| storageTypeOBS = "obs" | |||||
| autoStopDuration = 4 * 60 * 60 | |||||
| storageTypeOBS = "obs" | |||||
| autoStopDuration = 4 * 60 * 60 | |||||
| autoStopDurationMs = 4 * 60 * 60 * 1000 | autoStopDurationMs = 4 * 60 * 60 * 1000 | ||||
| DataSetMountPath = "/home/ma-user/work" | DataSetMountPath = "/home/ma-user/work" | ||||
| @@ -63,6 +64,7 @@ const ( | |||||
| var ( | var ( | ||||
| poolInfos *models.PoolInfos | poolInfos *models.PoolInfos | ||||
| FlavorInfos *models.FlavorInfos | FlavorInfos *models.FlavorInfos | ||||
| ImageInfos *models.ImageInfosModelArts | |||||
| ) | ) | ||||
| type GenerateTrainJobReq struct { | type GenerateTrainJobReq struct { | ||||
| @@ -263,31 +265,38 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin | |||||
| return nil | return nil | ||||
| } | } | ||||
| func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor string) error { | |||||
| func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor, imageId string) error { | |||||
| if poolInfos == nil { | if poolInfos == nil { | ||||
| json.Unmarshal([]byte(setting.PoolInfos), &poolInfos) | json.Unmarshal([]byte(setting.PoolInfos), &poolInfos) | ||||
| } | } | ||||
| imageName, err := GetNotebookImageName(imageId) | |||||
| if err != nil { | |||||
| log.Error("GetNotebookImageName failed: %v", err.Error()) | |||||
| return err | |||||
| } | |||||
| jobResult, err := createNotebook2(models.CreateNotebook2Params{ | jobResult, err := createNotebook2(models.CreateNotebook2Params{ | ||||
| JobName: jobName, | JobName: jobName, | ||||
| Description: description, | Description: description, | ||||
| Flavor: flavor, | Flavor: flavor, | ||||
| Duration: autoStopDurationMs, | Duration: autoStopDurationMs, | ||||
| ImageID: "59a6e9f5-93c0-44dd-85b0-82f390c5d53a", | |||||
| ImageID: imageId, | |||||
| PoolID: poolInfos.PoolInfo[0].PoolId, | PoolID: poolInfos.PoolInfo[0].PoolId, | ||||
| Feature: models.NotebookFeature, | Feature: models.NotebookFeature, | ||||
| Volume: models.VolumeReq{ | |||||
| Capacity: 100, | |||||
| Category: models.EVSCategory, | |||||
| Ownership: models.ManagedOwnership, | |||||
| Volume: models.VolumeReq{ | |||||
| Capacity: setting.Capacity, | |||||
| Category: models.EVSCategory, | |||||
| Ownership: models.ManagedOwnership, | |||||
| }, | }, | ||||
| WorkspaceID: "0", | |||||
| WorkspaceID: "0", | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("createNotebook2 failed: %v", err.Error()) | log.Error("createNotebook2 failed: %v", err.Error()) | ||||
| return err | return err | ||||
| } | } | ||||
| err = models.CreateCloudbrain(&models.Cloudbrain{ | err = models.CreateCloudbrain(&models.Cloudbrain{ | ||||
| Status: string(models.JobWaiting), | |||||
| Status: jobResult.Status, | |||||
| UserID: ctx.User.ID, | UserID: ctx.User.ID, | ||||
| RepoID: ctx.Repo.Repository.ID, | RepoID: ctx.Repo.Repository.ID, | ||||
| JobID: jobResult.ID, | JobID: jobResult.ID, | ||||
| @@ -296,6 +305,7 @@ func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor | |||||
| Type: models.TypeCloudBrainTwo, | Type: models.TypeCloudBrainTwo, | ||||
| Uuid: uuid, | Uuid: uuid, | ||||
| ComputeResource: models.NPUResource, | ComputeResource: models.NPUResource, | ||||
| Image: imageName, | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -598,3 +608,26 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e | |||||
| return nil | return nil | ||||
| } | } | ||||
| func GetNotebookImageName(imageId string) (string, error) { | |||||
| var validImage = false | |||||
| var imageName = "" | |||||
| if ImageInfos == nil { | |||||
| json.Unmarshal([]byte(setting.ImageInfos), &ImageInfos) | |||||
| } | |||||
| for _, imageInfo := range ImageInfos.ImageInfo { | |||||
| if imageInfo.Id == imageId { | |||||
| validImage = true | |||||
| imageName = imageInfo.Value | |||||
| } | |||||
| } | |||||
| if !validImage { | |||||
| log.Error("the image id(%s) is invalid", imageId) | |||||
| return imageName, errors.New("the image id is invalid") | |||||
| } | |||||
| return imageName, nil | |||||
| } | |||||
| @@ -513,6 +513,8 @@ var ( | |||||
| PoolInfos string | PoolInfos string | ||||
| Flavor string | Flavor string | ||||
| DebugHost string | DebugHost string | ||||
| ImageInfos string | |||||
| Capacity int | |||||
| //train-job | //train-job | ||||
| ResourcePools string | ResourcePools string | ||||
| Engines string | Engines string | ||||
| @@ -1326,7 +1328,8 @@ func NewContext() { | |||||
| ProfileID = sec.Key("PROFILE_ID").MustString("") | ProfileID = sec.Key("PROFILE_ID").MustString("") | ||||
| PoolInfos = sec.Key("POOL_INFOS").MustString("") | PoolInfos = sec.Key("POOL_INFOS").MustString("") | ||||
| Flavor = sec.Key("FLAVOR").MustString("") | Flavor = sec.Key("FLAVOR").MustString("") | ||||
| DebugHost = sec.Key("DEBUG_SERVER_HOST").MustString("http://192.168.202.73") | |||||
| ImageInfos = sec.Key("IMAGE_INFOS").MustString("") | |||||
| Capacity = sec.Key("IMAGE_INFOS").MustInt(100) | |||||
| ResourcePools = sec.Key("Resource_Pools").MustString("") | ResourcePools = sec.Key("Resource_Pools").MustString("") | ||||
| Engines = sec.Key("Engines").MustString("") | Engines = sec.Key("Engines").MustString("") | ||||
| EngineVersions = sec.Key("Engine_Versions").MustString("") | EngineVersions = sec.Key("Engine_Versions").MustString("") | ||||
| @@ -103,8 +103,13 @@ func MustEnableModelArts(ctx *context.Context) { | |||||
| } | } | ||||
| func NotebookNew(ctx *context.Context) { | func NotebookNew(ctx *context.Context) { | ||||
| ctx.Data["PageIsCloudBrain"] = true | |||||
| notebookNewDataPrepare(ctx) | |||||
| ctx.HTML(200, tplModelArtsNotebookNew) | |||||
| } | |||||
| func notebookNewDataPrepare(ctx *context.Context) error { | |||||
| ctx.Data["PageIsCloudBrain"] = true | |||||
| t := time.Now() | t := time.Now() | ||||
| var jobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | var jobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | ||||
| ctx.Data["job_name"] = jobName | ctx.Data["job_name"] = jobName | ||||
| @@ -112,26 +117,14 @@ func NotebookNew(ctx *context.Context) { | |||||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.ServerError("GetAllUserAttachments failed:", err) | ctx.ServerError("GetAllUserAttachments failed:", err) | ||||
| return | |||||
| return err | |||||
| } | } | ||||
| ctx.Data["attachments"] = attachs | ctx.Data["attachments"] = attachs | ||||
| ctx.Data["dataset_path"] = modelarts.DataSetMountPath | |||||
| ctx.Data["env"] = modelarts.NotebookEnv | |||||
| ctx.Data["notebook_type"] = modelarts.NotebookType | |||||
| if modelarts.FlavorInfos == nil { | |||||
| json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) | |||||
| } | |||||
| ctx.Data["flavors"] = modelarts.FlavorInfos.FlavorInfo | |||||
| ctx.HTML(200, tplModelArtsNotebookNew) | |||||
| } | |||||
| func notebookNewDataPrepare(ctx *context.Context) error { | |||||
| ctx.Data["PageIsCloudBrain"] = true | |||||
| t := time.Now() | |||||
| var jobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||||
| ctx.Data["job_name"] = jobName | |||||
| if modelarts.ImageInfos == nil { | |||||
| json.Unmarshal([]byte(setting.ImageInfos), &modelarts.ImageInfos) | |||||
| } | |||||
| ctx.Data["images"] = modelarts.ImageInfos.ImageInfo | |||||
| if modelarts.FlavorInfos == nil { | if modelarts.FlavorInfos == nil { | ||||
| json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) | json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) | ||||
| @@ -191,8 +184,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||||
| uuid := form.Attachment | uuid := form.Attachment | ||||
| description := form.Description | description := form.Description | ||||
| flavor := form.Flavor | flavor := form.Flavor | ||||
| flavor = "modelarts.bm.910.arm.public.1" | |||||
| imageId := form.ImageId | |||||
| count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -223,7 +215,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||||
| } | } | ||||
| } | } | ||||
| err = modelarts.GenerateNotebook2(ctx, jobName, uuid, description, flavor) | |||||
| err = modelarts.GenerateNotebook2(ctx, jobName, uuid, description, flavor, imageId) | |||||
| if err != nil { | if err != nil { | ||||
| log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) | log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) | ||||
| notebookNewDataPrepare(ctx) | notebookNewDataPrepare(ctx) | ||||
| @@ -51,7 +51,16 @@ | |||||
| <input name="job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.job_name}}" tabindex="3" autofocus required maxlength="255" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | <input name="job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.job_name}}" tabindex="3" autofocus required maxlength="255" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | ||||
| </div> | </div> | ||||
| <!-- <div class="inline field"> | |||||
| <div class="inline required field"> | |||||
| <label>镜像</label> | |||||
| <select id="cloudbrain_image" class="ui search dropdown" placeholder="选择镜像" style='width:385px' name="image_id"> | |||||
| {{range .images}} | |||||
| <option name="image_id" value="{{.Id}}">{{.Value}}</option> | |||||
| {{end}} | |||||
| </select> | |||||
| </div> | |||||
| <div class="inline field"> | |||||
| <label>数据集</label> | <label>数据集</label> | ||||
| <input type="text" list="cloudbrain_dataset" placeholder="选择数据集" name="" id="answerInput" autofocus maxlength="36"> | <input type="text" list="cloudbrain_dataset" placeholder="选择数据集" name="" id="answerInput" autofocus maxlength="36"> | ||||
| <datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment"> | <datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment"> | ||||
| @@ -62,7 +71,7 @@ | |||||
| <input type="hidden" name="attachment" id="answerInput-hidden"> | <input type="hidden" name="attachment" id="answerInput-hidden"> | ||||
| </div> | </div> | ||||
| <div class="inline required field"> | |||||
| <!--<div class="inline required field"> | |||||
| <label>工作环境</label> | <label>工作环境</label> | ||||
| <input name="de" id="cloudbrain_de" value="{{.env}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | <input name="de" id="cloudbrain_de" value="{{.env}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | ||||
| </div> | </div> | ||||
| @@ -23,7 +23,18 @@ | |||||
| <div> | <div> | ||||
| <div class="ui yellow segment"> | <div class="ui yellow segment"> | ||||
| {{with .task}} | {{with .task}} | ||||
| <p>任务名称: {{.JobName}}</p> | |||||
| <table class="ui celled striped table"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td class="four wide"> 任务名称 </td> | |||||
| <td>{{.JobName}}</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td> 镜像名称 </td> | |||||
| <td>{{.Image}}</td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| {{end}} | {{end}} | ||||
| </div> | </div> | ||||
| <div class="ui green segment"> | <div class="ui green segment"> | ||||