#1652 V20220314合并到develop

Merged
lewis merged 118 commits from V20220314 into develop 2 years ago
  1. +17
    -2
      Makefile
  2. +0
    -1
      custom/public/swiper/swiper-bundle.min.js
  3. +26
    -9
      models/cloudbrain.go
  4. +15
    -14
      models/dataset_permission.go
  5. +2
    -2
      models/org.go
  6. +13
    -0
      models/topic.go
  7. +1
    -0
      modules/auth/cloudbrain.go
  8. +8
    -5
      modules/auth/modelarts.go
  9. +58
    -9
      modules/cloudbrain/cloudbrain.go
  10. +17
    -30
      modules/modelarts/modelarts.go
  11. +2
    -1
      modules/modelarts/resty.go
  12. +6
    -0
      modules/repository/fork.go
  13. +15
    -0
      modules/util/util.go
  14. +28
    -3
      options/locale/locale_en-US.ini
  15. +25
    -1
      options/locale/locale_zh-CN.ini
  16. +26
    -15
      public/home/home.js
  17. +1
    -1
      routers/admin/cloudbrains.go
  18. +3
    -3
      routers/api/v1/api.go
  19. +11
    -10
      routers/api/v1/repo/cloudbrain.go
  20. +4
    -5
      routers/api/v1/repo/modelarts.go
  21. +7
    -0
      routers/org/home.go
  22. +4
    -4
      routers/private/hook.go
  23. +6
    -1
      routers/repo/attachment.go
  24. +85
    -54
      routers/repo/cloudbrain.go
  25. +100
    -78
      routers/repo/modelarts.go
  26. +12
    -15
      routers/routes/routes.go
  27. +50
    -37
      templates/admin/cloudbrain/list.tmpl
  28. +2
    -2
      templates/explore/repo_orgtop.tmpl
  29. +76
    -3
      templates/org/home.tmpl
  30. +4
    -24
      templates/org/home_courses.tmpl
  31. +22
    -13
      templates/repo/cloudbrain/benchmark/index.tmpl
  32. +11
    -4
      templates/repo/cloudbrain/benchmark/new.tmpl
  33. +2
    -2
      templates/repo/cloudbrain/benchmark/show.tmpl
  34. +1
    -1
      templates/repo/cloudbrain/models/dir_list.tmpl
  35. +38
    -38
      templates/repo/cloudbrain/new.tmpl
  36. +2
    -2
      templates/repo/cloudbrain/show.tmpl
  37. +44
    -44
      templates/repo/debugjob/index.tmpl
  38. +3
    -3
      templates/repo/modelarts/inferencejob/index.tmpl
  39. +3
    -3
      templates/repo/modelarts/inferencejob/new.tmpl
  40. +2
    -2
      templates/repo/modelarts/inferencejob/show.tmpl
  41. +3
    -3
      templates/repo/modelarts/notebook/new.tmpl
  42. +2
    -2
      templates/repo/modelarts/notebook/show.tmpl
  43. +3
    -3
      templates/repo/modelarts/trainjob/index.tmpl
  44. +3
    -3
      templates/repo/modelarts/trainjob/new.tmpl
  45. +3
    -3
      templates/repo/modelarts/trainjob/show.tmpl
  46. +21
    -2
      templates/repo/modelarts/trainjob/version_new.tmpl
  47. +3
    -2
      templates/repo/modelmanage/index.tmpl
  48. +2
    -2
      templates/user/dashboard/feeds.tmpl
  49. +55
    -56
      web_src/js/features/cloudrbanin.js
  50. +49
    -4
      web_src/less/openi.less
  51. +274
    -0
      webpack_pro.config.js

+ 17
- 2
Makefile View File

@@ -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)


+ 0
- 1
custom/public/swiper/swiper-bundle.min.js
File diff suppressed because it is too large
View File


+ 26
- 9
models/cloudbrain.go View File

@@ -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
@@ -144,8 +146,10 @@ type Cloudbrain struct {
CkptName string //权重文件名称
ResultUrl string //推理结果的obs路径

User *User `xorm:"-"`
Repo *Repository `xorm:"-"`
User *User `xorm:"-"`
Repo *Repository `xorm:"-"`
BenchmarkTypeName string `xorm:"-"`
BenchmarkTypeRankLink string `xorm:"-"`
}

type CloudbrainInfo struct {
@@ -407,9 +411,10 @@ type BenchmarkTypes struct {
}

type BenchmarkType struct {
Id int `json:"id"`
First string `json:"first"` //一级算法类型名称
Second []*BenchmarkDataset `json:"second"`
Id int `json:"id"`
RankLink string `json:"rank_link"`
First string `json:"first"` //一级算法类型名称
Second []*BenchmarkDataset `json:"second"`
}

type BenchmarkDataset struct {
@@ -1195,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)
}
@@ -1204,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)
}
}
@@ -1304,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)
@@ -1326,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)


+ 15
- 14
models/dataset_permission.go View File

@@ -4,26 +4,27 @@

package models

import (
"code.gitea.io/gitea/modules/log"
)
import "code.gitea.io/gitea/modules/log"

// GetUserDataSetPermission returns the user permissions to the data_set
func GetUserDataSetPermission(dataSet *Dataset, user *User) (isPermit bool, err error) {
isPermit = false

switch dataSet.Status {
case DatasetStatusDeleted:
log.Error("the data_set has been deleted")
case DatasetStatusPrivate:
if !user.IsAdmin && user.ID != dataSet.UserID {
log.Error("the user is not admin nor the owner of the data_set")
if user != nil {
switch dataSet.Status {
case DatasetStatusDeleted:
log.Error("the data_set has been deleted")
case DatasetStatusPrivate:
if !user.IsAdmin && user.ID != dataSet.UserID {
log.Error("the user is not admin nor the owner of the data_set")
} else {
isPermit = true
}
case DatasetStatusPublic:
isPermit = true
default:
log.Error("the status of data_set is wrong")
}
isPermit = true
case DatasetStatusPublic:
isPermit = true
default:
log.Error("the status of data_set is wrong")
}

return isPermit, nil


+ 2
- 2
models/org.go View File

@@ -180,8 +180,8 @@ func CreateOrganization(org, owner *User) (err error) {

// Add initial creator to organization and owner team.
if _, err = sess.Insert(&OrgUser{
UID: owner.ID,
OrgID: org.ID,
UID: owner.ID,
OrgID: org.ID,
IsPublic: setting.Service.DefaultOrgMemberVisible,
}); err != nil {
return fmt.Errorf("insert org-user relation: %v", err)


+ 13
- 0
models/topic.go View File

@@ -324,3 +324,16 @@ func SaveTopics(repoID int64, topicNames ...string) error {

return sess.Commit()
}

func GetOrgTopics(orgId int64) ([]Topic, error) {
result := make([]Topic, 0)
sql := "select distinct(t.*) from repository r " +
"inner join repo_topic rt on rt.repo_id = r.id " +
"inner join topic t on rt.topic_id = t.id " +
"where r.owner_id = ? order by repo_count desc limit 50"
if e := x.SQL(sql, orgId).Find(&result); e != nil {
return nil, e
}

return result, nil
}

+ 1
- 0
modules/auth/cloudbrain.go View File

@@ -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"`


+ 8
- 5
modules/auth/modelarts.go View File

@@ -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"`


+ 58
- 9
modules/cloudbrain/cloudbrain.go View File

@@ -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
}

+ 17
- 30
modules/modelarts/modelarts.go View File

@@ -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
}



+ 2
- 1
modules/modelarts/resty.go View File

@@ -35,7 +35,8 @@ const (
//error code
modelartsIllegalToken = "ModelArts.6401"
NotebookNotFound = "ModelArts.6404"
NotebookNoPermission = "ModelArts.6403"
NotebookNoPermission = "ModelArts.6407"
NotebookInvalid = "ModelArts.6400"
)

func getRestyClient() *resty.Client {


+ 6
- 0
modules/repository/fork.go View File

@@ -86,5 +86,11 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name,
if err := models.CopyLanguageStat(oldRepo, repo); err != nil {
log.Error("Copy language stat from oldRepo failed")
}
//inherit parent repo's topics
if len(oldRepo.Topics) > 0 {
if err := models.SaveTopics(repo.ID, oldRepo.Topics...); err != nil {
log.Error("SaveTopics failed when fork,e=%v", err)
}
}
return repo, models.CopyLFS(ctx, repo, oldRepo)
}

+ 15
- 0
modules/util/util.go View File

@@ -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]
}

+ 28
- 3
options/locale/locale_en-US.ini View File

@@ -235,7 +235,7 @@ page_recommend_org_more=More Organizations
page_recommend_repo=Recommended Projects
page_recommend_repo_desc=Excellent AI projects recommendation. To show your project here,
page_recommend_repo_commit=Click here to submit.
page_recommend_repo_go=Click here to
page_recommend_repo_go=Click here to
page_recommend_repo_more=explore more projects.
page_dev_env=Collaborative Development Environment
page_dev_env_desc=Provide a collaborative development environment for AI development, which is the biggest highlight that distinguishes the OpenI AI Collaboration Platform from other traditional Git platforms.
@@ -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.
@@ -1254,6 +1258,7 @@ issues.filter_sort.moststars = Most stars
issues.filter_sort.feweststars = Fewest stars
issues.filter_sort.mostforks = Most forks
issues.filter_sort.fewestforks = Fewest forks
issues.filter_sort.downloadtimes = Most downloaded
issues.action_open = Open
issues.action_close = Close
issues.action_label = Label
@@ -2088,14 +2093,17 @@ team_unit_disabled = (Disabled)
selected_couse=Selected Courses
release_course = Publish Course
all_keywords=All keywords
all_org_topics=All
max_selectedPro= Select up to 9 public projects
custom_select_courses = Customize selected courses
custom_select_courses = Customize selected courses
recommend_remain_pro = Remain
save_fail_tips = The upper limit is exceeded
select_again = Select more than 9, please select again!
custom_select_projects = Customize selected projects
custom_select_projects = Customize selected projects
customize = Customize
selected_project=Selected Projects
fold = Fold
unfold = Unfold

form.name_reserved = The organization name '%s' is reserved.
form.name_pattern_not_allowed = The pattern '%s' is not allowed in an organization name.
@@ -2792,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

+ 25
- 1
options/locale/locale_zh-CN.ini View File

@@ -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,8 +2098,9 @@ team_permission_desc=权限
team_unit_desc=允许访问项目单元
team_unit_disabled=(已禁用)
selected_couse=精选课程
release_course = 发布课程
release_course = 发布课程
all_keywords=全部关键字
all_org_topics=全部
max_selectedPro= 最多可选9个公开项目
custom_select_courses = 自定义精选课程
recommend_remain_pro = 还能推荐
@@ -2104,6 +2109,8 @@ select_again = 选择超过9个,请重新选择!
custom_select_projects = 自定义精选项目
customize = 自定义
selected_project=精选项目
fold = 收起
unfold = 展开

form.name_reserved=组织名称 '%s' 是被保留的。
form.name_pattern_not_allowed=组织名称中不允许使用 "%s"。
@@ -2801,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 = 选择镜像或输入镜像地址

+ 26
- 15
public/home/home.js View File

@@ -113,12 +113,18 @@ socket.onmessage = function (e) {
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>"
}
else if(record.OpType == "9" || record.OpType == "5"){
branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>"
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;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
}else if(record.OpType == "17"){
}else if(record.OpType == "9"){
branch = "<a href=\"" + getRepoLink(record) + "/src/tag/" + encodeURI(record.RefName) + "\" rel=\"nofollow\">" + record.RefName + "</a>"
actionName = actionName.replace("{branch}",branch);
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
}
else if(record.OpType == "17"){
actionName = actionName.replace("{deleteBranchName}",record.RefName);
var repoLink = "<a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
actionName = actionName.replace("{repoName}",repoLink);
@@ -129,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>"
}
@@ -152,20 +162,21 @@ socket.onmessage = function (e) {
function getTaskLink(record){
var re = getRepoLink(record);
if(record.OpType == 24){
return re + "/datasets?type=" + record.Content;
re = re + "/datasets?type=" + record.Content;
}else if(record.OpType == 25){
return re + "/cloudbrain/" + record.RefName;
re = re + "/cloudbrain/" + record.Content;
}else if(record.OpType == 26){
return re + "/modelarts/notebook/" + record.Content;
re = re + "/modelarts/notebook/" + record.Content;
}else if(record.OpType == 27){
return re + "/modelarts/train-job/" + record.Content;
re = re + "/modelarts/train-job/" + record.Content;
}else if(record.OpType == 28){
return re + "/modelarts/inference-job/" + record.Content;
re = re + "/modelarts/inference-job/" + record.Content;
}else if(record.OpType == 29){
return re + "/cloudbrain/benchmark/" + record.RefName;
re = re + "/cloudbrain/benchmark/" + record.Content;
}else if(record.OpType == 30){
return re + "/modelmanage/show_model_info?name=" + record.RefName;
re = re + "/modelmanage/show_model_info?name=" + record.RefName;
}
re = encodeURI(re);
return re;
}

@@ -180,7 +191,7 @@ function getMsg(record){
}
html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + name + "/-1\" alt=\"\">"
html += " <div class=\"middle aligned content nowrap\">"
html += " <a href=\"/" + name + "\" title=\"\">" + name + "</a>"
html += " <a href=\"/" + encodeURI(name) + "\" title=\"\">" + name + "</a>"
return html;
}

@@ -192,7 +203,7 @@ function getRepotext(record){
}
}
function getRepoLink(record){
return record.Repo.OwnerName + "/" + record.Repo.Name;
return encodeURI(record.Repo.OwnerName + "/" + record.Repo.Name);

}

@@ -224,7 +235,7 @@ function getTime(UpdatedUnix,currentTime){
}

function getPRLink(record){
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record);
return encodeURI("/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record));
}
function getPRText(record){
if(record.Repo.Alias){
@@ -237,7 +248,7 @@ function getPRText(record){

function getIssueLink(record){

return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record);
return encodeURI("/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record));
}

function getIssueId(record){


+ 1
- 1
routers/admin/cloudbrains.go View File

@@ -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,
}
}


+ 3
- 3
routers/api/v1/api.go View File

@@ -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() {


+ 11
- 10
routers/api/v1/repo/cloudbrain.go View File

@@ -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,
})



+ 4
- 5
routers/api/v1/repo/modelarts.go View File

@@ -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,
})


+ 7
- 0
routers/org/home.go View File

@@ -94,6 +94,13 @@ func Home(ctx *context.Context) {
recommendCourseKeyWords, _ := repository.GetRecommendCourseKeyWords()
ctx.Data["CoursesKeywords"] = recommendCourseKeyWords

} else {
orgTopics, err := models.GetOrgTopics(org.ID)
if err != nil {
ctx.Error(500, "GetOrgTopics failed")
return
}
ctx.Data["OrgTopics"] = orgTopics
}

repos, count, err = models.SearchRepository(&models.SearchRepoOptions{


+ 4
- 4
routers/private/hook.go View File

@@ -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,


+ 6
- 1
routers/repo/attachment.go View File

@@ -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


+ 85
- 54
routers/repo/cloudbrain.go View File

@@ -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,
})
}

@@ -339,6 +342,8 @@ func CloudBrainBenchMarkShow(ctx *context.Context) {
if benchmarkTypes == nil {
if err := json.Unmarshal([]byte(setting.BenchmarkTypes), &benchmarkTypes); err != nil {
log.Error("json.Unmarshal BenchmarkTypes(%s) failed:%v", setting.BenchmarkTypes, err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
return
}
}
cloudBrainShow(ctx, tplCloudBrainBenchmarkShow)
@@ -350,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 {
@@ -404,7 +411,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) {
} else {
duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix)
}
if benchmarkTypes != nil {
if task.BenchmarkTypeID > 0 {
for _, benchmarkType := range benchmarkTypes.BenchmarkType {
if task.BenchmarkTypeID == benchmarkType.Id {
ctx.Data["BenchmarkTypeName"] = benchmarkType.First
@@ -421,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
@@ -431,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)
}

@@ -458,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 = ""
@@ -472,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"
@@ -497,7 +505,7 @@ func CloudBrainStop(ctx *context.Context) {
"result_code": resultCode,
"error_msg": errorMsg,
"status": status,
"job_id": jobID,
"id": ID,
})
}

@@ -619,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)
@@ -657,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)
}

@@ -726,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
@@ -1051,6 +1059,13 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
return
}

if benchmarkTypes == nil {
if err := json.Unmarshal([]byte(setting.BenchmarkTypes), &benchmarkTypes); err != nil {
ctx.ServerError("Get BenchmarkTypes faild:", err)
return
}
}

for i, task := range ciTasks {
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain)
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource
@@ -1061,6 +1076,16 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
duration = int64(task.Cloudbrain.UpdatedUnix) - int64(task.Cloudbrain.CreatedUnix)
}
ciTasks[i].TrainJobDuration = util.AddZero(duration/3600000) + ":" + util.AddZero(duration%3600000/60000) + ":" + util.AddZero(duration%60000/1000)
ciTasks[i].BenchmarkTypeName = ""
if task.BenchmarkTypeID > 0 {
for _, benchmarkType := range benchmarkTypes.BenchmarkType {
if task.BenchmarkTypeID == benchmarkType.Id {
ciTasks[i].BenchmarkTypeRankLink = benchmarkType.RankLink
ciTasks[i].BenchmarkTypeName = benchmarkType.First
break
}
}
}
}

pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)
@@ -1201,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
@@ -1213,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)
@@ -1258,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"])
@@ -1336,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,


+ 100
- 78
routers/repo/modelarts.go View File

@@ -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,35 +425,34 @@ 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

if task.Status != string(models.ModelArtsCreateFailed) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsStopped) {
log.Error("the job(%s) has not been stopped", task.JobName)
ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped"))
ctx.RenderWithErr("the job has not been stopped", tplDebugJobIndex, nil)
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) {
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.ServerError("DelNotebook2 failed", err)
ctx.RenderWithErr(err.Error(), tplDebugJobIndex, nil)
return
}
}

err = models.DeleteJob(task)
if err != nil {
ctx.ServerError("DeleteJob failed", err)
ctx.RenderWithErr(err.Error(), tplDebugJobIndex, nil)
return
}

@@ -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)


+ 12
- 15
routers/routes/routes.go View File

@@ -6,13 +6,14 @@ package routes

import (
"bytes"
"code.gitea.io/gitea/routers/authentication"
"encoding/gob"
"net/http"
"path"
"text/template"
"time"

"code.gitea.io/gitea/routers/authentication"

"code.gitea.io/gitea/modules/cloudbrain"

"code.gitea.io/gitea/routers/operation"
@@ -579,7 +580,7 @@ func RegisterRoutes(m *macaron.Macaron) {

m.Group("", func() {
m.Get("/attachments/:uuid", repo.GetAttachment)
}, reqSignIn)
})

m.Group("/attachments", func() {
m.Post("", repo.UploadAttachment)
@@ -989,10 +990,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)
@@ -1007,10 +1006,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)
@@ -1058,7 +1055,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)
@@ -1072,11 +1069,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)
@@ -1088,7 +1085,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)


+ 50
- 37
templates/admin/cloudbrain/list.tmpl View File

@@ -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>


+ 2
- 2
templates/explore/repo_orgtop.tmpl View File

@@ -53,8 +53,8 @@
</div>
<div class="swiper-slide">
<div class="ui card">
<a class="image" href="https://git.openi.org.cn/JD_Group">
<img src="/img/org-jd@2x-80.jpg" alt="京东" title="京东">
<a class="image" href="https://git.openi.org.cn/JDOpenISCT">
<img src="/img/org-jd@2x-80.jpg" alt="京东智能供应链开源工具" title="京东智能供应链开源工具">
</a>
</div>
</div>


+ 76
- 3
templates/org/home.tmpl View File

@@ -1,3 +1,4 @@

{{template "base/head" .}}
<div class="organization profile">
{{/* overflow: auto is the clearfix - this avoids the image going beyond
@@ -22,22 +23,55 @@
<div class="ui container">
{{template "org/navber" .}}
{{template "org/select_pro" .}}
<div class="ui stackable grid">
<div class="ui sixteen wide computer column">
<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}}?" 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}}" 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>
&nbsp{{.i18n.Tr "org.unfold"}}
</a>
{{end}}
</div>
</div>
</div>
</div>
<div class="ui stackable grid">
<div class="ui sixteen wide computer column">
<div class="ui mobile reversed stackable grid">
<div class="ui ten wide tablet eleven wide computer column">
{{if .CanCreateOrgRepo}}
<!-- {{if .CanCreateOrgRepo}}
<div class="text right">
<a class="ui green button" href="{{AppSubUrl}}/repo/create?org={{.Org.ID}}">{{.i18n.Tr "new_repo"}}</a>
</div>
{{end}}
{{end}} -->
{{template "org/repo_list" .}}
{{template "base/paginate" .}}
</div>

<div class="ui sixteen wide mobile six wide tablet five wide computer column">
<h4 class="ui top attached header">
{{if .CanCreateOrgRepo}}
<div class="text right">
<a class="ui green button" href="{{AppSubUrl}}/repo/create?org={{.Org.ID}}">{{.i18n.Tr "new_repo"}}</a>
</div>
{{end}}
<h4 class="ui top attached header" style="margin-top: 10px;">
<strong>{{.i18n.Tr "org.people"}}</strong>
<div class="ui right">
<a class="text grey" href="{{.OrgLink}}/members">{{.MembersTotal}} {{svg "octicon-chevron-right" 16}}</a>
@@ -99,3 +133,42 @@
</div>
</div>
{{template "base/footer" .}}

<script>

function isUnfold(){
// var isTrue = document.getElementById("tag_a").getAttribute("data-tag")
var isContain= document.querySelector("#key_tag").classList.contains("maxheight");
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> &nbsp {{.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> &nbsp {{.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> &nbsp {{.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> &nbsp {{.i18n.Tr "org.unfold"}}"
}
}
isShowIconBtn()
iscontinueStatus()
</script>

+ 4
- 24
templates/org/home_courses.tmpl View File

@@ -32,27 +32,13 @@
.organization-info >.container {
padding-bottom:0px !important;
}
.tag_bg{
background-color: #0366D6 !important;
color:#FFFFFF !important;
}
.course{
padding:10px 0 15px !important;
}
.course_color{
color: #FA8C16;
}
.tag_lable{
border: 1px solid rgba(232, 232, 232, 100) ;
border-radius: 4px;
color: rgba(65, 80, 88, 100);
font-family: Microsoft Yahei;
font-size: 14px;
padding: 0.3em 0.5em;
height: 30px;
text-align: center;
margin: 0.2em;
}
.tag_lable_first{
border: 1px solid rgba(232, 232, 232, 100) ;
border-radius: 4px;
@@ -65,17 +51,11 @@
margin: 0.2em;
margin-left: none;
}
.tag_key{
max-width:100%;
margin: 3px 3px;
display:inline-flex;
}

.bpadding{
padding:10px 40px
}
.omit{
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}

.noborder{
border: none !important;
}
@@ -83,7 +63,7 @@
text-align: center;
margin-top: 5px;
margin-top: 10px;
}
}
</style>


+ 22
- 13
templates/repo/cloudbrain/benchmark/index.tmpl View File

@@ -39,7 +39,7 @@
</div>
</div>
<div class="column right aligned">
<a class="ui compact orange basic icon button" href="{{$.RepoLink}}/cloudbrain/123/rate?isObjectDetcionAll=true" style="box-shadow: none;" target="_blank"><i class="large ri-trophy-fill middle aligned icon"></i>基准测试排行榜</a>
<a class="ui compact orange basic icon button" href="https://openi.org.cn/projects/Benchmark/#algType" style="box-shadow: none;" target="_blank"><i class="large ri-trophy-fill middle aligned icon"></i>基准测试排行榜</a>
{{if .Permission.CanWrite $.UnitTypeCloudBrain}}
<a class="ui green button" href="{{.RepoLink}}/cloudbrain/benchmark/create">{{$.i18n.Tr "repo.modelarts.evaluate_job.new_job"}}</a>
{{else}}
@@ -76,9 +76,12 @@
<span>{{$.i18n.Tr "repo.modelarts.status"}}</span>
</div>
<div class="two wide column text center padding0">
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
<span>{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</span>
</div>
<div class="two wide column text center padding0">
<span>{{$.i18n.Tr "repo.modelarts.createtime"}}</span>
</div>
<div class="one wide column text center padding0">
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span>
</div>
<div class="two wide column text center padding0">
@@ -99,23 +102,28 @@
<!-- 任务名 -->
<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">
<a style="font-size: 12px;" href="{{.BenchmarkTypeRankLink}}" target="_blank">
{{.BenchmarkTypeName}}
</a>
</div>
<!-- 任务创建时间 -->
<div class="two wide column text center padding0">
<span style="font-size: 12px;" class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
</div>
<!-- 任务运行时间 -->
<div class="two wide column text center padding0">
<span style="font-size: 12px;" id="duration-{{.JobID}}">{{.TrainJobDuration}}</span>
<div class="one wide column text center padding0">
<span style="font-size: 12px;" id="duration-{{.Cloudbrain.ID}}">{{.TrainJobDuration}}</span>
</div>
<!-- 计算资源 -->
<div class="two wide column text center padding0">
@@ -133,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>
@@ -146,15 +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}}


+ 11
- 4
templates/repo/cloudbrain/benchmark/new.tmpl View File

@@ -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"}}&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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}}
@@ -150,13 +150,13 @@
<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}</label>
<input disabled="disabled" style="width: 33.5%;" name="train_file" id="train_file" value="train.py" tabindex="3" autofocus required maxlength="254" >
<a href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark" target="_blank">查看样例</a>
<a id="train_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark" target="_blank">查看样例</a>
</div>

<div class="inline unite min_title field required">
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_test"}}</label>
<input disabled="disabled" style="width: 33.5%;" name="test_file" id="test_file" value="test.py" tabindex="3" autofocus required maxlength="254" >
<a href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark" target="_blank">查看样例</a>
<a id="test_href_id" href="https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark" target="_blank">查看样例</a>
</div>

@@ -190,6 +190,13 @@

function setChildType(){
let type_id = $('#benchmark_types_id').val();
if(type_id == 3){
$('#train_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_MOT_benchmark');
$('#test_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_MOT_benchmark');
}else{
$('#train_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark');
$('#test_href_id').attr('href','https://git.openi.org.cn/CV_benchmark/CV_reID_benchmark');
}
let child_selected_id = $('#benchmark_child_types_id_hidden').val();
$.get(`${repolink}/cloudbrain/benchmark/get_child_types?benchmark_type_id=${type_id}`, (data) => {
const n_length = data['child_types'].length


+ 2
- 2
templates/repo/cloudbrain/benchmark/show.tmpl View File

@@ -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>


+ 1
- 1
templates/repo/cloudbrain/models/dir_list.tmpl View File

@@ -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>


+ 38
- 38
templates/repo/cloudbrain/new.tmpl View File

@@ -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>

+ 2
- 2
templates/repo/cloudbrain/show.tmpl View File

@@ -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">


+ 44
- 44
templates/repo/debugjob/index.tmpl View File

@@ -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">&times;</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>

+ 3
- 3
templates/repo/modelarts/inferencejob/index.tmpl View File

@@ -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}}


+ 3
- 3
templates/repo/modelarts/inferencejob/new.tmpl View File

@@ -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}[^-]$/]',


+ 2
- 2
templates/repo/modelarts/inferencejob/show.tmpl View File

@@ -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>


+ 3
- 3
templates/repo/modelarts/notebook/new.tmpl View File

@@ -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"
}


+ 2
- 2
templates/repo/modelarts/notebook/show.tmpl View File

@@ -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">


+ 3
- 3
templates/repo/modelarts/trainjob/index.tmpl View File

@@ -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}}


+ 3
- 3
templates/repo/modelarts/trainjob/new.tmpl View File

@@ -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}[^-]$/]',


+ 3
- 3
templates/repo/modelarts/trainjob/show.tmpl View File

@@ -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)"})


+ 21
- 2
templates/repo/modelarts/trainjob/version_new.tmpl View File

@@ -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: [


+ 3
- 2
templates/repo/modelmanage/index.tmpl View File

@@ -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()


+ 2
- 2
templates/user/dashboard/feeds.tmpl View File

@@ -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}}


+ 55
- 56
web_src/js/features/cloudrbanin.js View File

@@ -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)
})
}


+ 49
- 4
web_src/less/openi.less View File

@@ -699,9 +699,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;
@@ -734,4 +736,47 @@ display: block;
}
.el-pagination.is-background .el-pager li:hover {
color: #5bb973 !important;
}
}

.tag_key{
max-width:100%;
margin: 3px 3px;
display:inline-flex;
}
.tag_lable{
border: 1px solid rgba(232, 232, 232, 100) ;
border-radius: 4px;
color: rgba(65, 80, 88, 100);
font-family: Microsoft Yahei;
font-size: 14px;
padding: 0.3em 0.5em;
height: 30px;
text-align: center;
margin: 0.2em;
}
.omit{
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.tag_bg{
background-color: #0366D6 !important;
color:#FFFFFF !important;
}
.margin-bottom20{
margin-bottom: 20px;
}
.maxheight{
max-height: 88px;
overflow: hidden;
}
.pad-botom{
padding-bottom:0px !important;
}
.icon_a{
position: absolute;
right: 0;
bottom: .2em;
background: #FFF;
border: none !important;
color: #0366d6 !important;
box-shadow: -15px 0px 10px #fff;
}

+ 274
- 0
webpack_pro.config.js View File

@@ -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,
},
};

Loading…
Cancel
Save