| @@ -87,6 +87,8 @@ GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(fi | |||
| WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f) | |||
| WEBPACK_CONFIGS := webpack.config.js | |||
| WEBPACK_CONFIGS_TMP := webpack_temp.config.js | |||
| WEBPACK_CONFIGS_PRO := webpack_pro.config.js | |||
| WEBPACK_DEST := public/js/index.js public/css/index.css | |||
| WEBPACK_DEST_DIRS := public/js public/css public/fonts | |||
| @@ -290,7 +292,7 @@ lint-backend: golangci-lint revive vet swagger-check swagger-validate test-vendo | |||
| .PHONY: lint-frontend | |||
| lint-frontend: node_modules | |||
| npx eslint web_src/js webpack.config.js | |||
| npx eslint web_src/js $(WEBPACK_CONFIGS) | |||
| npx stylelint web_src/less | |||
| .PHONY: watch-frontend | |||
| @@ -504,7 +506,7 @@ install: $(wildcard *.go) | |||
| build: frontend backend | |||
| .PHONY: frontend | |||
| frontend: node-check $(FOMANTIC_DEST) $(WEBPACK_DEST) | |||
| frontend: node-check webpack_prepare $(FOMANTIC_DEST) $(WEBPACK_DEST) webpack_end | |||
| .PHONY: backend | |||
| backend: go-check generate $(EXECUTABLE) | |||
| @@ -596,6 +598,19 @@ $(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules | |||
| .PHONY: webpack | |||
| webpack: $(WEBPACK_DEST) | |||
| webpack_prepare: | |||
| if [ $(filter bindata,$(TAGS_SPLIT))x = "bindata"x ]; then \ | |||
| echo "prepare"; \ | |||
| cp $(WEBPACK_CONFIGS) $(WEBPACK_CONFIGS_TMP); \ | |||
| cp $(WEBPACK_CONFIGS_PRO) $(WEBPACK_CONFIGS); \ | |||
| fi | |||
| webpack_end: | |||
| if [ $(filter bindata,$(TAGS_SPLIT))x = "bindata"x ]; then \ | |||
| echo "end"; \ | |||
| mv $(WEBPACK_CONFIGS_TMP) $(WEBPACK_CONFIGS); \ | |||
| fi | |||
| $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules | |||
| rm -rf $(WEBPACK_DEST_DIRS) | |||
| @@ -3,6 +3,7 @@ package models | |||
| import ( | |||
| "encoding/json" | |||
| "fmt" | |||
| "strconv" | |||
| "strings" | |||
| "time" | |||
| @@ -92,9 +93,10 @@ type Cloudbrain struct { | |||
| JobID string `xorm:"INDEX NOT NULL"` | |||
| JobType string `xorm:"INDEX NOT NULL DEFAULT 'DEBUG'"` | |||
| JobName string | |||
| DisplayJobName string | |||
| Status string | |||
| UserID int64 | |||
| RepoID int64 | |||
| UserID int64 `xorm:"INDEX NOT NULL"` | |||
| RepoID int64 `xorm:"INDEX NOT NULL"` | |||
| SubTaskName string | |||
| ContainerID string | |||
| ContainerIp string | |||
| @@ -1198,7 +1200,7 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { | |||
| ) | |||
| cloudbrains := make([]*CloudbrainInfo, 0) | |||
| if err := sess.Select("job_id,job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | |||
| if err := sess.Select("job_id,display_job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | |||
| Find(&cloudbrains); err != nil { | |||
| return nil, 0, fmt.Errorf("Find: %v", err) | |||
| } | |||
| @@ -1207,7 +1209,7 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { | |||
| uniqueElements := make([]*CloudbrainInfo, 0) | |||
| for _, entry := range cloudbrains { | |||
| if _, value := keys[entry.JobID]; !value { | |||
| keys[entry.JobID] = entry.JobName | |||
| keys[entry.JobID] = entry.DisplayJobName | |||
| uniqueElements = append(uniqueElements, entry) | |||
| } | |||
| } | |||
| @@ -1307,6 +1309,12 @@ func GetCloudbrainByJobID(jobID string) (*Cloudbrain, error) { | |||
| return getRepoCloudBrain(cb) | |||
| } | |||
| func GetCloudbrainByID(id string) (*Cloudbrain, error) { | |||
| idInt64, _ := strconv.ParseInt(id, 10, 64) | |||
| cb := &Cloudbrain{ID: idInt64} | |||
| return getRepoCloudBrain(cb) | |||
| } | |||
| func GetCloudbrainByJobIDAndVersionName(jobID string, versionName string) (*Cloudbrain, error) { | |||
| cb := &Cloudbrain{JobID: jobID, VersionName: versionName} | |||
| return getRepoCloudBrain(cb) | |||
| @@ -1329,6 +1337,12 @@ func GetCloudbrainsNeededStopByRepoID(repoID int64) ([]*Cloudbrain, error) { | |||
| return cloudBrains, err | |||
| } | |||
| func GetCloudbrainsByDisplayJobName(repoID int64, jobType string, displayJobName string) ([]*Cloudbrain, error) { | |||
| cloudBrains := make([]*Cloudbrain, 0) | |||
| err := x.Cols("job_id", "job_name", "repo_id", "user_id", "job_type", "display_job_name").Where("repo_id=? AND job_type =? AND lower(display_job_name) = lower(?)", repoID, jobType, displayJobName).Find(&cloudBrains) | |||
| return cloudBrains, err | |||
| } | |||
| func SetCloudbrainStatusByJobID(jobID string, status CloudbrainStatus) (err error) { | |||
| cb := &Cloudbrain{JobID: jobID, Status: string(status)} | |||
| _, err = x.Cols("status").Where("cloudbrain.job_id=?", jobID).Update(cb) | |||
| @@ -7,6 +7,7 @@ import ( | |||
| type CreateCloudBrainForm struct { | |||
| JobName string `form:"job_name" binding:"Required"` | |||
| DisplayJobName string `form:"display_job_name" binding:"Required"` | |||
| Image string `form:"image" binding:"Required"` | |||
| Command string `form:"command" binding:"Required"` | |||
| Attachment string `form:"attachment" binding:"Required"` | |||
| @@ -16,11 +16,12 @@ func (f *CreateModelArtsForm) Validate(ctx *macaron.Context, errs binding.Errors | |||
| } | |||
| type CreateModelArtsNotebookForm struct { | |||
| JobName string `form:"job_name" binding:"Required"` | |||
| Attachment string `form:"attachment"` | |||
| Description string `form:"description"` | |||
| Flavor string `form:"flavor" binding:"Required"` | |||
| ImageId string `form:"image_id" binding:"Required"` | |||
| DisplayJobName string `form:"display_job_name" binding:"Required"` | |||
| JobName string `form:"job_name" binding:"Required"` | |||
| Attachment string `form:"attachment"` | |||
| Description string `form:"description"` | |||
| 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 { | |||
| @@ -28,6 +29,7 @@ func (f *CreateModelArtsNotebookForm) Validate(ctx *macaron.Context, errs bindin | |||
| } | |||
| type CreateModelArtsTrainJobForm struct { | |||
| DisplayJobName string `form:"display_job_name" binding:"Required"` | |||
| JobName string `form:"job_name" binding:"Required"` | |||
| Attachment string `form:"attachment" binding:"Required"` | |||
| BootFile string `form:"boot_file" binding:"Required"` | |||
| @@ -47,6 +49,7 @@ type CreateModelArtsTrainJobForm struct { | |||
| } | |||
| type CreateModelArtsInferenceJobForm struct { | |||
| DisplayJobName string `form:"display_job_name" binding:"Required"` | |||
| JobName string `form:"job_name" binding:"Required"` | |||
| Attachment string `form:"attachment" binding:"Required"` | |||
| BootFile string `form:"boot_file" binding:"Required"` | |||
| @@ -85,30 +85,69 @@ func isAdminOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error | |||
| func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var ID = ctx.Params(":id") | |||
| job, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByID failed:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| ctx.Cloudbrain = job | |||
| if !isAdminOrOwnerOrJobCreater(ctx, job, err) { | |||
| log.Error("!isAdminOrOwnerOrJobCreater error:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| } | |||
| func AdminOrJobCreaterRight(ctx *context.Context) { | |||
| var ID = ctx.Params(":id") | |||
| job, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByID failed:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| ctx.Cloudbrain = job | |||
| if !isAdminOrJobCreater(ctx, job, err) { | |||
| log.Error("!isAdminOrJobCreater error:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| } | |||
| func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| job, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID failed:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| ctx.Cloudbrain = job | |||
| if !isAdminOrOwnerOrJobCreater(ctx, job, err) { | |||
| log.Error("!isAdminOrOwnerOrJobCreater failed:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| } | |||
| func AdminOrJobCreaterRight(ctx *context.Context) { | |||
| func AdminOrJobCreaterRightForTrain(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| job, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID failed:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| ctx.Cloudbrain = job | |||
| if !isAdminOrJobCreater(ctx, job, err) { | |||
| log.Error("!isAdminOrJobCreater errot:%v", err.Error()) | |||
| ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | |||
| } | |||
| } | |||
| func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||
| func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||
| dataActualPath := setting.Attachment.Minio.RealPath + | |||
| setting.Attachment.Minio.Bucket + "/" + | |||
| setting.Attachment.Minio.BasePath + | |||
| @@ -212,6 +251,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobID, | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| SubTaskName: SubTaskName, | |||
| JobType: jobType, | |||
| Type: models.TypeCloudBrainOne, | |||
| @@ -229,16 +269,23 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||
| return err | |||
| } | |||
| task, err := models.GetCloudbrainByName(jobName) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByName failed: %v", err.Error()) | |||
| return err | |||
| } | |||
| stringId := strconv.FormatInt(task.ID, 10) | |||
| if string(models.JobTypeBenchmark) == jobType { | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, jobName, models.ActionCreateBenchMarkTask) | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateBenchMarkTask) | |||
| } else { | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, jobName, models.ActionCreateDebugGPUTask) | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugGPUTask) | |||
| } | |||
| return nil | |||
| } | |||
| func RestartTask(ctx *context.Context, task *models.Cloudbrain, newJobID *string) error { | |||
| func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) error { | |||
| dataActualPath := setting.Attachment.Minio.RealPath + | |||
| setting.Attachment.Minio.Bucket + "/" + | |||
| setting.Attachment.Minio.BasePath + | |||
| @@ -343,6 +390,7 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newJobID *string | |||
| RepoID: task.RepoID, | |||
| JobID: jobID, | |||
| JobName: task.JobName, | |||
| DisplayJobName: task.DisplayJobName, | |||
| SubTaskName: task.SubTaskName, | |||
| JobType: task.JobType, | |||
| Type: task.Type, | |||
| @@ -359,7 +407,8 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newJobID *string | |||
| return err | |||
| } | |||
| *newJobID = jobID | |||
| idString := strconv.FormatInt(newTask.ID, 10) | |||
| *newID = idString | |||
| return nil | |||
| } | |||
| @@ -70,6 +70,7 @@ var ( | |||
| type GenerateTrainJobReq struct { | |||
| JobName string | |||
| DisplayJobName string | |||
| Uuid string | |||
| Description string | |||
| CodeObsPath string | |||
| @@ -95,33 +96,9 @@ type GenerateTrainJobReq struct { | |||
| TotalVersionCount int | |||
| } | |||
| type GenerateTrainJobVersionReq struct { | |||
| JobName string | |||
| Uuid string | |||
| Description string | |||
| CodeObsPath string | |||
| BootFile string | |||
| BootFileUrl string | |||
| DataUrl string | |||
| TrainUrl string | |||
| FlavorCode string | |||
| LogUrl string | |||
| PoolID string | |||
| WorkServerNumber int | |||
| EngineID int64 | |||
| Parameters []models.Parameter | |||
| Params string | |||
| PreVersionId int64 | |||
| CommitID string | |||
| BranchName string | |||
| FlavorName string | |||
| EngineName string | |||
| PreVersionName string | |||
| TotalVersionCount int | |||
| } | |||
| type GenerateInferenceJobReq struct { | |||
| JobName string | |||
| DisplayJobName string | |||
| Uuid string | |||
| Description string | |||
| CodeObsPath string | |||
| @@ -266,7 +243,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin | |||
| return nil | |||
| } | |||
| func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor, imageId string) error { | |||
| func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, flavor, imageId string) error { | |||
| if poolInfos == nil { | |||
| json.Unmarshal([]byte(setting.PoolInfos), &poolInfos) | |||
| } | |||
| @@ -302,6 +279,7 @@ func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobResult.ID, | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| JobType: string(models.JobTypeDebug), | |||
| Type: models.TypeCloudBrainTwo, | |||
| Uuid: uuid, | |||
| @@ -313,7 +291,13 @@ func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor, | |||
| if err != nil { | |||
| return err | |||
| } | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobResult.ID, jobName, models.ActionCreateDebugNPUTask) | |||
| task, err := models.GetCloudbrainByName(jobName) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByName failed: %v", err.Error()) | |||
| return err | |||
| } | |||
| stringId := strconv.FormatInt(task.ID, 10) | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask) | |||
| return nil | |||
| } | |||
| @@ -354,6 +338,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobId, | |||
| JobName: req.JobName, | |||
| DisplayJobName: req.DisplayJobName, | |||
| JobType: string(models.JobTypeTrain), | |||
| Type: models.TypeCloudBrainTwo, | |||
| VersionID: jobResult.VersionID, | |||
| @@ -380,10 +365,10 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| }) | |||
| if err != nil { | |||
| log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error()) | |||
| log.Error("CreateCloudbrain(%s) failed:%v", req.DisplayJobName, err.Error()) | |||
| return err | |||
| } | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobId, req.JobName, models.ActionCreateTrainTask) | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobId, req.DisplayJobName, models.ActionCreateTrainTask) | |||
| return nil | |||
| } | |||
| @@ -438,6 +423,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: strconv.FormatInt(jobResult.JobID, 10), | |||
| JobName: req.JobName, | |||
| DisplayJobName: req.DisplayJobName, | |||
| JobType: string(models.JobTypeTrain), | |||
| Type: models.TypeCloudBrainTwo, | |||
| VersionID: jobResult.VersionID, | |||
| @@ -574,6 +560,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobID, | |||
| JobName: req.JobName, | |||
| DisplayJobName: req.DisplayJobName, | |||
| JobType: string(models.JobTypeInference), | |||
| Type: models.TypeCloudBrainTwo, | |||
| VersionID: jobResult.VersionID, | |||
| @@ -608,7 +595,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e | |||
| log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error()) | |||
| return err | |||
| } | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, req.JobName, models.ActionCreateInferenceTask) | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateInferenceTask) | |||
| return nil | |||
| } | |||
| @@ -6,8 +6,10 @@ package util | |||
| import ( | |||
| "bytes" | |||
| "math/rand" | |||
| "strconv" | |||
| "strings" | |||
| "time" | |||
| ) | |||
| // OptionalBool a boolean that can be "null" | |||
| @@ -110,3 +112,16 @@ func AddZero(t int64) (m string) { | |||
| return strconv.FormatInt(t, 10) | |||
| } | |||
| } | |||
| func ConvertDisplayJobNameToJobName(DisplayName string) (JobName string) { | |||
| t := time.Now() | |||
| JobName = "openi" + strings.ToLower(cutNameString(DisplayName, 15)) + "t" + t.Format("20060102150405")[4:] + strconv.Itoa(int(rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100000))) | |||
| return JobName | |||
| } | |||
| func cutNameString(str string, lens int) string { | |||
| if len(str) < lens { | |||
| return str | |||
| } | |||
| return str[:lens] | |||
| } | |||
| @@ -850,6 +850,8 @@ model_rename=Duplicate model name, please modify model name. | |||
| debug=Debug | |||
| stop=Stop | |||
| delete=Delete | |||
| more=More | |||
| gpu_type_all=All | |||
| model_download=Model Download | |||
| submit_image=Submit Image | |||
| download=Download | |||
| @@ -879,6 +881,8 @@ cloudbrain_status_createtime = Status/Createtime | |||
| cloudbrain_status_runtime = Running Time | |||
| cloudbrain_jobname_err=Name must start with a lowercase letter or number,can include lowercase letter,number,_ and -,can not end with _, and can be up to 36 characters long. | |||
| cloudbrain_query_fail=Failed to query cloudbrain information. | |||
| cloudbrain.mirror_tag = Mirror Tag | |||
| cloudbrain.mirror_description = Mirror Description | |||
| record_begintime_get_err=Can not get the record begin time. | |||
| parameter_is_wrong=The input parameter is wrong. | |||
| @@ -2796,3 +2800,20 @@ foot.help = help | |||
| foot.copyright= Copyright: New Generation Artificial Intelligence Open Source Open Platform (OpenI) | |||
| Platform_Tutorial = Tutorial | |||
| foot.advice_feedback = Feedback | |||
| [cloudbrain] | |||
| compute_resource = Computing resources | |||
| task_name = Task name | |||
| task_type = Task type | |||
| gpu_type = GPU type | |||
| mirror = Mirror | |||
| dataset = Dataset | |||
| resource_specification = Resource specification | |||
| dataset_storage_path = Dataset storage path | |||
| model_storage_path = Model storage path | |||
| code_storage_path = Code storage path | |||
| benchmark_path = Benchmark script path | |||
| snn4imagenet_path = Snn4imagenet script path | |||
| brainscore_path = Brainscore script path | |||
| start_command = Start command | |||
| choose_mirror = select mirror | |||
| @@ -855,6 +855,8 @@ debug=调试 | |||
| debug_again=再次调试 | |||
| stop=停止 | |||
| delete=删除 | |||
| more=更多 | |||
| gpu_type_all=全部 | |||
| model_download=结果下载 | |||
| submit_image=提交镜像 | |||
| download=模型下载 | |||
| @@ -883,6 +885,8 @@ cloudbrain_status_createtime=状态/创建时间 | |||
| cloudbrain_status_runtime = 运行时长 | |||
| cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。 | |||
| cloudbrain_query_fail=查询云脑任务失败。 | |||
| cloudbrain.mirror_tag = 镜像标签 | |||
| cloudbrain.mirror_description = 镜像描述 | |||
| record_begintime_get_err=无法获取统计开始时间。 | |||
| parameter_is_wrong=输入参数错误,请检查输入参数。 | |||
| @@ -2094,7 +2098,7 @@ team_permission_desc=权限 | |||
| team_unit_desc=允许访问项目单元 | |||
| team_unit_disabled=(已禁用) | |||
| selected_couse=精选课程 | |||
| release_course = 发布课程 | |||
| release_course = 发布课程 | |||
| all_keywords=全部关键字 | |||
| all_org_topics=全部 | |||
| max_selectedPro= 最多可选9个公开项目 | |||
| @@ -2105,7 +2109,7 @@ select_again = 选择超过9个,请重新选择! | |||
| custom_select_projects = 自定义精选项目 | |||
| customize = 自定义 | |||
| selected_project=精选项目 | |||
| fold = 折叠 | |||
| fold = 收起 | |||
| unfold = 展开 | |||
| form.name_reserved=组织名称 '%s' 是被保留的。 | |||
| @@ -2804,3 +2808,20 @@ foot.help=帮助 | |||
| foot.copyright= 版权所有:新一代人工智能开源开放平台(OpenI) | |||
| Platform_Tutorial=新手指引 | |||
| foot.advice_feedback = 意见反馈 | |||
| [cloudbrain] | |||
| compute_resource = 计算资源 | |||
| task_name = 任务名称 | |||
| task_type = 任务类型 | |||
| gpu_type = GPU类型 | |||
| mirror = 镜像 | |||
| dataset = 数据集 | |||
| resource_specification = 资源规格 | |||
| dataset_storage_path = 数据集存放路径 | |||
| model_storage_path = 模型存放路径 | |||
| code_storage_path = 代码存放路径 | |||
| benchmark_path = benchmark脚本存放路径 | |||
| snn4imagenet_path = snn4imagenet脚本存放路径 | |||
| brainscore_path = brainscore脚本存放路径 | |||
| start_command = 启动命令 | |||
| choose_mirror = 选择镜像或输入镜像地址 | |||
| @@ -113,7 +113,7 @@ socket.onmessage = function (e) { | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>" | |||
| } | |||
| else if( record.OpType == "5"){ | |||
| else if(record.OpType == "5"){ | |||
| branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + encodeURI(record.RefName) + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||
| actionName = actionName.replace("{branch}",branch); | |||
| html += recordPrefix + actionName; | |||
| @@ -135,7 +135,11 @@ socket.onmessage = function (e) { | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
| } | |||
| else if(record.OpType == "24" || record.OpType == "25" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "29" || record.OpType == "30"){ | |||
| else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30"){ | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||
| } | |||
| else if(record.OpType == "25" || record.OpType == "29"){ | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||
| } | |||
| @@ -160,7 +164,7 @@ function getTaskLink(record){ | |||
| if(record.OpType == 24){ | |||
| re = re + "/datasets?type=" + record.Content; | |||
| }else if(record.OpType == 25){ | |||
| re = re + "/cloudbrain/" + record.RefName; | |||
| re = re + "/cloudbrain/" + record.Content; | |||
| }else if(record.OpType == 26){ | |||
| re = re + "/modelarts/notebook/" + record.Content; | |||
| }else if(record.OpType == 27){ | |||
| @@ -168,7 +172,7 @@ function getTaskLink(record){ | |||
| }else if(record.OpType == 28){ | |||
| re = re + "/modelarts/inference-job/" + record.Content; | |||
| }else if(record.OpType == 29){ | |||
| re = re + "/cloudbrain/benchmark/" + record.RefName; | |||
| re = re + "/cloudbrain/benchmark/" + record.Content; | |||
| }else if(record.OpType == 30){ | |||
| re = re + "/modelmanage/show_model_info?name=" + record.RefName; | |||
| } | |||
| @@ -179,7 +179,7 @@ func DownloadCloudBrains(ctx *context.Context) { | |||
| } | |||
| func allValues(row int, rs *models.CloudbrainInfo, ctx *context.Context) map[string]string { | |||
| return map[string]string{getCellName("A", row): rs.JobName, getCellName("B", row): rs.JobType, getCellName("C", row): rs.Status, getCellName("D", row): time.Unix(int64(rs.Cloudbrain.CreatedUnix), 0).Format(CREATE_TIME_FORMAT), getCellName("E", row): getDurationTime(rs), | |||
| return map[string]string{getCellName("A", row): rs.DisplayJobName, getCellName("B", row): rs.JobType, getCellName("C", row): rs.Status, getCellName("D", row): time.Unix(int64(rs.Cloudbrain.CreatedUnix), 0).Format(CREATE_TIME_FORMAT), getCellName("E", row): getDurationTime(rs), | |||
| getCellName("F", row): rs.ComputeResource, getCellName("G", row): rs.Name, getCellName("H", row): getRepoPathName(rs), getCellName("I", row): rs.JobName, | |||
| } | |||
| } | |||
| @@ -880,13 +880,13 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| }, reqAdmin()) | |||
| }, reqAnyRepoReader()) | |||
| m.Group("/cloudbrain", func() { | |||
| m.Get("/:jobid", repo.GetCloudbrainTask) | |||
| m.Get("/:jobname/log", repo.CloudbrainGetLog) | |||
| m.Get("/:id", repo.GetCloudbrainTask) | |||
| m.Get("/:id/log", repo.CloudbrainGetLog) | |||
| }, reqRepoReader(models.UnitTypeCloudBrain)) | |||
| m.Group("/modelarts", func() { | |||
| m.Group("/notebook", func() { | |||
| //m.Get("/:jobid", repo.GetModelArtsNotebook) | |||
| m.Get("/:jobid", repo.GetModelArtsNotebook2) | |||
| m.Get("/:id", repo.GetModelArtsNotebook2) | |||
| }) | |||
| m.Group("/train-job", func() { | |||
| m.Group("/:jobid", func() { | |||
| @@ -49,22 +49,23 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
| err error | |||
| ) | |||
| // jobName := ctx.Params(":jobname") | |||
| // job, err := models.GetCloudbrainByName(jobName) | |||
| jobID := ctx.Params(":jobid") | |||
| repoID := ctx.Repo.Repository.ID | |||
| job, err := models.GetRepoCloudBrainByJobID(repoID, jobID) | |||
| ID := ctx.Params(":id") | |||
| job, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| ctx.NotFound(err) | |||
| log.Error("GetCloudbrainByID failed:", err) | |||
| return | |||
| } | |||
| jobResult, err := cloudbrain.GetJob(job.JobID) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| log.Error("GetJob failed:", err) | |||
| return | |||
| } | |||
| result, err := models.ConvertToJobResultPayload(jobResult.Payload) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| log.Error("ConvertToJobResultPayload failed:", err) | |||
| return | |||
| } | |||
| @@ -86,7 +87,7 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| "JobID": result.Config.JobID, | |||
| "ID": ID, | |||
| "JobName": result.Config.JobName, | |||
| "JobStatus": result.JobStatus.State, | |||
| "SubState": result.JobStatus.SubState, | |||
| @@ -97,8 +98,8 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
| } | |||
| func CloudbrainGetLog(ctx *context.Context) { | |||
| jobName := ctx.Params(":jobname") | |||
| job, err := models.GetCloudbrainByName(jobName) | |||
| ID := ctx.Params(":id") | |||
| job, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"]) | |||
| ctx.ServerError(err.Error(), err) | |||
| @@ -145,7 +146,7 @@ func CloudbrainGetLog(ctx *context.Context) { | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| "JobName": jobName, | |||
| "JobName": job.JobName, | |||
| "Content": content, | |||
| }) | |||
| @@ -56,14 +56,13 @@ func GetModelArtsNotebook2(ctx *context.APIContext) { | |||
| err error | |||
| ) | |||
| jobID := ctx.Params(":jobid") | |||
| repoID := ctx.Repo.Repository.ID | |||
| job, err := models.GetRepoCloudBrainByJobID(repoID, jobID) | |||
| ID := ctx.Params(":id") | |||
| job, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| result, err := modelarts.GetNotebook2(jobID) | |||
| result, err := modelarts.GetNotebook2(job.JobID) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| return | |||
| @@ -76,7 +75,7 @@ func GetModelArtsNotebook2(ctx *context.APIContext) { | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| "JobID": jobID, | |||
| "ID": ID, | |||
| "JobName": job.JobName, | |||
| "JobStatus": result.Status, | |||
| }) | |||
| @@ -6,8 +6,13 @@ package events | |||
| import ( | |||
| "net/http" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/eventsource" | |||
| "code.gitea.io/gitea/modules/graceful" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/routers/user" | |||
| ) | |||
| // Events listens for events | |||
| @@ -22,86 +27,86 @@ func Events(ctx *context.Context) { | |||
| ctx.Resp.WriteHeader(http.StatusOK) | |||
| // Listen to connection close and un-register messageChan | |||
| // notify := ctx.Req.Context().Done() | |||
| // ctx.Resp.Flush() | |||
| notify := ctx.Req.Context().Done() | |||
| ctx.Resp.Flush() | |||
| // shutdownCtx := graceful.GetManager().ShutdownContext() | |||
| shutdownCtx := graceful.GetManager().ShutdownContext() | |||
| // uid := ctx.User.ID | |||
| uid := ctx.User.ID | |||
| // messageChan := eventsource.GetManager().Register(uid) | |||
| messageChan := eventsource.GetManager().Register(uid) | |||
| // unregister := func() { | |||
| // eventsource.GetManager().Unregister(uid, messageChan) | |||
| // // ensure the messageChan is closed | |||
| // for { | |||
| // _, ok := <-messageChan | |||
| // if !ok { | |||
| // break | |||
| // } | |||
| // } | |||
| // } | |||
| unregister := func() { | |||
| eventsource.GetManager().Unregister(uid, messageChan) | |||
| // ensure the messageChan is closed | |||
| for { | |||
| _, ok := <-messageChan | |||
| if !ok { | |||
| break | |||
| } | |||
| } | |||
| } | |||
| // if _, err := ctx.Resp.Write([]byte("\n")); err != nil { | |||
| // log.Error("Unable to write to EventStream: %v", err) | |||
| // unregister() | |||
| // return | |||
| // } | |||
| if _, err := ctx.Resp.Write([]byte("\n")); err != nil { | |||
| log.Error("Unable to write to EventStream: %v", err) | |||
| unregister() | |||
| return | |||
| } | |||
| // timer := time.NewTicker(30 * time.Second) | |||
| timer := time.NewTicker(30 * time.Second) | |||
| // loop: | |||
| // for { | |||
| // select { | |||
| // case <-timer.C: | |||
| // event := &eventsource.Event{ | |||
| // Name: "ping", | |||
| // } | |||
| // _, err := event.WriteTo(ctx.Resp) | |||
| // if err != nil { | |||
| // log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err) | |||
| // go unregister() | |||
| // break loop | |||
| // } | |||
| // ctx.Resp.Flush() | |||
| // case <-notify: | |||
| // go unregister() | |||
| // break loop | |||
| // case <-shutdownCtx.Done(): | |||
| // go unregister() | |||
| // break loop | |||
| // case event, ok := <-messageChan: | |||
| // if !ok { | |||
| // break loop | |||
| // } | |||
| loop: | |||
| for { | |||
| select { | |||
| case <-timer.C: | |||
| event := &eventsource.Event{ | |||
| Name: "ping", | |||
| } | |||
| _, err := event.WriteTo(ctx.Resp) | |||
| if err != nil { | |||
| log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err) | |||
| go unregister() | |||
| break loop | |||
| } | |||
| ctx.Resp.Flush() | |||
| case <-notify: | |||
| go unregister() | |||
| break loop | |||
| case <-shutdownCtx.Done(): | |||
| go unregister() | |||
| break loop | |||
| case event, ok := <-messageChan: | |||
| if !ok { | |||
| break loop | |||
| } | |||
| // // Handle logout | |||
| // if event.Name == "logout" { | |||
| // if ctx.Session.ID() == event.Data { | |||
| // _, _ = (&eventsource.Event{ | |||
| // Name: "logout", | |||
| // Data: "here", | |||
| // }).WriteTo(ctx.Resp) | |||
| // ctx.Resp.Flush() | |||
| // go unregister() | |||
| // user.HandleSignOut(ctx) | |||
| // break loop | |||
| // } | |||
| // // Replace the event - we don't want to expose the session ID to the user | |||
| // event = (&eventsource.Event{ | |||
| // Name: "logout", | |||
| // Data: "elsewhere", | |||
| // }) | |||
| // } | |||
| // Handle logout | |||
| if event.Name == "logout" { | |||
| if ctx.Session.ID() == event.Data { | |||
| _, _ = (&eventsource.Event{ | |||
| Name: "logout", | |||
| Data: "here", | |||
| }).WriteTo(ctx.Resp) | |||
| ctx.Resp.Flush() | |||
| go unregister() | |||
| user.HandleSignOut(ctx) | |||
| break loop | |||
| } | |||
| // Replace the event - we don't want to expose the session ID to the user | |||
| event = (&eventsource.Event{ | |||
| Name: "logout", | |||
| Data: "elsewhere", | |||
| }) | |||
| } | |||
| // _, err := event.WriteTo(ctx.Resp) | |||
| // if err != nil { | |||
| // log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err) | |||
| // go unregister() | |||
| // break loop | |||
| // } | |||
| // ctx.Resp.Flush() | |||
| // } | |||
| // } | |||
| // timer.Stop() | |||
| _, err := event.WriteTo(ctx.Resp) | |||
| if err != nil { | |||
| log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err) | |||
| go unregister() | |||
| break loop | |||
| } | |||
| ctx.Resp.Flush() | |||
| } | |||
| } | |||
| timer.Stop() | |||
| } | |||
| @@ -416,6 +416,10 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) { | |||
| copy(updates[1:], updates) | |||
| updates[0] = &option | |||
| } | |||
| if err := updateRepoCommitCnt(ctx, repo); err != nil { | |||
| log.Error("updateRepoCommitCnt failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| } | |||
| } | |||
| } | |||
| @@ -521,10 +525,6 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) { | |||
| } | |||
| } | |||
| if err := updateRepoCommitCnt(ctx, repo); err != nil { | |||
| log.Error("updateRepoCommitCnt failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| } | |||
| ctx.JSON(http.StatusOK, private.HookPostReceiveResult{ | |||
| Results: results, | |||
| RepoWasEmpty: wasEmpty, | |||
| @@ -512,7 +512,12 @@ func GetSuccessChunks(ctx *context.Context) { | |||
| return | |||
| } | |||
| } else { | |||
| isExist, err = storage.ObsHasObject(setting.BasePath + models.AttachmentRelativePath(fileChunk.UUID) + "/" + fileName) | |||
| oldFileName := fileName | |||
| oldAttachment, _ := models.GetAttachmentByUUID(fileChunk.UUID) | |||
| if oldAttachment != nil { | |||
| oldFileName = oldAttachment.Name | |||
| } | |||
| isExist, err = storage.ObsHasObject(setting.BasePath + models.AttachmentRelativePath(fileChunk.UUID) + "/" + oldFileName) | |||
| if err != nil { | |||
| ctx.ServerError("ObsHasObject failed", err) | |||
| return | |||
| @@ -76,8 +76,8 @@ func jobNamePrefixValid(s string) string { | |||
| func cloudBrainNewDataPrepare(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 | |||
| var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = displayJobName | |||
| result, err := cloudbrain.GetImages() | |||
| if err != nil { | |||
| @@ -176,7 +176,8 @@ func CloudBrainNew(ctx *context.Context) { | |||
| func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| jobName := form.JobName | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| image := form.Image | |||
| uuid := form.Attachment | |||
| jobType := form.JobType | |||
| @@ -184,8 +185,26 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| gpuQueue := form.GpuType | |||
| codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath | |||
| resourceSpecId := form.ResourceSpecId | |||
| repo := ctx.Repo.Repository | |||
| if !jobNamePattern.MatchString(jobName) { | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplCloudBrainNew, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
| return | |||
| } | |||
| } | |||
| if !jobNamePattern.MatchString(displayJobName) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainNew, &form) | |||
| return | |||
| } | |||
| @@ -212,21 +231,6 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| } | |||
| } | |||
| _, err = models.GetCloudbrainByName(jobName) | |||
| if err == nil { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplCloudBrainNew, &form) | |||
| return | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
| return | |||
| } | |||
| } | |||
| repo := ctx.Repo.Repository | |||
| downloadCode(repo, codePath) | |||
| uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") | |||
| @@ -258,7 +262,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/") | |||
| } | |||
| err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, | |||
| @@ -273,11 +277,10 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| } | |||
| func CloudBrainRestart(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var ID = ctx.Params(":id") | |||
| var resultCode = "0" | |||
| var errorMsg = "" | |||
| var status = string(models.JobWaiting) | |||
| task := ctx.Cloudbrain | |||
| for { | |||
| if task.Status != string(models.JobStopped) && task.Status != string(models.JobSucceeded) && task.Status != string(models.JobFailed) { | |||
| @@ -316,7 +319,7 @@ func CloudBrainRestart(ctx *context.Context) { | |||
| } | |||
| } | |||
| err = cloudbrain.RestartTask(ctx, task, &jobID) | |||
| err = cloudbrain.RestartTask(ctx, task, &ID) | |||
| if err != nil { | |||
| log.Error("RestartTask failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| @@ -331,7 +334,7 @@ func CloudBrainRestart(ctx *context.Context) { | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "job_id": jobID, | |||
| "id": ID, | |||
| }) | |||
| } | |||
| @@ -352,14 +355,16 @@ func CloudBrainShow(ctx *context.Context) { | |||
| func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| var jobName = ctx.Params(":jobname") | |||
| var ID = ctx.Params(":id") | |||
| debugListType := ctx.Query("debugListType") | |||
| task, err := models.GetCloudbrainByName(jobName) | |||
| task, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| log.Info("error:" + err.Error()) | |||
| ctx.Data["error"] = err.Error() | |||
| } | |||
| result, err := cloudbrain.GetJob(task.JobID) | |||
| if err != nil { | |||
| log.Info("error:" + err.Error()) | |||
| ctx.Data["error"] = err.Error() | |||
| } | |||
| if result != nil { | |||
| @@ -423,8 +428,8 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| ctx.Data["duration"] = util.AddZero(duration/3600000) + ":" + util.AddZero(duration%3600000/60000) + ":" + util.AddZero(duration%60000/1000) | |||
| ctx.Data["task"] = task | |||
| // ctx.Data["jobID"] = task.JobID | |||
| ctx.Data["jobName"] = task.JobName | |||
| ctx.Data["displayJobName"] = task.DisplayJobName | |||
| version_list_task := make([]*models.Cloudbrain, 0) | |||
| version_list_task = append(version_list_task, task) | |||
| ctx.Data["version_list_task"] = version_list_task | |||
| @@ -433,7 +438,8 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| } | |||
| func CloudBrainDebug(ctx *context.Context) { | |||
| debugUrl := setting.DebugServerHost + "jpylab_" + ctx.Cloudbrain.JobID + "_" + ctx.Cloudbrain.SubTaskName | |||
| task := ctx.Cloudbrain | |||
| debugUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName | |||
| ctx.Redirect(debugUrl) | |||
| } | |||
| @@ -460,7 +466,7 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain | |||
| } | |||
| func CloudBrainStop(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var ID = ctx.Params(":id") | |||
| var resultCode = "0" | |||
| var errorMsg = "" | |||
| var status = "" | |||
| @@ -474,7 +480,7 @@ func CloudBrainStop(ctx *context.Context) { | |||
| break | |||
| } | |||
| err := cloudbrain.StopJob(jobID) | |||
| err := cloudbrain.StopJob(task.JobID) | |||
| if err != nil { | |||
| log.Error("StopJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||
| resultCode = "-1" | |||
| @@ -499,7 +505,7 @@ func CloudBrainStop(ctx *context.Context) { | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "job_id": jobID, | |||
| "id": ID, | |||
| }) | |||
| } | |||
| @@ -621,10 +627,10 @@ func deleteCloudbrainJob(ctx *context.Context) error { | |||
| func CloudBrainShowModels(ctx *context.Context) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| jobID := ctx.Params(":jobid") | |||
| ID := ctx.Params(":id") | |||
| parentDir := ctx.Query("parentDir") | |||
| dirArray := strings.Split(parentDir, "/") | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| task, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| log.Error("no such job!", ctx.Data["msgID"]) | |||
| ctx.ServerError("no such job:", err) | |||
| @@ -659,7 +665,7 @@ func CloudBrainShowModels(ctx *context.Context) { | |||
| ctx.Data["Path"] = dirArray | |||
| ctx.Data["Dirs"] = fileInfos | |||
| ctx.Data["task"] = task | |||
| ctx.Data["JobID"] = jobID | |||
| ctx.Data["ID"] = ID | |||
| ctx.HTML(200, tplCloudBrainShowModels) | |||
| } | |||
| @@ -728,8 +734,8 @@ func GetRate(ctx *context.Context) { | |||
| return | |||
| } | |||
| var jobID = ctx.Params(":jobid") | |||
| job, err := models.GetCloudbrainByJobID(jobID) | |||
| var ID = ctx.Params(":id") | |||
| job, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetCloudbrainByJobID failed", err) | |||
| return | |||
| @@ -1220,7 +1226,8 @@ func getBenchmarkResourceSpec(resourceSpecID int) (int, error) { | |||
| func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| jobName := form.JobName | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| image := form.Image | |||
| gpuQueue := form.GpuType | |||
| command := cloudbrain.CommandBenchmark | |||
| @@ -1232,6 +1239,26 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
| ctx.Data["description"] = form.Description | |||
| ctx.Data["benchmarkTypeID"] = benchmarkTypeID | |||
| ctx.Data["benchmark_child_types_id_hidden"] = benchmarkChildTypeID | |||
| repo := ctx.Repo.Repository | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeBenchmark), displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplCloudBrainBenchmarkNew, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) | |||
| return | |||
| } | |||
| } | |||
| if !jobNamePattern.MatchString(jobName) { | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainBenchmarkNew, &form) | |||
| @@ -1277,21 +1304,6 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
| } | |||
| } | |||
| _, err = models.GetCloudbrainByName(jobName) | |||
| if err == nil { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplCloudBrainBenchmarkNew, &form) | |||
| return | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("GetCloudbrainByName failed, %v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) | |||
| return | |||
| } | |||
| } | |||
| repo := ctx.Repo.Repository | |||
| os.RemoveAll(codePath) | |||
| if err := downloadCode(repo, codePath); err != nil { | |||
| log.Error("downloadCode failed, %v", err, ctx.Data["MsgID"]) | |||
| @@ -1355,7 +1367,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
| //return | |||
| } | |||
| err = cloudbrain.GenerateTask(ctx, jobName, image, command, childInfo.Attachment, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, childInfo.Attachment, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, | |||
| @@ -25,6 +25,7 @@ import ( | |||
| "code.gitea.io/gitea/modules/obs" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| "code.gitea.io/gitea/modules/util" | |||
| ) | |||
| const ( | |||
| @@ -112,8 +113,8 @@ func NotebookNew(ctx *context.Context) { | |||
| 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 | |||
| var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = displayJobName | |||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| @@ -181,11 +182,13 @@ func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) | |||
| func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm) { | |||
| ctx.Data["PageIsNotebook"] = true | |||
| jobName := form.JobName | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| uuid := form.Attachment | |||
| description := form.Description | |||
| flavor := form.Flavor | |||
| imageId := form.ImageId | |||
| repo := ctx.Repo.Repository | |||
| count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| @@ -201,12 +204,15 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||
| return | |||
| } | |||
| } | |||
| _, err = models.GetCloudbrainByName(jobName) | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName) | |||
| if err == nil { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| notebookNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplModelArtsNotebookNew, &form) | |||
| return | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| notebookNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplModelArtsNotebookNew, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| @@ -216,7 +222,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||
| } | |||
| } | |||
| err = modelarts.GenerateNotebook2(ctx, jobName, uuid, description, flavor, imageId) | |||
| err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, flavor, imageId) | |||
| if err != nil { | |||
| log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) | |||
| notebookNewDataPrepare(ctx) | |||
| @@ -230,15 +236,15 @@ func NotebookShow(ctx *context.Context) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| debugListType := ctx.Query("debugListType") | |||
| var jobID = ctx.Params(":jobid") | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| var ID = ctx.Params(":id") | |||
| task, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookShow, nil) | |||
| return | |||
| } | |||
| result, err := modelarts.GetNotebook2(jobID) | |||
| result, err := modelarts.GetNotebook2(task.JobID) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookShow, nil) | |||
| @@ -270,7 +276,7 @@ func NotebookShow(ctx *context.Context) { | |||
| ctx.Data["datasetDownloadLink"] = datasetDownloadLink | |||
| ctx.Data["task"] = task | |||
| ctx.Data["jobID"] = jobID | |||
| ctx.Data["ID"] = ID | |||
| ctx.Data["jobName"] = task.JobName | |||
| ctx.Data["result"] = result | |||
| ctx.Data["debugListType"] = debugListType | |||
| @@ -305,9 +311,8 @@ func NotebookDebug(ctx *context.Context) { | |||
| } | |||
| func NotebookDebug2(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| result, err := modelarts.GetNotebook2(jobID) | |||
| task := ctx.Cloudbrain | |||
| result, err := modelarts.GetNotebook2(task.JobID) | |||
| if err != nil { | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil) | |||
| return | |||
| @@ -317,16 +322,16 @@ func NotebookDebug2(ctx *context.Context) { | |||
| } | |||
| func NotebookManage(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var ID = ctx.Params(":id") | |||
| var action = ctx.Params(":action") | |||
| var resultCode = "0" | |||
| var errorMsg = "" | |||
| var status = "" | |||
| for { | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| task, err := models.GetCloudbrainByID(ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID failed:%v", err, ctx.Data["MsgID"]) | |||
| log.Error("get task(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| @@ -391,7 +396,7 @@ func NotebookManage(ctx *context.Context) { | |||
| param := models.NotebookAction{ | |||
| Action: action, | |||
| } | |||
| res, err := modelarts.ManageNotebook2(jobID, param) | |||
| res, err := modelarts.ManageNotebook2(task.JobID, param) | |||
| if err != nil { | |||
| log.Error("ManageNotebook2(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| @@ -420,12 +425,11 @@ func NotebookManage(ctx *context.Context) { | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "job_id": jobID, | |||
| "id": ID, | |||
| }) | |||
| } | |||
| func NotebookDel(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var listType = ctx.Query("debugListType") | |||
| task := ctx.Cloudbrain | |||
| @@ -435,10 +439,10 @@ func NotebookDel(ctx *context.Context) { | |||
| return | |||
| } | |||
| _, err := modelarts.DelNotebook2(jobID) | |||
| _, err := modelarts.DelNotebook2(task.JobID) | |||
| if err != nil { | |||
| log.Error("DelNotebook2(%s) failed:%v", task.JobName, err.Error()) | |||
| if strings.Contains(err.Error(), modelarts.NotebookNotFound) || strings.Contains(err.Error(), modelarts.NotebookNoPermission) || strings.Contains(err.Error(), modelarts.NotebookInvalid){ | |||
| if strings.Contains(err.Error(), modelarts.NotebookNotFound) || strings.Contains(err.Error(), modelarts.NotebookNoPermission) || strings.Contains(err.Error(), modelarts.NotebookInvalid) { | |||
| log.Info("old notebook version") | |||
| } else { | |||
| ctx.RenderWithErr(err.Error(), tplDebugJobIndex, nil) | |||
| @@ -529,8 +533,8 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
| //} | |||
| t := time.Now() | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = jobName | |||
| var displayJobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = displayJobName | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| @@ -567,8 +571,6 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
| } | |||
| ctx.Data["flavor_infos"] = flavorInfos.Info | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||
| ctx.Data["train_url"] = outputObsPath | |||
| ctx.Data["params"] = "" | |||
| ctx.Data["branchName"] = ctx.Repo.BranchName | |||
| @@ -598,8 +600,8 @@ func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArts | |||
| //} | |||
| t := time.Now() | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = jobName | |||
| var displayJobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = displayJobName | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| @@ -636,9 +638,6 @@ func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArts | |||
| } | |||
| ctx.Data["flavor_infos"] = flavorInfos.Info | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||
| ctx.Data["train_url"] = outputObsPath | |||
| configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
| if err != nil { | |||
| ctx.ServerError("getConfigList failed:", err) | |||
| @@ -685,8 +684,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
| return err | |||
| } | |||
| t := time.Now() | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = task.DisplayJobName | |||
| ctx.Data["job_name"] = task.JobName | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| @@ -731,9 +729,6 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
| } | |||
| ctx.Data["params"] = Parameters.Parameter | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||
| ctx.Data["train_url"] = outputObsPath | |||
| branches, _, err := ctx.Repo.GitRepo.GetBranches(0, 0) | |||
| if err != nil { | |||
| ctx.ServerError("GetBranches error:", err) | |||
| @@ -854,7 +849,8 @@ func versionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrai | |||
| func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) { | |||
| ctx.Data["PageIsTrainJob"] = true | |||
| VersionOutputPath := modelarts.GetOutputPathByCount(modelarts.TotalVersionCount) | |||
| jobName := form.JobName | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| uuid := form.Attachment | |||
| description := form.Description | |||
| workServerNumber := form.WorkServerNumber | |||
| @@ -897,6 +893,23 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| //Determine whether the task name of the task in the project is duplicated | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeTrain), displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("the job name did already exist", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("system error", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| } | |||
| //todo: del the codeLocalPath | |||
| _, err = ioutil.ReadDir(codeLocalPath) | |||
| @@ -910,9 +923,9 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| if err := git.Clone(repo.RepoPath(), codeLocalPath, git.CloneRepoOptions{ | |||
| Branch: branch_name, | |||
| }); err != nil { | |||
| log.Error("创建任务失败,服务器超时!: %s (%v)", repo.FullName(), err) | |||
| log.Error("Create task failed, server timed out: %s (%v)", repo.FullName(), err) | |||
| trainJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("创建任务失败,服务器超时!", tplModelArtsTrainJobNew, &form) | |||
| ctx.RenderWithErr("Create task failed, server timed out", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1006,6 +1019,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| req := &modelarts.GenerateTrainJobReq{ | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| DataUrl: dataPath, | |||
| Description: description, | |||
| CodeObsPath: codeObsPath, | |||
| @@ -1072,6 +1086,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| } | |||
| VersionOutputPath := modelarts.GetOutputPathByCount(latestTask.TotalVersionCount + 1) | |||
| displayJobName := form.DisplayJobName | |||
| jobName := form.JobName | |||
| uuid := form.Attachment | |||
| description := form.Description | |||
| @@ -1094,7 +1109,6 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| EngineName := form.EngineName | |||
| isLatestVersion := modelarts.IsLatestVersion | |||
| //判断权限 | |||
| canNewJob, _ := canUserCreateTrainJobVersion(ctx, latestTask.UserID) | |||
| if !canNewJob { | |||
| ctx.RenderWithErr("user cann't new trainjob", tplModelArtsTrainJobVersionNew, &form) | |||
| @@ -1112,22 +1126,16 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| _, err = ioutil.ReadDir(codeLocalPath) | |||
| if err == nil { | |||
| os.RemoveAll(codeLocalPath) | |||
| } else { | |||
| log.Error("创建任务失败,原代码还未删除,请重试!: %s (%v)", repo.FullName(), err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("创建任务失败,原代码还未删除,请重试!", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| // os.RemoveAll(codeLocalPath) | |||
| gitRepo, _ := git.OpenRepository(repo.RepoPath()) | |||
| commitID, _ := gitRepo.GetBranchCommitID(branch_name) | |||
| if err := git.Clone(repo.RepoPath(), codeLocalPath, git.CloneRepoOptions{ | |||
| Branch: branch_name, | |||
| }); err != nil { | |||
| log.Error("创建任务失败,任务名称已存在!: %s (%v)", repo.FullName(), err) | |||
| log.Error("Failed git clone repo to local(!: %s (%v)", repo.FullName(), err) | |||
| versionErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("创建任务失败,任务名称已存在!", tplModelArtsTrainJobVersionNew, &form) | |||
| ctx.RenderWithErr("Failed git clone repo to local!", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -1233,7 +1241,8 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| return | |||
| } | |||
| req := &modelarts.GenerateTrainJobReq{ | |||
| JobName: task.JobName, | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| DataUrl: dataPath, | |||
| Description: description, | |||
| CodeObsPath: codeObsPath, | |||
| @@ -1463,7 +1472,7 @@ func TrainJobShow(ctx *context.Context) { | |||
| pager.SetDefaultParams(ctx) | |||
| ctx.Data["Page"] = pager | |||
| ctx.Data["jobID"] = jobID | |||
| ctx.Data["jobName"] = VersionListTasks[0].JobName | |||
| ctx.Data["displayJobName"] = VersionListTasks[0].DisplayJobName | |||
| ctx.Data["version_list_task"] = VersionListTasks | |||
| ctx.Data["version_list_count"] = VersionListCount | |||
| ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, &VersionListTasks[0].Cloudbrain) | |||
| @@ -1664,7 +1673,8 @@ func getConfigList(perPage, page int, sortBy, order, searchContent, configType s | |||
| func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInferenceJobForm) { | |||
| ctx.Data["PageIsTrainJob"] = true | |||
| VersionOutputPath := modelarts.GetOutputPathByCount(modelarts.TotalVersionCount) | |||
| jobName := form.JobName | |||
| displayJobName := form.DisplayJobName | |||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
| uuid := form.Attachment | |||
| description := form.Description | |||
| workServerNumber := form.WorkServerNumber | |||
| @@ -1692,13 +1702,6 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| ckptUrl := form.TrainUrl + form.CkptName | |||
| if err := paramCheckCreateInferenceJob(form); err != nil { | |||
| log.Error("paramCheckCreateInferenceJob failed:(%v)", err) | |||
| inferenceJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsInferenceJobNew, &form) | |||
| return | |||
| } | |||
| count, err := models.GetCloudbrainInferenceJobCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| @@ -1714,6 +1717,31 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| } | |||
| } | |||
| if err := paramCheckCreateInferenceJob(form); err != nil { | |||
| log.Error("paramCheckCreateInferenceJob failed:(%v)", err) | |||
| inferenceJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsInferenceJobNew, &form) | |||
| return | |||
| } | |||
| //Determine whether the task name of the task in the project is duplicated | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeInference), displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| inferenceJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("the job name did already exist", tplModelArtsInferenceJobNew, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| inferenceJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("system error", tplModelArtsInferenceJobNew, &form) | |||
| return | |||
| } | |||
| } | |||
| //todo: del the codeLocalPath | |||
| _, err = ioutil.ReadDir(codeLocalPath) | |||
| if err == nil { | |||
| @@ -1726,9 +1754,9 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| if err := git.Clone(repo.RepoPath(), codeLocalPath, git.CloneRepoOptions{ | |||
| Branch: branch_name, | |||
| }); err != nil { | |||
| log.Error("创建任务失败,服务器超时!: %s (%v)", repo.FullName(), err) | |||
| log.Error("Create task failed, server timed out: %s (%v)", repo.FullName(), err) | |||
| inferenceJobErrorNewDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("创建任务失败,服务器超时!", tplModelArtsInferenceJobNew, &form) | |||
| ctx.RenderWithErr("Create task failed, server timed out", tplModelArtsInferenceJobNew, &form) | |||
| return | |||
| } | |||
| @@ -1785,6 +1813,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| req := &modelarts.GenerateInferenceJobReq{ | |||
| JobName: jobName, | |||
| DisplayJobName: displayJobName, | |||
| DataUrl: dataPath, | |||
| Description: description, | |||
| CodeObsPath: codeObsPath, | |||
| @@ -1797,7 +1826,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| LogUrl: logObsPath, | |||
| PoolID: poolID, | |||
| Uuid: uuid, | |||
| Parameters: param, //modelarts训练时用到 | |||
| Parameters: param, //modelarts train parameters | |||
| CommitID: commitID, | |||
| BranchName: branch_name, | |||
| Params: form.Params, | |||
| @@ -1813,13 +1842,6 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
| ResultUrl: resultObsPath, | |||
| } | |||
| //将params转换Parameters.Parameter,出错时返回给前端 | |||
| // var Parameters modelarts.Parameters | |||
| // if err := json.Unmarshal([]byte(params), &Parameters); err != nil { | |||
| // ctx.ServerError("json.Unmarshal failed:", err) | |||
| // return | |||
| // } | |||
| err = modelarts.GenerateInferenceJob(ctx, req) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
| @@ -1895,8 +1917,8 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| t := time.Now() | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = jobName | |||
| var displayJobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["display_job_name"] = displayJobName | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| @@ -2070,6 +2092,7 @@ func InferenceJobShow(ctx *context.Context) { | |||
| ctx.Data["labelName"] = LabelName | |||
| ctx.Data["jobID"] = jobID | |||
| ctx.Data["jobName"] = task.JobName | |||
| ctx.Data["displayJobName"] = task.DisplayJobName | |||
| ctx.Data["task"] = task | |||
| ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, task) | |||
| @@ -2116,12 +2139,11 @@ func ResultDownload(ctx *context.Context) { | |||
| err error | |||
| ) | |||
| var jobID = ctx.Params(":jobid") | |||
| versionName := ctx.Query("version_name") | |||
| parentDir := ctx.Query("parent_dir") | |||
| fileName := ctx.Query("file_name") | |||
| log.Info("DownloadResult start.") | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| task := ctx.Cloudbrain | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| } | |||
| @@ -2175,7 +2197,7 @@ func DownloadMultiResultFile(ctx *context.Context) { | |||
| //count++ | |||
| // models.ModifyModelDownloadCount(id) | |||
| returnFileName := task.JobName + ".zip" | |||
| returnFileName := task.DisplayJobName + ".zip" | |||
| ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+returnFileName) | |||
| ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||
| w := zip.NewWriter(ctx.Resp) | |||
| @@ -992,10 +992,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| }, context.RepoRef()) | |||
| m.Group("/cloudbrain", func() { | |||
| m.Group("/:jobname", func() { | |||
| m.Group("/:id", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.CloudBrainShow) | |||
| }) | |||
| m.Group("/:jobid", func() { | |||
| m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDebug) | |||
| m.Post("/commit_image", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage) | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) | |||
| @@ -1010,10 +1008,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/benchmark", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.CloudBrainBenchmarkIndex) | |||
| m.Group("/:jobname", func() { | |||
| m.Group("/:id", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.CloudBrainBenchMarkShow) | |||
| }) | |||
| m.Group("/:jobid", func() { | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.BenchmarkDel) | |||
| m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) | |||
| @@ -1061,7 +1057,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Get("/create", reqRepoCloudBrainWriter, repo.NotebookNew) | |||
| m.Post("/create", reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsNotebookForm{}), repo.NotebookCreate) | |||
| */ | |||
| m.Group("/:jobid", func() { | |||
| m.Group("/:id", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) | |||
| m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.NotebookDebug2) | |||
| m.Post("/:action", reqRepoCloudBrainWriter, repo.NotebookManage) | |||
| @@ -1075,11 +1071,11 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Get("", reqRepoCloudBrainReader, repo.TrainJobIndex) | |||
| m.Group("/:jobid", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.TrainJobShow) | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.TrainJobStop) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.TrainJobDel) | |||
| m.Get("/model_download", cloudbrain.AdminOrJobCreaterRight, repo.ModelDownload) | |||
| m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRight, repo.TrainJobNewVersion) | |||
| m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobStop) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobDel) | |||
| m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload) | |||
| m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobNewVersion) | |||
| m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | |||
| }) | |||
| m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.TrainJobNew) | |||
| m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreate) | |||
| @@ -1091,7 +1087,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Get("", reqRepoCloudBrainReader, repo.InferenceJobIndex) | |||
| m.Group("/:jobid", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.InferenceJobShow) | |||
| m.Get("/result_download", cloudbrain.AdminOrJobCreaterRight, repo.ResultDownload) | |||
| m.Get("/result_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ResultDownload) | |||
| m.Get("/downloadall", repo.DownloadMultiResultFile) | |||
| }) | |||
| m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.InferenceJobNew) | |||
| @@ -64,22 +64,29 @@ | |||
| <div class="ui grid stackable item"> | |||
| <div class="row"> | |||
| <!-- 任务名 --> | |||
| {{$JobID := '0'}} | |||
| {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK"}} | |||
| {{$JobID = .Cloudbrain.ID}} | |||
| {{else}} | |||
| {{$JobID = .JobID}} | |||
| {{end}} | |||
| <!-- {{$JobID}} --> | |||
| <div class="two wide column nowrap"> | |||
| {{if or (eq .JobType "DEBUG") (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}} | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/{{.JobName}}{{else}}/modelarts/notebook/{{.JobID}}{{end}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/{{$JobID}}{{else}}/modelarts/notebook/{{$JobID}}{{end}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "INFERENCE"}} | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "TRAIN"}} | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/train-job/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/train-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "BENCHMARK"}} | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{.JobName}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| @@ -89,8 +96,8 @@ | |||
| </div> | |||
| <!-- 任务状态 --> | |||
| <div class="two wide column text center nowrap" style="padding-left: 2.2rem !important; width: 10% !important;"> | |||
| <span class="job-status" id="{{.JobID}}" data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}' data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
| <span><i id="{{.JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| <span class="job-status" id="{{$JobID}}" data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK"}}/cloudbrain{{end}}' data-jobid="{{$JobID}}" data-version="{{.VersionName}}"> | |||
| <span><i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| </div> | |||
| <!-- 任务创建时间 --> | |||
| @@ -99,7 +106,7 @@ | |||
| </div> | |||
| <!-- 任务运行时间 --> | |||
| <div class="one wide column text center nowrap"> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
| <span style="font-size: 12px;" id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
| </div> | |||
| <!-- 计算资源 --> | |||
| <div class="one wide column text center nowrap"> | |||
| @@ -119,19 +126,19 @@ | |||
| </div> | |||
| <!-- 云脑侧名称 --> | |||
| <div class="two wide column text center nowrap" style="overflow: hidden;text-overflow:ellipsis;"> | |||
| <span class="fitted">{{.JobName}}</span> | |||
| <span class="fitted" title="{{.JobName}}">{{.JobName}}</span> | |||
| </div> | |||
| <div class="two wide column text center nowrap" style="width: 17.5%!important;"> | |||
| {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE"}} | |||
| <div class="ui compact buttons"> | |||
| <form id="debugAgainForm-{{.JobID}}"> | |||
| <form id="debugAgainForm-{{$JobID}}"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
| <a style="margin: 0 1rem;" id="ai-debug-{{.JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{.JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.JobID}}/'> | |||
| <a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{$JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'> | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| </a> | |||
| {{else}} | |||
| <a id="ai-debug-{{.JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{.JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.JobID}}/'> | |||
| <a id="ai-debug-{{$JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{$JobID}}" data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{$JobID}}/'> | |||
| {{$.i18n.Tr "repo.debug_again"}} | |||
| </a> | |||
| {{end}} | |||
| @@ -141,22 +148,22 @@ | |||
| <!-- 停止任务 --> | |||
| <div class="ui compact buttons"> | |||
| {{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}} | |||
| <form id="stopForm-{{.JobID}}" style="margin-left:-1px;"> | |||
| <form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
| {{$.CsrfTokenHtml}} | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{.JobID}}" class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING"}}disabled {{else}} blue {{end}}button' data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{.JobID}}/stop' data-jobid="{{.JobID}}"> | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING"}}disabled {{else}} blue {{end}}button' data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop' data-jobid="{{$JobID}}"> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| </form> | |||
| {{else}} | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{.JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}} blue {{end}}button" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}" > | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}} blue {{end}}button" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" > | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{.JobID}}" action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{end}}/{{.JobID}}/del?isadminpage=true' method="post"> | |||
| <form class="ui compact buttons" id="delForm-{{$JobID}}" action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{end}}/{{$JobID}}/del?isadminpage=true' method="post"> | |||
| {{$.CsrfTokenHtml}} | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{.JobID}}" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{.JobID}}/del_version?isadminpage=true" data-version="{{.VersionName}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true" data-version="{{.VersionName}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| </form> | |||
| @@ -164,25 +171,31 @@ | |||
| </div> | |||
| </div> | |||
| {{else}} | |||
| {{$JobID := '0'}} | |||
| {{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK"}} | |||
| {{$JobID = .Cloudbrain.ID}} | |||
| {{else}} | |||
| {{$JobID = .JobID}} | |||
| {{end}} | |||
| <div class="ui grid stackable item"> | |||
| <div class="row"> | |||
| <!-- 任务名 --> | |||
| <div class="two wide column nowrap"> | |||
| {{if eq .JobType "DEBUG"}} | |||
| <a class="title" href="" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "INFERENCE"}} | |||
| <a class="title" href="" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "TRAIN"}} | |||
| <a class="title" href="" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "BENCHMARK"}} | |||
| <a class="title" href="" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| @@ -192,8 +205,8 @@ | |||
| </div> | |||
| <!-- 任务状态 --> | |||
| <div class="two wide column text center nowrap" style="padding-left: 2.2rem !important; width: 10% !important;"> | |||
| <span class="job-status" id="{{.JobID}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
| <span><i id="{{.JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| <span class="job-status" id="{{$JobID}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}"> | |||
| <span><i id="{{$JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{$JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| </div> | |||
| <!-- 任务创建时间 --> | |||
| @@ -202,7 +215,7 @@ | |||
| </div> | |||
| <!-- 任务运行时间 --> | |||
| <div class="one wide column text center nowrap"> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
| <span style="font-size: 12px;" id="duration-{{$JobID}}">{{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}}</span> | |||
| </div> | |||
| <!-- 计算资源 --> | |||
| <div class="one wide column text center nowrap"> | |||
| @@ -227,14 +240,14 @@ | |||
| <div class="two wide column text center nowrap" style="width: 17.5%!important;"> | |||
| {{if eq .JobType "DEBUG"}} | |||
| <div class="ui compact buttons"> | |||
| <form id="debugAgainForm-{{.JobID}}"> | |||
| <form id="debugAgainForm-{{$JobID}}"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
| <a style="margin: 0 1rem;" id="ai-debug-{{.JobID}}" class='ui basic disabled button' > | |||
| <a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}" class='ui basic disabled button' > | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| </a> | |||
| {{else}} | |||
| <a id="ai-debug-{{.JobID}}" class='ui basic disabled button' > | |||
| <a id="ai-debug-{{$JobID}}" class='ui basic disabled button' > | |||
| {{$.i18n.Tr "repo.debug_again"}} | |||
| </a> | |||
| {{end}} | |||
| @@ -243,14 +256,14 @@ | |||
| {{end}} | |||
| <!-- 停止任务 --> | |||
| <div class="ui compact buttons"> | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{.JobID}}" class="ui basic disabled button" data-jobid="{{.JobID}}" data-version="{{.VersionName}}" > | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic disabled button" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" > | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| </div> | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{.JobID}}" action='' method="post"> | |||
| <form class="ui compact buttons" id="delForm-{{$JobID}}" action='' method="post"> | |||
| {{$.CsrfTokenHtml}} | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{.JobID}}" class="ui basic disabled button" style="border-radius: .28571429rem;"> | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" class="ui basic disabled button" style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| </form> | |||
| @@ -29,16 +29,17 @@ | |||
| <div class="ui mobile reversed stackable grid"> | |||
| <div class="ui sixteen wide tablet sixteen wide computer column margin-bottom20 pad-botom maxheight" id='key_tag'> | |||
| {{if .OrgTopics}} | |||
| <a class="{{if eq $.Keyword "" }} tag_bg {{end}} tag_key ui small tag_lable topic omit" href="{{$.Link}}?" >{{$.i18n.Tr "org.all_org_topics"}}</span></a> | |||
| <a class="{{if eq $.Keyword "" }} tag_bg {{end}} tag_key ui small tag_lable topic omit" href="{{$.Link}}?" onclick="iscontinueStatus()" id="tag_a">{{$.i18n.Tr "org.all_org_topics"}}</a> | |||
| {{end}} | |||
| {{range .OrgTopics}} | |||
| {{if ne .Name ""}} | |||
| <a class="{{if eq $.Keyword .Name }} tag_bg {{end}} tag_key ui small tag_lable topic omit" href="{{$.Link}}?q={{.Name}}" > | |||
| <a class="{{if eq $.Keyword .Name }} tag_bg {{end}} tag_key ui small tag_lable topic omit" href="{{$.Link}}?q={{.Name}}" onclick="iscontinueStatus()"> | |||
| {{.Name}} | |||
| </a> | |||
| {{end}} | |||
| {{end}} | |||
| {{if .OrgTopics}} | |||
| <a class=" tag_key ui small tag_lable topic omit icon_a" onclick="isUnfold()" id="icon_btn" > | |||
| <i class="ri-arrow-down-s-line" style="display:inline-block;vertical-align:top"></i> | |||
| @@ -136,14 +137,38 @@ | |||
| <script> | |||
| function isUnfold(){ | |||
| // var isTrue = document.getElementById("tag_a").getAttribute("data-tag") | |||
| var isContain= document.querySelector("#key_tag").classList.contains("maxheight"); | |||
| if(isContain){ | |||
| if(isContain){ | |||
| document.querySelector("#key_tag").classList.remove("maxheight"); | |||
| document.getElementById("icon_btn").innerHTML="<i class=\"ri-arrow-up-s-line\" style=\"display:inline-block;vertical-align:top\"></i>   {{.i18n.Tr "org.fold"}}" | |||
| localStorage.setItem("isunfold",true) | |||
| }else{ | |||
| document.querySelector("#key_tag").classList.add("maxheight"); | |||
| document.getElementById("icon_btn").innerHTML="<i class=\"ri-arrow-down-s-line\" style=\"display:inline-block;vertical-align:top\"></i>   {{.i18n.Tr "org.unfold"}}" | |||
| localStorage.setItem("isunfold",false) | |||
| } | |||
| } | |||
| function isShowIconBtn(){ | |||
| var key_height = document.getElementById("key_tag").offsetHeight | |||
| var parent = document.getElementById("key_tag") | |||
| var child = document.getElementById("icon_btn") | |||
| if (key_height < 88){ | |||
| parent.removeChild(child) | |||
| } | |||
| } | |||
| function iscontinueStatus(){ | |||
| var isunfold = localStorage.getItem("isunfold") | |||
| if (isunfold == "true" || isunfold == true){ | |||
| document.querySelector("#key_tag").classList.remove("maxheight"); | |||
| document.getElementById("icon_btn").innerHTML="<i class=\"ri-arrow-up-s-line\" style=\"display:inline-block;vertical-align:top\"></i>   {{.i18n.Tr "org.fold"}}" | |||
| }else{ | |||
| document.querySelector("#key_tag").classList.add("maxheight"); | |||
| document.getElementById("icon_btn").innerHTML="<i class=\"ri-arrow-down-s-line\" style=\"display:inline-block;vertical-align:top\"></i>   {{.i18n.Tr "org.unfold"}}" | |||
| } | |||
| } | |||
| isShowIconBtn() | |||
| iscontinueStatus() | |||
| </script> | |||
| @@ -102,14 +102,14 @@ | |||
| <!-- 任务名 --> | |||
| <div class="three wide column padding0"> | |||
| <a class="title" href="{{$.Link}}/{{.JobName}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href="{{$.Link}}/{{.Cloudbrain.ID}}" title="{{.Cloudbrain.ID}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| </div> | |||
| <!-- 任务状态 --> | |||
| <div class="two wide column padding0" style="padding-left: 2.2rem !important;"> | |||
| <span class="job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
| <span><i id="{{.JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| <span class="job-status" id="{{.Cloudbrain.ID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.Cloudbrain.ID}}" data-version="{{.VersionName}}"> | |||
| <span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| </div> | |||
| <div class="two wide column text center padding0"> | |||
| @@ -123,7 +123,7 @@ | |||
| </div> | |||
| <!-- 任务运行时间 --> | |||
| <div class="one wide column text center padding0"> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}">{{.TrainJobDuration}}</span> | |||
| <span style="font-size: 12px;" id="duration-{{.Cloudbrain.ID}}">{{.TrainJobDuration}}</span> | |||
| </div> | |||
| <!-- 计算资源 --> | |||
| <div class="two wide column text center padding0"> | |||
| @@ -141,10 +141,10 @@ | |||
| <div class="three wide column text center padding0"> | |||
| <div class="ui compact buttons" > | |||
| <!-- 停止任务 --> | |||
| <form id="stopForm-{{.JobID}}" style="margin-left:-1px;"> | |||
| <form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a id="ai-stop-{{.JobID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.JobID}}/stop" data-jobid="{{.JobID}}"> | |||
| <a id="ai-stop-{{.Cloudbrain.ID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/stop" data-jobid="{{.Cloudbrain.ID}}"> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| @@ -154,16 +154,16 @@ | |||
| </a> | |||
| {{end}} | |||
| </form> | |||
| <a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}" href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/rate" target="_blank"> | |||
| <a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank"> | |||
| 评分 | |||
| </a> | |||
| <!-- 删除任务 --> | |||
| <form id="delForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/benchmark{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/del" method="post"> | |||
| <form id="delForm-{{.Cloudbrain.ID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/benchmark{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del" method="post"> | |||
| <input type="hidden" name="debugListType" value="all"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a id="ai-delete-{{.JobID}}" class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "SUCCEEDED"}}blue {{else}}disabled {{end}}button' style="border-radius: .28571429rem;"> | |||
| <a id="ai-delete-{{.Cloudbrain.ID}}" class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "SUCCEEDED"}}blue {{else}}disabled {{end}}button' style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| {{else}} | |||
| @@ -82,7 +82,7 @@ | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 80%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" tabindex="3" autofocus required maxlength="254"> | |||
| <input style="width: 80%;" name="display_job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" autofocus required maxlength="254"> | |||
| </div> | |||
| <div class="unite min_title inline field"> | |||
| <label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
| @@ -124,7 +124,7 @@ | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_mirror"}}</label> | |||
| <span> </span> | |||
| <input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" value="{{.image}}" class="required autofocus" style='width:492px;' maxlength="254"> | |||
| <input type="text" list="cloudbrain_image" placeholder="选择镜像或输入镜像地址" name="image" value="{{.image}}" class="required autofocus" style='width:492px;' maxlength="254"> | |||
| <i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||
| <datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | |||
| {{range .images}} | |||
| @@ -183,7 +183,7 @@ td, th { | |||
| {{$.i18n.Tr "repo.modelarts.evaluate_job"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <div class="active section">{{.jobName}}</div> | |||
| <div class="active section">{{.displayJobName}}</div> | |||
| </div> | |||
| </h4> | |||
| {{range $k ,$v := .version_list_task}} | |||
| @@ -229,7 +229,7 @@ td, th { | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.JobName}} | |||
| {{.DisplayJobName}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -6,7 +6,7 @@ | |||
| <td class="name four wide"> | |||
| <span class="truncate"> | |||
| <span class="octicon octicon-file-directory"></span> | |||
| <a class="title" href="{{if .IsDir}}{{$.RepoLink}}/cloudbrain/{{$.JobID}}/models?parentDir={{.ParenDir}}{{else}}{{$.RepoLink}}/cloudbrain/{{$.JobID}}/download_model?parentDir={{.ParenDir}}&fileName={{.FileName}}&jobName={{$.task.JobName}}{{end}}"> | |||
| <a class="title" href="{{if .IsDir}}{{$.RepoLink}}/cloudbrain/{{$.task.ID}}/models?parentDir={{.ParenDir}}{{else}}{{$.RepoLink}}/cloudbrain/{{$.task.ID}}/download_model?parentDir={{.ParenDir}}&fileName={{.FileName}}&jobName={{$.task.JobName}}{{end}}"> | |||
| <span class="fitted">{{if .IsDir}} {{svg "octicon-file-directory" 16}}{{else}}{{svg "octicon-file" 16}}{{end}}</span> {{.FileName}} | |||
| </a> | |||
| </span> | |||
| @@ -1,7 +1,7 @@ | |||
| {{template "base/head" .}} | |||
| <style> | |||
| /* 遮罩层css效果图 */ | |||
| #mask { | |||
| position: fixed; | |||
| top: 0px; | |||
| @@ -18,7 +18,7 @@ | |||
| color: #000000 | |||
| } | |||
| /* 加载圈css效果图 */ | |||
| #loadingPage { | |||
| margin: 200px auto; | |||
| width: 50px; | |||
| @@ -27,7 +27,7 @@ | |||
| font-size: 10px; | |||
| display: block; | |||
| } | |||
| #loadingPage>div { | |||
| background-color: green; | |||
| height: 100%; | |||
| @@ -36,27 +36,27 @@ | |||
| -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out; | |||
| animation: sk-stretchdelay 1.2s infinite ease-in-out; | |||
| } | |||
| #loadingPage .rect2 { | |||
| -webkit-animation-delay: -1.1s; | |||
| animation-delay: -1.1s; | |||
| } | |||
| #loadingPage .rect3 { | |||
| -webkit-animation-delay: -1.0s; | |||
| animation-delay: -1.0s; | |||
| } | |||
| #loadingPage .rect4 { | |||
| -webkit-animation-delay: -0.9s; | |||
| animation-delay: -0.9s; | |||
| } | |||
| #loadingPage .rect5 { | |||
| -webkit-animation-delay: -0.8s; | |||
| animation-delay: -0.8s; | |||
| } | |||
| @-webkit-keyframes sk-stretchdelay { | |||
| 0%, | |||
| 40%, | |||
| @@ -67,7 +67,7 @@ | |||
| -webkit-transform: scaleY(1.0) | |||
| } | |||
| } | |||
| @keyframes sk-stretchdelay { | |||
| 0%, | |||
| 40%, | |||
| @@ -80,7 +80,7 @@ | |||
| -webkit-transform: scaleY(1.0); | |||
| } | |||
| } | |||
| .inline.required.field.cloudbrain_benchmark { | |||
| display: none; | |||
| } | |||
| @@ -128,7 +128,7 @@ | |||
| </h3> | |||
| <div class="ui attached segment"> | |||
| <div class="inline required field"> | |||
| <label>计算资源</label> | |||
| <label>{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | |||
| <div class="ui blue small menu compact selectcloudbrain"> | |||
| <a class="active item" href="{{.RepoLink}}/cloudbrain/create"> | |||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
| @@ -146,12 +146,12 @@ | |||
| </div> | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>任务名称</label> | |||
| <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,'')"> | |||
| <label>{{.i18n.Tr "cloudbrain.task_name"}}</label> | |||
| <input name="display_job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.display_job_name}}" tabindex="3" autofocus required maxlength="255" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>任务类型</label> | |||
| <label>{{.i18n.Tr "cloudbrain.task_type"}}</label> | |||
| <select id="cloudbrain_job_type" class="ui search dropdown" placeholder="选择任务类型" style='width:385px' name="job_type"> | |||
| <option name="job_type" value="DEBUG">DEBUG</option> | |||
| {{if .is_snn4imagenet_enabled}} | |||
| @@ -179,7 +179,7 @@ | |||
| <input id="store_category" type="hidden" name="get_benchmark_category"> | |||
| <div class="inline required field"> | |||
| <label>GPU类型</label> | |||
| <label>{{.i18n.Tr "cloudbrain.gpu_type"}}</label> | |||
| <select id="cloudbrain_gpu_type" class="ui search dropdown" placeholder="选择GPU类型" style='width:385px' name="gpu_type"> | |||
| {{range .gpu_types}} | |||
| <option value="{{.Queue}}">{{.Value}}</option> | |||
| @@ -188,8 +188,8 @@ | |||
| </div> | |||
| <div class="inline required field" style="position: relative;"> | |||
| <label>镜像</label> | |||
| <input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" required autofocus maxlength="255"> | |||
| <label>{{.i18n.Tr "cloudbrain.mirror"}}</label> | |||
| <input type="text" list="cloudbrain_image" placeholder="{{.i18n.Tr "cloudbrain.choose_mirror"}}" name="image" required autofocus maxlength="255"> | |||
| <i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||
| <datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | |||
| {{range .images}} | |||
| @@ -202,9 +202,9 @@ | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>数据集</label> | |||
| <select id="cloudbrain_dataset" class="ui search dropdown" placeholder="选择数据集" style='width:385px' name="attachment" required> | |||
| <label>{{.i18n.Tr "cloudbrain.dataset"}}</label> | |||
| <select id="cloudbrain_dataset" class="ui search dropdown" placeholder="选择数据集" style='width:385px' name="attachment" required> | |||
| {{range .attachments}} | |||
| <option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
| {{end}} | |||
| @@ -212,7 +212,7 @@ | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>资源规格</label> | |||
| <label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label> | |||
| <select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="选择资源规格" style='width:385px' name="resource_spec_id"> | |||
| {{range .resource_specs}} | |||
| <option name="resource_spec_id" value="{{.Id}}">GPU数:{{.GpuNum}},CPU数:{{.CpuNum}},内存(MB):{{.MemMiB}},共享内存(MB):{{.ShareMemMiB}}</option> | |||
| @@ -221,31 +221,31 @@ | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>数据集存放路径</label> | |||
| <label>{{.i18n.Tr "cloudbrain.dataset_storage_path"}}</label> | |||
| <input name="dataset_path" id="cloudbrain_dataset_path" value="{{.dataset_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>模型存放路径</label> | |||
| <label>{{.i18n.Tr "cloudbrain.model_storage_path"}}</label> | |||
| <input name="model_path" id="cloudbrain_model_path" value="{{.model_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>代码存放路径</label> | |||
| <label>{{.i18n.Tr "cloudbrain.code_storage_path"}}</label> | |||
| <input name="code_path" id="cloudbrain_code_path" value="{{.code_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||
| </div> | |||
| <div class="inline required field cloudbrain_benchmark"> | |||
| <label>benchmark脚本存放路径</label> | |||
| <label>{{.i18n.Tr "cloudbrain.benchmark_path"}}</label> | |||
| <input name="benchmark_path" id="cloudbrain_benchmark_path" value="{{.benchmark_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||
| </div> | |||
| <div class="inline required field cloudbrain_snn4imagenet"> | |||
| <label>snn4imagenet脚本存放路径</label> | |||
| <label>{{.i18n.Tr "cloudbrain.snn4imagenet_path"}}</label> | |||
| <input name="snn4imagenet_path" id="cloudbrain_snn4imagenet_path" value="{{.snn4imagenet_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||
| </div> | |||
| <div class="inline required field cloudbrain_brainscore"> | |||
| <label>brainscore脚本存放路径</label> | |||
| <label>{{.i18n.Tr "cloudbrain.brainscore_path"}}</label> | |||
| <input name="brainscore_path" id="cloudbrain_brainscore_path" value="{{.brainscore_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||
| </div> | |||
| <div class="inline required field" hidden> | |||
| <label>启动命令</label> | |||
| <label>{{.i18n.Tr "cloudbrain.start_command"}}</label> | |||
| <textarea name="command" rows="10" readonly="readonly">{{.command}}</textarea> | |||
| </div> | |||
| @@ -259,7 +259,7 @@ | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -279,7 +279,7 @@ | |||
| $(".icon.icons").css("visibility","hidden") | |||
| } | |||
| form.onsubmit = function(e){ | |||
| let value_task = $("input[name='job_name']").val() | |||
| let value_task = $("input[name='display_job_name']").val() | |||
| let value_image = $("input[name='image']").val() | |||
| let value_data = $("input[name='attachment']").val() | |||
| let re = /^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/ | |||
| @@ -291,9 +291,9 @@ | |||
| return false | |||
| } | |||
| let min_value_task = value_task.toLowerCase() | |||
| $("input[name='job_name']").attr("value",min_value_task) | |||
| $("input[name='display_job_name']").attr("value",min_value_task) | |||
| document.getElementById("mask").style.display = "block" | |||
| } | |||
| // 页面加载完毕后遮罩层隐藏 | |||
| @@ -302,21 +302,21 @@ | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| $('#cloudbrain_benchmark_category') | |||
| .dropdown({ | |||
| placeholder: "选择数据集类别", | |||
| }) | |||
| }) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| // $('#cloudbrain_image').select2({ | |||
| // placeholder: "选择镜像" | |||
| // }); | |||
| $(".ui.button.reset").click(function(e){ | |||
| e.preventDefault() | |||
| $('#cloudbrain_benchmark_category') | |||
| @@ -354,4 +354,4 @@ | |||
| $('#store_category').attr("value", selected_value) | |||
| }) | |||
| </script> | |||
| </script> | |||
| @@ -16,14 +16,14 @@ | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| {{with .task}} | |||
| <div class="active section">{{.JobName}}</div> | |||
| <div class="active section">{{.DisplayJobName}}</div> | |||
| {{end}} | |||
| </div> | |||
| </h4> | |||
| <div> | |||
| <div class="ui yellow segment"> | |||
| {{with .task}} | |||
| <p>任务名称: {{.JobName}}</p> | |||
| <p>任务名称: {{.DisplayJobName}}</p> | |||
| {{end}} | |||
| </div> | |||
| <div class="ui green segment"> | |||
| @@ -189,7 +189,7 @@ | |||
| margin-top: 0.4rem; | |||
| display: inline-block; | |||
| } | |||
| </style> | |||
| <!-- 弹窗 --> | |||
| @@ -208,10 +208,10 @@ | |||
| {{template "repo/header" .}} | |||
| {{template "base/alert" .}} | |||
| <!-- 提示框 --> | |||
| <!-- 列表容器 --> | |||
| <div class="ui container"> | |||
| <div class="ui two column stackable grid"> | |||
| <div class="column"> | |||
| <div class="ui blue small menu compact selectcloudbrain"> | |||
| @@ -227,12 +227,12 @@ | |||
| <div class="default text" style="color: rgba(0,0,0,.87);"></div> | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu"> | |||
| <div class="item" data-value="all">全部</div> | |||
| <div class="item" data-value="all">{{$.i18n.Tr "repo.gpu_type_all"}}</div> | |||
| <div class="item" data-value="CPU/GPU">CPU/GPU</div> | |||
| <div class="item" data-value="NPU">NPU</div> | |||
| </div> | |||
| </div> | |||
| {{if .Permission.CanWrite $.UnitTypeCloudBrain}} | |||
| {{if .Permission.CanWrite $.UnitTypeCloudBrain}} | |||
| <a class="ui green button" href="{{.RepoLink}}/cloudbrain/create">{{$.i18n.Tr "repo.modelarts.train_job.new_debug"}}</a> | |||
| {{else}} | |||
| <a class="ui disabled button">{{$.i18n.Tr "repo.modelarts.train_job.new_debug"}}</a> | |||
| @@ -272,29 +272,29 @@ | |||
| <span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span> | |||
| </div> | |||
| <div class="two wide column text center"> | |||
| <span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span> | |||
| <span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span> | |||
| </div> | |||
| <div class="one wide column text center"> | |||
| <span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span> | |||
| <span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span> | |||
| </div> | |||
| <div class="five wide column text center"> | |||
| <span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{range .Tasks}} | |||
| <div class="ui grid stackable item"> | |||
| <div class="row"> | |||
| <!-- 任务名 --> | |||
| <div class="four wide column"> | |||
| <a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/{{.JobName}}{{else}}{{$.RepoLink}}/modelarts/notebook/{{.JobID}}{{end}}?debugListType={{$.debugListType}}' title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}{{else}}{{$.RepoLink}}/modelarts/notebook/{{.Cloudbrain.ID}}{{end}}' title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| </div> | |||
| <div class="two wide column text center"> | |||
| <!--任务状态 --> | |||
| <span class="job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.JobID}}" data-resource="{{.ComputeResource}}"> | |||
| <span><i id="{{.JobID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.JobID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| <span class="job-status" id="{{.Cloudbrain.ID}}" data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}" data-jobid="{{.Cloudbrain.ID}}" data-resource="{{.ComputeResource}}"> | |||
| <span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| </div> | |||
| <div class="two wide column text center"> | |||
| @@ -313,22 +313,22 @@ | |||
| {{end}} | |||
| </div> | |||
| <div class="five wide column text center"> | |||
| <div class="ui compact buttons"> | |||
| <div class="ui compact buttons"> | |||
| <!-- {{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}} | |||
| <a class="ui basic button" href="{{$.Link}}/{{.JobID}}/rate" target="_blank"> | |||
| <a class="ui basic button" href="{{$.Link}}/{{.Cloudbrain.ID}}/rate" target="_blank"> | |||
| 评分 | |||
| </a> | |||
| {{end}} --> | |||
| <!-- 调试 --> | |||
| <form id="debugAgainForm-{{.JobID}}"> | |||
| <form id="debugAgainForm-{{.Cloudbrain.ID}}"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDebug}} | |||
| {{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||
| <a style="margin: 0 1rem;" id="ai-debug-{{.JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{.JobID}}" data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.JobID}}/'> | |||
| <a style="margin: 0 1rem;" id="ai-debug-{{.Cloudbrain.ID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' data-jobid="{{.Cloudbrain.ID}}" data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/'> | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| </a> | |||
| {{else}} | |||
| <a id="ai-debug-{{.JobID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{.JobID}}" data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.JobID}}/' data-linkpath='{{$.Link}}'> | |||
| <a id="ai-debug-{{.Cloudbrain.ID}}" class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' data-jobid="{{.Cloudbrain.ID}}" data-repopath='{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/' data-linkpath='{{$.Link}}'> | |||
| {{$.i18n.Tr "repo.debug_again"}} | |||
| </a> | |||
| {{end}} | |||
| @@ -344,12 +344,12 @@ | |||
| {{end}} | |||
| {{end}} | |||
| </form> | |||
| <!-- 停止 --> | |||
| <form id="stopForm-{{.JobID}}" style="margin-left:-1px;"> | |||
| <form id="stopForm-{{.Cloudbrain.ID}}" style="margin-left:-1px;"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a id="ai-stop-{{.JobID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.JobID}}/stop" data-jobid="{{.JobID}}"> | |||
| <a id="ai-stop-{{.Cloudbrain.ID}}" class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/stop" data-jobid="{{.Cloudbrain.ID}}"> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{else}} | |||
| @@ -359,11 +359,11 @@ | |||
| {{end}} | |||
| </form> | |||
| <!-- 删除 --> | |||
| <form id="delForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/del" method="post"> | |||
| <form id="delForm-{{.Cloudbrain.ID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/del" method="post"> | |||
| <input type="hidden" name="debugListType" value="{{$.ListType}}"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a id="ai-delete-{{.JobID}}" class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED"}}blue {{else}}disabled {{end}}button' style="border-radius: .28571429rem;"> | |||
| <a id="ai-delete-{{.Cloudbrain.ID}}" class='ui basic ai_delete {{if eq .Status "STOPPED" "FAILED" "START_FAILED"}}blue {{else}}disabled {{end}}button' style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| {{else}} | |||
| @@ -371,18 +371,18 @@ | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| {{end}} | |||
| </form> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| <div class="ui compact buttons" style="{{if eq .ComputeResource "CPU/GPU"}} visibility: visible {{else}} visibility: hidden{{end}}"> | |||
| <div class="ui dropdown" id="model_more" style="padding: .58928571em 1.125em .58928571em;"> | |||
| <div class="text">更多</div> | |||
| <div class="text">{{$.i18n.Tr "repo.more"}}</div> | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu" style="right: auto;"> | |||
| <div class="item" style="padding: 0 !important;"> | |||
| <!-- 接收结果 --> | |||
| <iframe src="" frameborder="0" name="iframeContent" style="display: none;"></iframe> | |||
| {{if .CanDebug}} | |||
| <a id="model-image-{{.JobID}}" class='imageBtn ui basic {{if ne .Status "RUNNING"}}disabled {{else}}blue {{end}}button'>{{$.i18n.Tr "repo.submit_image"}}</a> | |||
| <a id="model-image-{{.Cloudbrain.ID}}" class='imageBtn ui basic {{if ne .Status "RUNNING"}}disabled {{else}}blue {{end}}button'>{{$.i18n.Tr "repo.submit_image"}}</a> | |||
| {{else}} | |||
| <a class="imageBtn ui basic disabled button">{{$.i18n.Tr "repo.submit_image"}}</a> | |||
| {{end}} | |||
| @@ -390,14 +390,14 @@ | |||
| <div class="item" style="padding: 0 !important;"> | |||
| <!-- 模型下载 --> | |||
| {{if .CanDebug}} | |||
| <a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/models" target="_blank">{{$.i18n.Tr "repo.download"}}</a> | |||
| <a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/models" target="_blank">{{$.i18n.Tr "repo.download"}}</a> | |||
| {{else}} | |||
| <a class="ui basic disabled button">{{$.i18n.Tr "repo.download"}}</a> | |||
| {{end}} | |||
| </div> | |||
| {{if and (ne .JobType "DEBUG") (eq .Cloudbrain.Type 0)}} | |||
| <div class="item" style="padding: 0 !important;"> | |||
| <a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/rate" target="_blank"> | |||
| <div class="item" style="padding: 0 !important;"> | |||
| <a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank"> | |||
| 评分 | |||
| </a> | |||
| </div> | |||
| @@ -408,28 +408,28 @@ | |||
| </div> | |||
| <!-- 镜像列表弹窗 --> | |||
| <div id="imageModal" class="modal" style="display: none;"> | |||
| <div class="modal-content"> | |||
| <div class="modal-content"> | |||
| <!-- 表格 --> | |||
| <div class="ui form"> | |||
| <form id="commitImageForm" action="{{$.RepoLink}}/cloudbrain/{{.JobID}}/commit_image" method="post" target="iframeContent"> | |||
| <form id="commitImageForm" action="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/commit_image" method="post" target="iframeContent"> | |||
| {{$.CsrfTokenHtml}} | |||
| <div class="row"> | |||
| <p style="display: inline;">提交任务镜像</p> | |||
| <span class="close">×</span> | |||
| </div> | |||
| <div class="ui divider"></div> | |||
| <div class="inline required field dis"> | |||
| <label>镜像标签:</label> | |||
| <label> {{$.i18n.Tr "repo.cloudbrain.mirror_tag"}}:</label> | |||
| <input name="tag" id="image_tag" tabindex="3" autofocus required maxlength="255" style="width:75%"> | |||
| </div> | |||
| <div class="inline field"> | |||
| <label class="label_after">镜像描述:</label> | |||
| <label class="label_after">{{$.i18n.Tr "repo.cloudbrain.mirror_description"}}:</label> | |||
| <textarea name="description" maxlength="255" rows="8" style="width:75%;margin-left: 0.2em;"></textarea> | |||
| </div> | |||
| <div class="ui divider"></div> | |||
| </div> | |||
| <div class="ui divider"></div> | |||
| <div class="inline field"> | |||
| <label></label> | |||
| <button class="ui green button" onclick="showmask()"> | |||
| @@ -438,7 +438,7 @@ | |||
| </div> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -483,8 +483,8 @@ | |||
| let url={{.RepoLink}} | |||
| let redirect_to = {{$.Link}} | |||
| let getParam=getQueryVariable('debugListType') | |||
| let dropdownValue = ['all','',false].includes(getParam)? '全部' : getParam | |||
| let dropdownValue = ['all','',false].includes(getParam)? '{{$.i18n.Tr "repo.gpu_type_all"}}' : getParam | |||
| // localStorage.setItem('all',location.href) | |||
| function getQueryVariable(variable) | |||
| { | |||
| @@ -505,7 +505,7 @@ | |||
| }) | |||
| $('.ui.selection.dropdown').dropdown({ | |||
| onChange:function(value){ | |||
| location.href = `${url}/debugjob?debugListType=${value}` | |||
| } | |||
| }) | |||
| @@ -565,5 +565,5 @@ | |||
| } | |||
| }) | |||
| } | |||
| </script> | |||
| </script> | |||
| @@ -105,9 +105,9 @@ | |||
| <!-- 任务名 --> | |||
| <div class="three wide column padding0"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| </div> | |||
| <!-- 模型版本 --> | |||
| @@ -174,7 +174,7 @@ | |||
| <div class="ui compact buttons"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="model-delete-{{.JobID}}" class="ui basic ai_delete blue button" data-repopath="{{$.RepoRelPath}}/modelarts/inference-job/{{.JobID}}/del_version" data-version="{{.VersionName}}" style="border-radius: .28571429rem;"> | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{.JobID}}" class="ui basic ai_delete blue button" data-repopath="{{$.RepoRelPath}}/modelarts/inference-job/{{.JobID}}/del_version" data-version="{{.VersionName}}" style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| {{else}} | |||
| @@ -67,7 +67,7 @@ | |||
| <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" onkeyup="this.value=this.value.replace(/[, ]/g,'')" tabindex="3" autofocus required maxlength="64"> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" onkeyup="this.value=this.value.replace(/[, ]/g,'')" tabindex="3" autofocus required maxlength="64"> | |||
| <span class="tooltips" style="display: block;">请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。</span> | |||
| </div> | |||
| @@ -414,8 +414,8 @@ | |||
| } | |||
| ] | |||
| }, | |||
| job_name:{ | |||
| identifier : 'job_name', | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[^-]$/]', | |||
| @@ -174,7 +174,7 @@ td, th { | |||
| {{$.i18n.Tr "repo.modelarts.infer_job"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <div class="active section">{{.jobName}}</div> | |||
| <div class="active section">{{.displayJobName}}</div> | |||
| </div> | |||
| </h4> | |||
| {{with .task}} | |||
| @@ -199,7 +199,7 @@ td, th { | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.JobName}} | |||
| {{.DisplayJobName}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -48,7 +48,7 @@ | |||
| </div> | |||
| <div class="inline required field"> | |||
| <label>任务名称</label> | |||
| <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="display_job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.display_job_name}}" tabindex="3" autofocus required maxlength="255" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||
| </div> | |||
| <div class="inline required field"> | |||
| @@ -117,7 +117,7 @@ | |||
| $('#messageInfo').css('display','none') | |||
| form.onsubmit = function(e){ | |||
| let value_task = $("input[name='job_name']").val() | |||
| let value_task = $("input[name='display_job_name']").val() | |||
| let re = /^[a-z0-9][a-z0-9-_]{1,36}$/ | |||
| @@ -131,7 +131,7 @@ | |||
| let min_value_task = value_task.toLowerCase() | |||
| $("input[name='job_name']").attr("value",min_value_task) | |||
| $("input[name='display_job_name']").attr("value",min_value_task) | |||
| document.getElementById("mask").style.display = "block" | |||
| } | |||
| @@ -16,14 +16,14 @@ | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| {{with .task}} | |||
| <div class="active section">{{.JobName}}</div> | |||
| <div class="active section">{{.DisplayJobName}}</div> | |||
| {{end}} | |||
| </div> | |||
| </h4> | |||
| <div> | |||
| <div class="ui yellow segment"> | |||
| {{with .task}} | |||
| <p>任务名称: {{.JobName}}</p> | |||
| <p>任务名称: {{.DisplayJobName}}</p> | |||
| {{end}} | |||
| </div> | |||
| <div class="ui green segment"> | |||
| @@ -102,9 +102,9 @@ | |||
| <!-- 任务名 --> | |||
| <div class="three wide column padding0"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| </div> | |||
| <!-- 版本数量 --> | |||
| @@ -157,7 +157,7 @@ | |||
| <form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="model-delete-{{.JobID}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{.JobID}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| </a> | |||
| {{else}} | |||
| @@ -80,7 +80,7 @@ | |||
| <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="64"> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="64"> | |||
| <span class="tooltips" style="display: block;">请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。</span> | |||
| </div> | |||
| @@ -391,8 +391,8 @@ | |||
| } | |||
| ] | |||
| }, | |||
| job_name:{ | |||
| identifier : 'job_name', | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[^-]$/]', | |||
| @@ -183,7 +183,7 @@ td, th { | |||
| {{$.i18n.Tr "repo.modelarts.train_job"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <div class="active section">{{.jobName}}</div> | |||
| <div class="active section">{{.displayJobName}}</div> | |||
| </div> | |||
| </h4> | |||
| {{range $k ,$v := .version_list_task}} | |||
| @@ -260,7 +260,7 @@ td, th { | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.JobName}} | |||
| {{.DisplayJobName}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -558,7 +558,7 @@ td, th { | |||
| onShow:function(){ | |||
| $('input[name="Version"]').addClass('model_disabled') | |||
| // $('input[name="JobId"]').text(obj.JobName) | |||
| $('#JobName').val(obj.JobName).addClass('model_disabled') | |||
| $('#JobName').val(obj.DisplayJobName).addClass('model_disabled') | |||
| $('input[name="JobId"]').val(obj.JobID) | |||
| $('input[name="VersionName"]').val(obj.VersionName).addClass('model_disabled') | |||
| $('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"}) | |||
| @@ -82,11 +82,12 @@ | |||
| {{end}} | |||
| <input type="hidden" id="ai_engine_name" name="engine_names" value=""> | |||
| <input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
| <input type="hidden" id="display_job_name" name="display_job_name" value="{{.display_job_name}}"> | |||
| <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input type="hidden" style="width: 60%;" name="job_name" id="trainjob_job_name" value="{{.job_name}}"> | |||
| <input style="width: 60%;" value="{{.job_name}}" tabindex="3" disabled > | |||
| <input type="hidden" style="width: 60%;" name="job_name" id="job_name" value="{{.job_name}}"> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" value="{{.display_job_name}}" tabindex="3" disabled > | |||
| </div> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.parents_version"}}</label> | |||
| @@ -426,6 +427,15 @@ | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]', | |||
| prompt : '只包含大小写字母、数字、_和-,最长36个字符。' | |||
| } | |||
| ] | |||
| }, | |||
| attachment:{ | |||
| identifier : 'attachment', | |||
| rules: [ | |||
| @@ -483,6 +493,15 @@ | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]', | |||
| prompt : '只包含大小写字母、数字、_和-,最长36个字符。' | |||
| } | |||
| ] | |||
| }, | |||
| attachment:{ | |||
| identifier : 'attachment', | |||
| rules: [ | |||
| @@ -221,15 +221,16 @@ | |||
| } | |||
| function loadTrainList(){ | |||
| $.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => { | |||
| console.log(data) | |||
| const n_length = data.length | |||
| let train_html='' | |||
| for (let i=0;i<n_length;i++){ | |||
| train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].JobName}</div>` | |||
| train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].DisplayJobName}</div>` | |||
| train_html += '</div>' | |||
| } | |||
| $("#job-name").append(train_html) | |||
| $(".ui.dropdown.selection.search.width83").removeClass("loading") | |||
| $('#choice_model .default.text').text(data[0].JobName) | |||
| $('#choice_model .default.text').text(data[0].DisplayJobName) | |||
| $('#choice_model input[name="JobId"]').val(data[0].JobID) | |||
| loadTrainVersion() | |||
| @@ -73,7 +73,7 @@ | |||
| {{else if eq .GetOpType 24}} | |||
| {{$.i18n.Tr "action.upload_dataset" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 25}} | |||
| {{$.i18n.Tr "action.task_gpudebugjob" .GetRepoLink .RefName .RefName | Str2html}} | |||
| {{$.i18n.Tr "action.task_gpudebugjob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 26}} | |||
| {{$.i18n.Tr "action.task_npudebugjob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 27}} | |||
| @@ -81,7 +81,7 @@ | |||
| {{else if eq .GetOpType 28}} | |||
| {{$.i18n.Tr "action.task_inferencejob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 29}} | |||
| {{$.i18n.Tr "action.task_benchmark" .GetRepoLink .RefName .RefName | Str2html}} | |||
| {{$.i18n.Tr "action.task_benchmark" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 30}} | |||
| {{$.i18n.Tr "action.task_createmodel" .GetRepoLink .RefName .RefName | Str2html}} | |||
| {{end}} | |||
| @@ -3,52 +3,52 @@ export default async function initCloudrain() { | |||
| $(document).ready(loadJobStatus); | |||
| function loadJobStatus() { | |||
| $(".job-status").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const ID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| // const computeResource = job.dataset.resource | |||
| const versionname = job.dataset.version | |||
| const status_text = $(`#${jobID}-text`).text() | |||
| const status_text = $(`#${ID}-text`).text() | |||
| const finalState = ['STOPPED','CREATE_FAILED','UNAVAILABLE','DELETED','RESIZE_FAILED','SUCCEEDED','IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED','SUBMIT_MODEL_FAILED','DEPLOY_SERVICE_FAILED','CHECK_FAILED'] | |||
| if (finalState.includes(status_text)) { | |||
| return | |||
| } | |||
| // const diffResource = computeResource == "NPU" ? 'modelarts/notebook' : 'cloudbrain' | |||
| $.get(`/api/v1/repos/${repoPath}/${jobID}?version_name=${versionname}`, (data) => { | |||
| const jobID = data.JobID | |||
| $.get(`/api/v1/repos/${repoPath}/${ID}?version_name=${versionname}`, (data) => { | |||
| const ID = data.ID || data.JobID | |||
| const status = data.JobStatus | |||
| const duration = data.JobDuration | |||
| $('#duration-'+jobID).text(duration) | |||
| $('#duration-'+ID).text(duration) | |||
| if (status != status_text) { | |||
| $('#' + jobID+'-icon').removeClass().addClass(status) | |||
| $('#' + jobID+ '-text').text(status) | |||
| finalState.includes(status) && $('#' + jobID + '-stop').removeClass('blue').addClass('disabled') | |||
| $('#' + ID+'-icon').removeClass().addClass(status) | |||
| $('#' + ID+ '-text').text(status) | |||
| finalState.includes(status) && $('#' + ID + '-stop').removeClass('blue').addClass('disabled') | |||
| } | |||
| if(status==="RUNNING"){ | |||
| $('#ai-debug-'+jobID).removeClass('disabled').addClass('blue').text('调试').css("margin","0 1rem") | |||
| $('#model-image-'+jobID).removeClass('disabled').addClass('blue') | |||
| $('#ai-debug-'+ID).removeClass('disabled').addClass('blue').text('调试').css("margin","0 1rem") | |||
| $('#model-image-'+ID).removeClass('disabled').addClass('blue') | |||
| } | |||
| if(status!=="RUNNING"){ | |||
| // $('#model-debug-'+jobID).removeClass('blue') | |||
| // $('#model-debug-'+jobID).addClass('disabled') | |||
| $('#model-image-'+jobID).removeClass('blue').addClass('disabled') | |||
| // $('#model-debug-'+ID).removeClass('blue') | |||
| // $('#model-debug-'+ID).addClass('disabled') | |||
| $('#model-image-'+ID).removeClass('blue').addClass('disabled') | |||
| } | |||
| if(["CREATING","STOPPING","WAITING","STARTING"].includes(status)){ | |||
| $('#ai-debug-'+jobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-debug-'+ID).removeClass('blue').addClass('disabled') | |||
| } | |||
| if(['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'].includes(status)){ | |||
| $('#ai-debug-'+jobID).removeClass('disabled').addClass('blue').text('再次调试').css("margin","0") | |||
| $('#ai-debug-'+ID).removeClass('disabled').addClass('blue').text('再次调试').css("margin","0") | |||
| } | |||
| if(["RUNNING","WAITING"].includes(status)){ | |||
| $('#ai-stop-'+jobID).removeClass('disabled').addClass('blue') | |||
| $('#ai-stop-'+ID).removeClass('disabled').addClass('blue') | |||
| } | |||
| if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED","SUCCEEDED"].includes(status)){ | |||
| $('#ai-stop-'+jobID).removeClass('blue').addClass('disabled') | |||
| if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED","SUCCEEDED","COMPLETED"].includes(status)){ | |||
| $('#ai-stop-'+ID).removeClass('blue').addClass('disabled') | |||
| } | |||
| if(["STOPPED","FAILED","START_FAILED","KILLED","COMPLETED","SUCCEEDED"].includes(status)){ | |||
| $('#ai-delete-'+jobID).removeClass('disabled').addClass('blue') | |||
| $('#ai-delete-'+ID).removeClass('disabled').addClass('blue') | |||
| }else{ | |||
| $('#ai-delete-'+jobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-delete-'+ID).removeClass('blue').addClass('disabled') | |||
| } | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| @@ -104,25 +104,25 @@ export default async function initCloudrain() { | |||
| assertDelete(this) | |||
| } | |||
| }) | |||
| function stopDebug(JobID,stopUrl){ | |||
| function stopDebug(ID,stopUrl){ | |||
| $.ajax({ | |||
| type:"POST", | |||
| url:stopUrl, | |||
| data:$('#stopForm-'+JobID).serialize(), | |||
| data:$('#stopForm-'+ID).serialize(), | |||
| success:function(res){ | |||
| if(res.result_code==="0"){ | |||
| $('#' + JobID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + JobID+ '-text').text(res.status) | |||
| $('#' + ID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + ID+ '-text').text(res.status) | |||
| if(res.status==="STOPPED"){ | |||
| $('#ai-debug-'+JobID).removeClass('disabled').addClass('blue').text("再次调试").css("margin","0") | |||
| $('#ai-image-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-delete-'+JobID).removeClass('disabled').addClass('blue') | |||
| $('#ai-stop-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-debug-'+ID).removeClass('disabled').addClass('blue').text("再次调试").css("margin","0") | |||
| $('#ai-image-'+ID).removeClass('blue').addClass('disabled') | |||
| $('#ai-model-debug-'+ID).removeClass('blue').addClass('disabled') | |||
| $('#ai-delete-'+ID).removeClass('disabled').addClass('blue') | |||
| $('#ai-stop-'+ID).removeClass('blue').addClass('disabled') | |||
| } | |||
| else{ | |||
| $('#ai-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-stop-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-debug-'+ID).removeClass('blue').addClass('disabled') | |||
| $('#ai-stop-'+ID).removeClass('blue').addClass('disabled') | |||
| } | |||
| }else{ | |||
| @@ -136,42 +136,41 @@ export default async function initCloudrain() { | |||
| }) | |||
| } | |||
| $('.ui.basic.ai_stop').click(function() { | |||
| const jobID = this.dataset.jobid | |||
| const ID = this.dataset.jobid | |||
| const repoPath = this.dataset.repopath | |||
| stopDebug(jobID,repoPath) | |||
| stopDebug(ID,repoPath) | |||
| }) | |||
| function stopVersion(version_name,jobID,repoPath){ | |||
| const url = `/api/v1/repos/${repoPath}/${jobID}/stop_version` | |||
| function stopVersion(version_name,ID,repoPath){ | |||
| const url = `/api/v1/repos/${repoPath}/${ID}/stop_version` | |||
| $.post(url,{version_name:version_name},(data)=>{ | |||
| if(data.StatusOK===0){ | |||
| $('#ai-stop-'+jobID).removeClass('blue') | |||
| $('#ai-stop-'+jobID).addClass('disabled') | |||
| refreshStatus(version_name,jobID,repoPath) | |||
| $('#ai-stop-'+ID).removeClass('blue') | |||
| $('#ai-stop-'+ID).addClass('disabled') | |||
| refreshStatus(version_name,ID,repoPath) | |||
| } | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| }); | |||
| } | |||
| function refreshStatus(version_name,jobID,repoPath){ | |||
| function refreshStatus(version_name,ID,repoPath){ | |||
| const url = `/api/v1/repos/${repoPath}/${jobID}/?version_name${version_name}` | |||
| const url = `/api/v1/repos/${repoPath}/${ID}/?version_name${version_name}` | |||
| $.get(url,(data)=>{ | |||
| $(`#${jobID}-icon`).attr("class",data.JobStatus) | |||
| $(`#${ID}-icon`).attr("class",data.JobStatus) | |||
| // detail status and duration | |||
| $(`#${jobID}-text`).text(data.JobStatus) | |||
| $(`#${ID}-text`).text(data.JobStatus) | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| }); | |||
| } | |||
| $('.ui.basic.ai_stop_version').click(function() { | |||
| const jobID = this.dataset.jobid | |||
| const ID = this.dataset.jobid | |||
| const repoPath = this.dataset.repopath | |||
| const versionName = this.dataset.version | |||
| stopVersion(versionName,jobID,repoPath) | |||
| stopVersion(versionName,ID,repoPath) | |||
| }) | |||
| function getModelInfo(repoPath,modelName,versionName,jobName){ | |||
| console.log("getModelInfo") | |||
| $.get(`${repoPath}/modelmanage/show_model_info_api?name=${modelName}`,(data)=>{ | |||
| if(data.length===0){ | |||
| $(`#${jobName}`).popup('toggle') | |||
| @@ -195,27 +194,27 @@ export default async function initCloudrain() { | |||
| const jobName = this.dataset.jobname | |||
| getModelInfo(repoPath,modelName,versionName,jobName) | |||
| }) | |||
| function debugAgain(JobID,debugUrl,redirect_to){ | |||
| if($('#' + JobID+ '-text').text()==="RUNNING"){ | |||
| function debugAgain(ID,debugUrl,redirect_to){ | |||
| if($('#' + ID+ '-text').text()==="RUNNING"){ | |||
| window.open(debugUrl+'debug') | |||
| }else{ | |||
| $.ajax({ | |||
| type:"POST", | |||
| url:debugUrl+'restart?redirect_to='+redirect_to, | |||
| data:$('#debugAgainForm-'+JobID).serialize(), | |||
| data:$('#debugAgainForm-'+ID).serialize(), | |||
| success:function(res){ | |||
| if(res['WechatRedirectUrl']){ | |||
| window.location.href=res['WechatRedirectUrl'] | |||
| } | |||
| else if(res.result_code==="0"){ | |||
| if(res.job_id!==JobID){ | |||
| if(res.id!==ID){ | |||
| location.reload() | |||
| }else{ | |||
| $('#' + JobID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + JobID+ '-text').text(res.status) | |||
| $('#ai-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-delete-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#ai-debug-'+JobID).text("调试").css("margin","0 1rem") | |||
| $('#' + ID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + ID+ '-text').text(res.status) | |||
| $('#ai-debug-'+ID).removeClass('blue').addClass('disabled') | |||
| $('#ai-delete-'+ID).removeClass('blue').addClass('disabled') | |||
| $('#ai-debug-'+ID).text("调试").css("margin","0 1rem") | |||
| } | |||
| }else{ | |||
| $('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut(); | |||
| @@ -228,10 +227,10 @@ export default async function initCloudrain() { | |||
| } | |||
| } | |||
| $('.ui.basic.ai_debug').click(function() { | |||
| const jobID = this.dataset.jobid | |||
| const ID = this.dataset.jobid | |||
| const repoPath = this.dataset.repopath | |||
| const redirect_to = this.dataset.linkpath | |||
| debugAgain(jobID,repoPath,redirect_to) | |||
| debugAgain(ID,repoPath,redirect_to) | |||
| }) | |||
| } | |||
| @@ -725,9 +725,11 @@ display: block; | |||
| margin-bottom: -50px; | |||
| } | |||
| .repo-header .repo-buttons{ | |||
| position: absolute; | |||
| right: 15px; | |||
| margin-bottom: -60px; | |||
| position: relative; | |||
| top: 1rem; | |||
| width: 100%; | |||
| display: flex; | |||
| justify-content: flex-end; | |||
| } | |||
| .repo-buttons .ui.labeled.button>.button{ | |||
| box-shadow: none !important; | |||
| @@ -0,0 +1,274 @@ | |||
| const cssnano = require('cssnano'); | |||
| const fastGlob = require('fast-glob'); | |||
| const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); | |||
| const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | |||
| const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | |||
| const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); | |||
| const PostCSSPresetEnv = require('postcss-preset-env'); | |||
| const PostCSSSafeParser = require('postcss-safe-parser'); | |||
| const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); | |||
| const TerserPlugin = require('terser-webpack-plugin'); | |||
| const VueLoaderPlugin = require('vue-loader/lib/plugin'); | |||
| const {statSync} = require('fs'); | |||
| const {resolve, parse} = require('path'); | |||
| //const {SourceMapDevToolPlugin} = require('webpack'); | |||
| const glob = (pattern) => fastGlob.sync(pattern, {cwd: __dirname, absolute: true}); | |||
| const themes = {}; | |||
| for (const path of glob('web_src/less/themes/*.less')) { | |||
| themes[parse(path).name] = [path]; | |||
| } | |||
| const isProduction = process.env.NODE_ENV !== 'development'; | |||
| module.exports = { | |||
| mode: isProduction ? 'production' : 'development', | |||
| entry: { | |||
| index: [ | |||
| resolve(__dirname, 'web_src/js/index.js'), | |||
| resolve(__dirname, 'web_src/less/index.less'), | |||
| ], | |||
| swagger: [ | |||
| resolve(__dirname, 'web_src/js/standalone/swagger.js'), | |||
| ], | |||
| jquery: [ | |||
| resolve(__dirname, 'web_src/js/jquery.js'), | |||
| ], | |||
| icons: glob('node_modules/@primer/octicons/build/svg/**/*.svg'), | |||
| ...themes, | |||
| }, | |||
| devtool: false, | |||
| output: { | |||
| path: resolve(__dirname, 'public'), | |||
| filename: 'js/[name].js', | |||
| chunkFilename: 'js/[name].js', | |||
| }, | |||
| node:{ | |||
| fs: 'empty' | |||
| }, | |||
| optimization: { | |||
| minimize: isProduction, | |||
| minimizer: [ | |||
| new TerserPlugin({ | |||
| sourceMap: true, | |||
| extractComments: false, | |||
| terserOptions: { | |||
| keep_fnames: /^(HTML|SVG)/, // https://github.com/fgnass/domino/issues/144 | |||
| output: { | |||
| comments: false, | |||
| }, | |||
| }, | |||
| }), | |||
| new OptimizeCSSAssetsPlugin({ | |||
| cssProcessor: cssnano, | |||
| cssProcessorOptions: { | |||
| parser: PostCSSSafeParser, | |||
| }, | |||
| cssProcessorPluginOptions: { | |||
| preset: [ | |||
| 'default', | |||
| { | |||
| discardComments: { | |||
| removeAll: true, | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| }), | |||
| ], | |||
| splitChunks: { | |||
| chunks: 'async', | |||
| name: (_, chunks) => chunks.map((item) => item.name).join('-'), | |||
| cacheGroups: { | |||
| // this bundles all monaco's languages into one file instead of emitting 1-65.js files | |||
| monaco: { | |||
| test: /monaco-editor/, | |||
| name: 'monaco', | |||
| chunks: 'async' | |||
| } | |||
| } | |||
| } | |||
| }, | |||
| module: { | |||
| rules: [ | |||
| { | |||
| test: /\.vue$/, | |||
| exclude: /node_modules/, | |||
| loader: 'vue-loader', | |||
| }, | |||
| { | |||
| test: require.resolve('jquery-datetimepicker'), | |||
| use: 'imports-loader?define=>false,exports=>false', | |||
| }, | |||
| { | |||
| test: /\.worker\.js$/, | |||
| exclude: /monaco/, | |||
| use: [ | |||
| { | |||
| loader: 'worker-loader', | |||
| options: { | |||
| name: '[name].js', | |||
| inline: true, | |||
| fallback: false, | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| test: /\.ts$/, | |||
| use: [ | |||
| { | |||
| loader: "ts-loader", | |||
| } | |||
| ], | |||
| exclude: /node_modules/ | |||
| }, | |||
| { | |||
| test: /\.js$/, | |||
| exclude: /node_modules/, | |||
| use: [ | |||
| { | |||
| loader: 'babel-loader', | |||
| options: { | |||
| cacheDirectory: true, | |||
| cacheCompression: false, | |||
| cacheIdentifier: [ | |||
| resolve(__dirname, 'package.json'), | |||
| resolve(__dirname, 'package-lock.json'), | |||
| resolve(__dirname, 'webpack.config.js'), | |||
| ].map((path) => statSync(path).mtime.getTime()).join(':'), | |||
| sourceMaps: true, | |||
| presets: [ | |||
| [ | |||
| '@babel/preset-env', | |||
| { | |||
| useBuiltIns: 'usage', | |||
| corejs: 3, | |||
| }, | |||
| ], | |||
| ], | |||
| plugins: [ | |||
| [ | |||
| '@babel/plugin-transform-runtime', | |||
| { | |||
| regenerator: true, | |||
| } | |||
| ], | |||
| '@babel/plugin-proposal-object-rest-spread', | |||
| ], | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| test: /\.(less|css)$/i, | |||
| use: [ | |||
| { | |||
| loader: MiniCssExtractPlugin.loader, | |||
| }, | |||
| { | |||
| loader: 'css-loader', | |||
| options: { | |||
| importLoaders: 2, | |||
| url: (_url, resourcePath) => { | |||
| // only resolve URLs for dependencies | |||
| return resourcePath.includes('node_modules'); | |||
| }, | |||
| } | |||
| }, | |||
| { | |||
| loader: 'postcss-loader', | |||
| options: { | |||
| plugins: () => [ | |||
| PostCSSPresetEnv(), | |||
| ], | |||
| }, | |||
| }, | |||
| { | |||
| loader: 'less-loader', | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| test: /\.svg$/, | |||
| use: [ | |||
| { | |||
| loader: 'svg-sprite-loader', | |||
| options: { | |||
| extract: true, | |||
| spriteFilename: 'img/svg/icons.svg', | |||
| symbolId: (path) => { | |||
| const {name} = parse(path); | |||
| if (/@primer[/\\]octicons/.test(path)) { | |||
| return `octicon-${name}`; | |||
| } | |||
| return name; | |||
| }, | |||
| }, | |||
| }, | |||
| { | |||
| loader: 'svgo-loader', | |||
| }, | |||
| ], | |||
| }, | |||
| { | |||
| test: /\.(ttf|woff2?)$/, | |||
| use: [ | |||
| { | |||
| loader: 'file-loader', | |||
| options: { | |||
| name: '[name].[ext]', | |||
| outputPath: 'fonts/', | |||
| publicPath: (url) => `../fonts/${url}`, // seems required for monaco's font | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| ], | |||
| }, | |||
| plugins: [ | |||
| new VueLoaderPlugin(), | |||
| // avoid generating useless js output files for css- and svg-only chunks | |||
| new FixStyleOnlyEntriesPlugin({ | |||
| extensions: ['less', 'scss', 'css', 'svg'], | |||
| silent: true, | |||
| }), | |||
| new MiniCssExtractPlugin({ | |||
| filename: 'css/[name].css', | |||
| chunkFilename: 'css/[name].css', | |||
| }), | |||
| //new SourceMapDevToolPlugin({ | |||
| //filename: 'js/[name].js.map', | |||
| //include: [ | |||
| //'js/index.js', | |||
| //], | |||
| //}), | |||
| new SpriteLoaderPlugin({ | |||
| plainSprite: true, | |||
| }), | |||
| new MonacoWebpackPlugin({ | |||
| filename: 'js/monaco-[name].worker.js', | |||
| }) | |||
| ], | |||
| performance: { | |||
| hints: false, | |||
| maxEntrypointSize: Infinity, | |||
| maxAssetSize: Infinity, | |||
| }, | |||
| resolve: { | |||
| symlinks: false, | |||
| alias: { | |||
| vue$: 'vue/dist/vue.esm.js', // needed because vue's default export is the runtime only | |||
| }, | |||
| extensions: ['.tsx', '.ts', '.js'] | |||
| }, | |||
| watchOptions: { | |||
| ignored: [ | |||
| 'node_modules/**', | |||
| ], | |||
| }, | |||
| stats: { | |||
| children: false, | |||
| }, | |||
| }; | |||