Browse Source

Merge remote-tracking branch 'origin/res-manage-v2' into point-v2

# Conflicts:
#	models/cloudbrain.go
#	options/locale/locale_en-US.ini
#	routers/repo/cloudbrain.go
#	routers/repo/modelarts.go
#	templates/repo/cloudbrain/benchmark/new.tmpl
#	templates/repo/cloudbrain/inference/new.tmpl
#	templates/repo/cloudbrain/new.tmpl
#	templates/repo/cloudbrain/trainjob/new.tmpl
#	templates/repo/grampus/trainjob/gpu/new.tmpl
#	templates/repo/grampus/trainjob/npu/new.tmpl
#	templates/repo/modelarts/inferencejob/new.tmpl
#	templates/repo/modelarts/notebook/new.tmpl
#	templates/repo/modelarts/trainjob/new.tmpl
#	templates/repo/modelarts/trainjob/version_new.tmpl
#	web_src/js/standalone/specsuse.js
tags/v1.22.9.2^2
chenyifan01 3 years ago
parent
commit
b0a12f43f0
57 changed files with 1589 additions and 358 deletions
  1. +72
    -28
      models/cloudbrain.go
  2. +6
    -12
      models/dataset.go
  3. +14
    -0
      models/repo_collaboration.go
  4. +2
    -0
      models/resource_queue.go
  5. +1
    -0
      models/resource_specification.go
  6. +3
    -3
      modules/cloudbrain/cloudbrain.go
  7. +2
    -2
      modules/grampus/grampus.go
  8. +26
    -10
      modules/modelarts/modelarts.go
  9. +215
    -0
      modules/modelarts_cd/modelarts.go
  10. +220
    -0
      modules/modelarts_cd/resty.go
  11. +42
    -0
      modules/modelarts_gateway/core/escape.go
  12. +208
    -0
      modules/modelarts_gateway/core/signer.go
  13. +75
    -7
      modules/setting/setting.go
  14. +13
    -7
      options/locale/locale_en-US.ini
  15. +9
    -2
      options/locale/locale_zh-CN.ini
  16. +2
    -2
      routers/admin/cloudbrains.go
  17. +139
    -30
      routers/api/v1/repo/cloudbrain.go
  18. +12
    -7
      routers/repo/cloudbrain.go
  19. +2
    -7
      routers/repo/dataset.go
  20. +1
    -1
      routers/repo/grampus.go
  21. +194
    -95
      routers/repo/modelarts.go
  22. +1
    -3
      routers/user/home.go
  23. +13
    -2
      services/cloudbrain/resource/resource_specification.go
  24. +12
    -4
      templates/admin/cloudbrain/list.tmpl
  25. +1
    -1
      templates/custom/wait_count_train.tmpl
  26. +11
    -4
      templates/repo/cloudbrain/benchmark/new.tmpl
  27. +39
    -15
      templates/repo/cloudbrain/benchmark/show.tmpl
  28. +9
    -1
      templates/repo/cloudbrain/inference/new.tmpl
  29. +49
    -5
      templates/repo/cloudbrain/inference/show.tmpl
  30. +23
    -15
      templates/repo/cloudbrain/new.tmpl
  31. +7
    -1
      templates/repo/cloudbrain/show.tmpl
  32. +8
    -1
      templates/repo/cloudbrain/trainjob/new.tmpl
  33. +8
    -2
      templates/repo/cloudbrain/trainjob/show.tmpl
  34. +9
    -2
      templates/repo/grampus/trainjob/gpu/new.tmpl
  35. +8
    -1
      templates/repo/grampus/trainjob/npu/new.tmpl
  36. +7
    -2
      templates/repo/grampus/trainjob/show.tmpl
  37. +9
    -1
      templates/repo/modelarts/inferencejob/new.tmpl
  38. +8
    -1
      templates/repo/modelarts/inferencejob/show.tmpl
  39. +14
    -5
      templates/repo/modelarts/notebook/new.tmpl
  40. +8
    -1
      templates/repo/modelarts/notebook/show.tmpl
  41. +26
    -3
      templates/repo/modelarts/trainjob/new.tmpl
  42. +8
    -2
      templates/repo/modelarts/trainjob/show.tmpl
  43. +11
    -51
      templates/repo/modelarts/trainjob/version_new.tmpl
  44. +2
    -2
      templates/repo/modelmanage/convertIndex.tmpl
  45. +3
    -3
      templates/repo/modelmanage/index.tmpl
  46. +1
    -1
      templates/repo/modelmanage/showinfo.tmpl
  47. +12
    -5
      templates/user/dashboard/cloudbrains.tmpl
  48. +2
    -1
      web_src/js/components/Model.vue
  49. +1
    -1
      web_src/js/components/dataset/referenceDataset.vue
  50. +5
    -2
      web_src/js/components/dataset/selectDataset.vue
  51. +5
    -1
      web_src/js/features/i18nVue.js
  52. +2
    -0
      web_src/js/standalone/specsuse.js
  53. +1
    -1
      web_src/vuepages/const/index.js
  54. +2
    -1
      web_src/vuepages/langs/config/en-US.js
  55. +2
    -1
      web_src/vuepages/langs/config/zh-CN.js
  56. +3
    -2
      web_src/vuepages/pages/resources/components/QueueDialog.vue
  57. +1
    -1
      web_src/vuepages/pages/resources/components/SceneDialog.vue

+ 72
- 28
models/cloudbrain.go View File

@@ -25,7 +25,8 @@ type ModelArtsJobStatus string
const ( const (
TypeCloudBrainOne int = iota TypeCloudBrainOne int = iota
TypeCloudBrainTwo TypeCloudBrainTwo
TypeC2Net //智算网络
TypeC2Net //智算网络
TypeCDCenter //成都智算中心


TypeCloudBrainAll = -1 TypeCloudBrainAll = -1
) )
@@ -71,6 +72,7 @@ const (
ModelArtsStopping ModelArtsJobStatus = "STOPPING" //停止中 ModelArtsStopping ModelArtsJobStatus = "STOPPING" //停止中
ModelArtsStopped ModelArtsJobStatus = "STOPPED" //停止 ModelArtsStopped ModelArtsJobStatus = "STOPPED" //停止
ModelArtsUnavailable ModelArtsJobStatus = "UNAVAILABLE" //故障 ModelArtsUnavailable ModelArtsJobStatus = "UNAVAILABLE" //故障
ModelArtsDeleting ModelArtsJobStatus = "DELETING" //删除中
ModelArtsDeleted ModelArtsJobStatus = "DELETED" //已删除 ModelArtsDeleted ModelArtsJobStatus = "DELETED" //已删除
ModelArtsResizing ModelArtsJobStatus = "RESIZING" //规格变更中 ModelArtsResizing ModelArtsJobStatus = "RESIZING" //规格变更中
ModelArtsResizFailed ModelArtsJobStatus = "RESIZE_FAILED" //规格变更失败 ModelArtsResizFailed ModelArtsJobStatus = "RESIZE_FAILED" //规格变更失败
@@ -119,6 +121,7 @@ const (
//AI center //AI center
AICenterOfCloudBrainOne = "OpenIOne" AICenterOfCloudBrainOne = "OpenIOne"
AICenterOfCloudBrainTwo = "OpenITwo" AICenterOfCloudBrainTwo = "OpenITwo"
AICenterOfChengdu = "OpenIChengdu"


//ComputeResource //ComputeResource
GPU = "GPU" GPU = "GPU"
@@ -655,23 +658,13 @@ type SpecialPools struct {
Pools []*SpecialPool `json:"pools"` Pools []*SpecialPool `json:"pools"`
} }
type SpecialPool struct { type SpecialPool struct {
Org string `json:"org"`
Type string `json:"type"`
IsExclusive bool `json:"isExclusive"`
Pool []*GpuInfo `json:"pool"`
JobType []string `json:"jobType"`
ResourceSpec []*ResourceSpec `json:"resourceSpecs"`
Flavor []*FlavorInfo `json:"flavor"`
}

type ImageInfosModelArts struct {
ImageInfo []*ImageInfoModelArts `json:"image_info"`
}

type ImageInfoModelArts struct {
Id string `json:"id"`
Value string `json:"value"`
Desc string `json:"desc"`
Org string `json:"org"`
Type string `json:"type"`
IsExclusive bool `json:"isExclusive"`
Pool []*GpuInfo `json:"pool"`
JobType []string `json:"jobType"`
ResourceSpec []*ResourceSpec `json:"resourceSpecs"`
Flavor []*setting.FlavorInfo `json:"flavor"`
} }


type PoolInfos struct { type PoolInfos struct {
@@ -777,6 +770,17 @@ type CreateNotebook2Params struct {
Volume VolumeReq `json:"volume"` Volume VolumeReq `json:"volume"`
} }


type CreateNotebookWithoutPoolParams struct {
JobName string `json:"name"`
Description string `json:"description"`
Duration int64 `json:"duration"` //ms
Feature string `json:"feature"`
Flavor string `json:"flavor"`
ImageID string `json:"image_id"`
WorkspaceID string `json:"workspace_id"`
Volume VolumeReq `json:"volume"`
}

type VolumeReq struct { type VolumeReq struct {
Capacity int `json:"capacity"` Capacity int `json:"capacity"`
Category string `json:"category"` Category string `json:"category"`
@@ -1000,6 +1004,7 @@ type NotebookGetJobTokenResult struct {
} }


type NotebookDelResult struct { type NotebookDelResult struct {
NotebookResult
InstanceID string `json:"instance_id"` InstanceID string `json:"instance_id"`
} }


@@ -1138,6 +1143,7 @@ type DatasetDownload struct {
DatasetName string `json:"dataset_name"` DatasetName string `json:"dataset_name"`
DatasetDownloadLink string `json:"dataset_download_link"` DatasetDownloadLink string `json:"dataset_download_link"`
RepositoryLink string `json:"repository_link"` RepositoryLink string `json:"repository_link"`
IsDelete bool `json:"is_delete"`
} }


type DataSource struct { type DataSource struct {
@@ -1525,12 +1531,6 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
) )
} }


if len(opts.ComputeResource) > 0 {
cond = cond.And(
builder.Eq{"cloudbrain.compute_resource": opts.ComputeResource},
)
}

if len(opts.JobTypes) > 0 { if len(opts.JobTypes) > 0 {
if opts.JobTypeNot { if opts.JobTypeNot {
cond = cond.And( cond = cond.And(
@@ -1550,7 +1550,7 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
if (opts.Cluster) != "" { if (opts.Cluster) != "" {
if opts.Cluster == "resource_cluster_openi" { if opts.Cluster == "resource_cluster_openi" {
cond = cond.And( cond = cond.And(
builder.Or(builder.Eq{"cloudbrain.type": TypeCloudBrainOne}, builder.Eq{"cloudbrain.type": TypeCloudBrainTwo}),
builder.Or(builder.Eq{"cloudbrain.type": TypeCloudBrainOne}, builder.Eq{"cloudbrain.type": TypeCloudBrainTwo}, builder.Eq{"cloudbrain.type": TypeCDCenter}),
) )
} }
if opts.Cluster == "resource_cluster_c2net" { if opts.Cluster == "resource_cluster_c2net" {
@@ -1992,9 +1992,9 @@ func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) {


func GetCloudbrainRunCountByRepoID(repoID int64) (int, error) { func GetCloudbrainRunCountByRepoID(repoID int64) (int, error) {
count, err := x.In("status", JobWaiting, JobRunning, ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, count, err := x.In("status", JobWaiting, JobRunning, ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting,
ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting, ModelArtsTrainJobInit,
ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsDeleting, ModelArtsRestarting, ModelArtsTrainJobInit,
ModelArtsTrainJobImageCreating, ModelArtsTrainJobSubmitTrying, ModelArtsTrainJobWaiting, ModelArtsTrainJobRunning, ModelArtsStopping, ModelArtsResizing, ModelArtsTrainJobImageCreating, ModelArtsTrainJobSubmitTrying, ModelArtsTrainJobWaiting, ModelArtsTrainJobRunning, ModelArtsStopping, ModelArtsResizing,
ModelArtsTrainJobScaling, ModelArtsTrainJobCheckInit, ModelArtsTrainJobCheckRunning, ModelArtsTrainJobCheckRunningCompleted).And("repo_id = ?", repoID).Count(new(Cloudbrain))
ModelArtsTrainJobScaling, ModelArtsTrainJobCheckInit, ModelArtsTrainJobCheckRunning, ModelArtsTrainJobKilling, ModelArtsTrainJobCheckRunningCompleted).And("repo_id = ?", repoID).Count(new(Cloudbrain))
return int(count), err return int(count), err
} }


@@ -2016,7 +2016,7 @@ func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTy


func GetCloudbrainNotebookCountByUserID(userID int64) (int, error) { func GetCloudbrainNotebookCountByUserID(userID int64) (int, error) {
count, err := x.In("status", ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting). count, err := x.In("status", ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting).
And("job_type = ? and user_id = ? and type = ?", JobTypeDebug, userID, TypeCloudBrainTwo).Count(new(Cloudbrain))
And("job_type = ? and user_id = ? and type in (?,?)", JobTypeDebug, userID, TypeCloudBrainTwo, TypeCDCenter).Count(new(Cloudbrain))
return int(count), err return int(count), err
} }


@@ -2494,3 +2494,47 @@ func GetCloudbrainCountByJobName(jobName, jobType string, typeCloudbrain int) (i
count, err := x.Where("job_name = ? and job_type= ? and type = ?", jobName, jobType, typeCloudbrain).Count(new(Cloudbrain)) count, err := x.Where("job_name = ? and job_type= ? and type = ?", jobName, jobType, typeCloudbrain).Count(new(Cloudbrain))
return int(count), err return int(count), err
} }

func LoadSpecs(tasks []*Cloudbrain) error {
cloudbrainIds := make([]int64, len(tasks))
for i, v := range tasks {
cloudbrainIds[i] = v.ID
}
specs := make([]*CloudbrainSpec, 0)
err := x.In("cloudbrain_id", cloudbrainIds).Find(&specs)
if err != nil {
return err
}
specMap := make(map[int64]*CloudbrainSpec)
for _, v := range specs {
specMap[v.SpecId] = v
}
for _, v := range tasks {
if specMap[v.ID] != nil {
v.Spec = specMap[v.ID].ConvertToSpecification()
}
}
return nil
}

func LoadSpecs4CloudbrainInfo(tasks []*CloudbrainInfo) error {
cloudbrainIds := make([]int64, len(tasks))
for i, v := range tasks {
cloudbrainIds[i] = v.Cloudbrain.ID
}
specs := make([]*CloudbrainSpec, 0)
err := x.In("cloudbrain_id", cloudbrainIds).Find(&specs)
if err != nil {
return err
}
specMap := make(map[int64]*CloudbrainSpec)
for _, v := range specs {
specMap[v.CloudbrainID] = v
}
for _, v := range tasks {
if specMap[v.Cloudbrain.ID] != nil {
v.Cloudbrain.Spec = specMap[v.Cloudbrain.ID].ConvertToSpecification()
}
}
return nil
}

+ 6
- 12
models/dataset.go View File

@@ -121,22 +121,20 @@ func (datasets DatasetList) loadAttachmentAttributes(opts *SearchDatasetOptions)


for i := range datasets { for i := range datasets {
if attachment.DatasetID == datasets[i].ID { if attachment.DatasetID == datasets[i].ID {
if opts.StarByMe {


if !attachment.IsPrivate{
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
}else{
permission, ok := permissionMap[datasets[i].ID] permission, ok := permissionMap[datasets[i].ID]
if !ok { if !ok {


permission = false permission = false
datasets[i].Repo.GetOwner() datasets[i].Repo.GetOwner()
if datasets[i].Repo.Owner.IsOrganization() {
if datasets[i].Repo.Owner.IsUserPartOfOrg(opts.User.ID) {
log.Info("user is member of org.")
permission = true
}
}
if !permission { if !permission {
isCollaborator, _ := datasets[i].Repo.IsCollaborator(opts.User.ID) isCollaborator, _ := datasets[i].Repo.IsCollaborator(opts.User.ID)
if isCollaborator {
isInRepoTeam,_:=datasets[i].Repo.IsInRepoTeam(opts.User.ID)

if isCollaborator ||isInRepoTeam {
log.Info("Collaborator user may visit the attach.") log.Info("Collaborator user may visit the attach.")
permission = true permission = true
} }
@@ -147,11 +145,7 @@ func (datasets DatasetList) loadAttachmentAttributes(opts *SearchDatasetOptions)


if permission { if permission {
datasets[i].Attachments = append(datasets[i].Attachments, attachment) datasets[i].Attachments = append(datasets[i].Attachments, attachment)
} else if !attachment.IsPrivate {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
} }
} else {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
} }


} }


+ 14
- 0
models/repo_collaboration.go View File

@@ -130,6 +130,20 @@ func (repo *Repository) IsCollaborator(userID int64) (bool, error) {
return repo.isCollaborator(x, userID) return repo.isCollaborator(x, userID)
} }


func (repo *Repository) IsInRepoTeam(userID int64) (bool, error) {
teams,err:=repo.GetRepoTeams()
if err!=nil || len(teams)==0{
return false,err
}
for _,team :=range teams{
if team.IsMember(userID){
return true,nil
}
}
return false,nil

}

func (repo *Repository) changeCollaborationAccessMode(e Engine, uid int64, mode AccessMode) error { func (repo *Repository) changeCollaborationAccessMode(e Engine, uid int64, mode AccessMode) error {
// Discard invalid input // Discard invalid input
if mode <= AccessModeNone || mode > AccessModeOwner { if mode <= AccessModeNone || mode > AccessModeOwner {


+ 2
- 0
models/resource_queue.go View File

@@ -71,6 +71,8 @@ func (r ResourceQueueReq) ToDTO() ResourceQueue {
q.AiCenterName = "云脑一" q.AiCenterName = "云脑一"
} else if r.AiCenterCode == AICenterOfCloudBrainTwo { } else if r.AiCenterCode == AICenterOfCloudBrainTwo {
q.AiCenterName = "云脑二" q.AiCenterName = "云脑二"
} else if r.AiCenterCode == AICenterOfChengdu {
q.AiCenterName = "启智成都智算"
} }
} }
return q return q


+ 1
- 0
models/resource_specification.go View File

@@ -525,6 +525,7 @@ func InitCloudbrainTwoSpecs() (map[string]*Specification, error) {
MemGiB: float32(i * 256), MemGiB: float32(i * 256),
GPUMemGiB: float32(32), GPUMemGiB: float32(32),
Status: SpecOffShelf, Status: SpecOffShelf,
IsAvailable: true,
} }
_, err = x.Insert(spec) _, err = x.Insert(spec)
if err != nil { if err != nil {


+ 3
- 3
modules/cloudbrain/cloudbrain.go View File

@@ -20,7 +20,7 @@ import (
const ( const (
//Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"` //Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"`
//CommandBenchmark = `echo "start benchmark";python /code/test.py;echo "end benchmark"` //CommandBenchmark = `echo "start benchmark";python /code/test.py;echo "end benchmark"`
CommandBenchmark = `echo "start benchmark";cd /benchmark && bash run_bk.sh;echo "end benchmark"`
CommandBenchmark = `echo "start benchmark";cd /benchmark && bash run_bk.sh | tee /model/benchmark-log.txt;echo "end benchmark"`
CodeMountPath = "/code" CodeMountPath = "/code"
DataSetMountPath = "/dataset" DataSetMountPath = "/dataset"
ModelMountPath = "/model" ModelMountPath = "/model"
@@ -30,8 +30,8 @@ const (
Snn4imagenetMountPath = "/snn4imagenet" Snn4imagenetMountPath = "/snn4imagenet"
BrainScoreMountPath = "/brainscore" BrainScoreMountPath = "/brainscore"
TaskInfoName = "/taskInfo" TaskInfoName = "/taskInfo"
Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s'`
BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s'`
Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s' | tee /model/benchmark-log.txt`
BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s' | tee /model/benchmark-log.txt`


SubTaskName = "task1" SubTaskName = "task1"




+ 2
- 2
modules/grampus/grampus.go View File

@@ -30,8 +30,8 @@ const (


var ( var (
poolInfos *models.PoolInfos poolInfos *models.PoolInfos
FlavorInfos *models.FlavorInfos
ImageInfos *models.ImageInfosModelArts
FlavorInfos *setting.StFlavorInfos
ImageInfos *setting.StImageInfosModelArts


SpecialPools *models.SpecialPools SpecialPools *models.SpecialPools
) )


+ 26
- 10
modules/modelarts/modelarts.go View File

@@ -1,6 +1,7 @@
package modelarts package modelarts


import ( import (
"code.gitea.io/gitea/modules/modelarts_cd"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@@ -68,10 +69,9 @@ const (


var ( var (
poolInfos *models.PoolInfos poolInfos *models.PoolInfos
FlavorInfos *models.FlavorInfos
ImageInfos *models.ImageInfosModelArts
TrainFlavorInfos *Flavor TrainFlavorInfos *Flavor
SpecialPools *models.SpecialPools
SpecialPools *models.SpecialPools
MultiNodeConfig *MultiNodes
) )


type GenerateTrainJobReq struct { type GenerateTrainJobReq struct {
@@ -168,6 +168,14 @@ type ResourcePool struct {
} `json:"resource_pool"` } `json:"resource_pool"`
} }


type MultiNodes struct{
Info []OrgMultiNode `json:"multinode"`
}
type OrgMultiNode struct{
Org string `json:"org"`
Node []int `json:"node"`
}

// type Parameter struct { // type Parameter struct {
// Label string `json:"label"` // Label string `json:"label"`
// Value string `json:"value"` // Value string `json:"value"`
@@ -754,11 +762,7 @@ func GetNotebookImageName(imageId string) (string, error) {
var validImage = false var validImage = false
var imageName = "" var imageName = ""


if ImageInfos == nil {
json.Unmarshal([]byte(setting.ImageInfos), &ImageInfos)
}

for _, imageInfo := range ImageInfos.ImageInfo {
for _, imageInfo := range setting.StImageInfos.ImageInfo {
if imageInfo.Id == imageId { if imageInfo.Id == imageId {
validImage = true validImage = true
imageName = imageInfo.Value imageName = imageInfo.Value
@@ -779,6 +783,13 @@ func InitSpecialPool() {
} }
} }


func InitMultiNode(){
if MultiNodeConfig ==nil && setting.ModelArtsMultiNode!=""{
json.Unmarshal([]byte(setting.ModelArtsMultiNode), &MultiNodeConfig)
}

}

func HandleTrainJobInfo(task *models.Cloudbrain) error { func HandleTrainJobInfo(task *models.Cloudbrain) error {


result, err := GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10)) result, err := GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10))
@@ -815,8 +826,13 @@ func HandleTrainJobInfo(task *models.Cloudbrain) error {
} }


func HandleNotebookInfo(task *models.Cloudbrain) error { func HandleNotebookInfo(task *models.Cloudbrain) error {

result, err := GetNotebook2(task.JobID)
var result *models.GetNotebook2Result
var err error
if task.Type == models.TypeCloudBrainTwo {
result, err = GetNotebook2(task.JobID)
} else if task.Type == models.TypeCDCenter {
result, err = modelarts_cd.GetNotebook(task.JobID)
}
if err != nil { if err != nil {
log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err) log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err)
return err return err


+ 215
- 0
modules/modelarts_cd/modelarts.go View File

@@ -0,0 +1,215 @@
package modelarts_cd

import (
"errors"
"strconv"
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
)

const (
//notebook
storageTypeOBS = "obs"
autoStopDuration = 4 * 60 * 60
autoStopDurationMs = 4 * 60 * 60 * 1000
MORDELART_USER_IMAGE_ENGINE_ID = -1
DataSetMountPath = "/home/ma-user/work"
NotebookEnv = "Python3"
NotebookType = "Ascend"
FlavorInfo = "Ascend: 1*Ascend 910 CPU: 24 核 96GiB (modelarts.kat1.xlarge)"

//train-job
CodePath = "/code/"
OutputPath = "/output/"
ResultPath = "/result/"
LogPath = "/log/"
JobPath = "/job/"
OrderDesc = "desc" //向下查询
OrderAsc = "asc" //向上查询
Lines = 500
TrainUrl = "train_url"
DataUrl = "data_url"
MultiDataUrl = "multi_data_url"
ResultUrl = "result_url"
CkptUrl = "ckpt_url"
DeviceTarget = "device_target"
Ascend = "Ascend"
PerPage = 10
IsLatestVersion = "1"
NotLatestVersion = "0"
VersionCountOne = 1

SortByCreateTime = "create_time"
ConfigTypeCustom = "custom"
TotalVersionCount = 1
)

var ()

type VersionInfo struct {
Version []struct {
ID int `json:"id"`
Value string `json:"value"`
Url string `json:"url"`
} `json:"version"`
}

type Flavor struct {
Info []struct {
Code string `json:"code"`
Value string `json:"value"`
} `json:"flavor"`
}

type Engine struct {
Info []struct {
ID int `json:"id"`
Value string `json:"value"`
} `json:"engine"`
}

type ResourcePool struct {
Info []struct {
ID string `json:"id"`
Value string `json:"value"`
} `json:"resource_pool"`
}

type Parameters struct {
Parameter []struct {
Label string `json:"label"`
Value string `json:"value"`
} `json:"parameter"`
}

func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error {
imageName, err := GetNotebookImageName(imageId)
if err != nil {
log.Error("GetNotebookImageName failed: %v", err.Error())
return err
}
createTime := timeutil.TimeStampNow()
jobResult, err := createNotebook(models.CreateNotebookWithoutPoolParams{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
Duration: autoStopDurationMs,
ImageID: imageId,
Feature: models.NotebookFeature,
Volume: models.VolumeReq{
Capacity: setting.Capacity,
Category: models.EVSCategory,
Ownership: models.ManagedOwnership,
},
WorkspaceID: "0",
})
if err != nil {
log.Error("createNotebook failed: %v", err.Error())
if strings.HasPrefix(err.Error(), UnknownErrorPrefix) {
log.Info("(%s)unknown error, set temp status", displayJobName)
errTemp := models.InsertCloudbrainTemp(&models.CloudbrainTemp{
JobID: models.TempJobId,
VersionID: models.TempVersionId,
Status: models.TempJobStatus,
Type: models.TypeCDCenter,
JobName: jobName,
JobType: string(models.JobTypeDebug),
})
if errTemp != nil {
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error())
return errTemp
}
}
return err
}
task := &models.Cloudbrain{
Status: jobResult.Status,
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
JobID: jobResult.ID,
JobName: jobName,
FlavorCode: spec.SourceSpecId,
DisplayJobName: displayJobName,
JobType: string(models.JobTypeDebug),
Type: models.TypeCDCenter,
Uuid: uuid,
ComputeResource: models.NPUResource,
Image: imageName,
Description: description,
CreatedUnix: createTime,
UpdatedUnix: createTime,
Spec: spec,
}

err = models.CreateCloudbrain(task)
if err != nil {
return err
}

stringId := strconv.FormatInt(task.ID, 10)
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask)
return nil
}

func GetNotebookImageName(imageId string) (string, error) {
var validImage = false
var imageName = ""

for _, imageInfo := range setting.StImageInfos.ImageInfo {
if imageInfo.Id == imageId {
validImage = true
imageName = imageInfo.Value
}
}

if !validImage {
log.Error("the image id(%s) is invalid", imageId)
return imageName, errors.New("the image id is invalid")
}

return imageName, nil
}

/*
func HandleNotebookInfo(task *models.Cloudbrain) error {

result, err := GetNotebook(task.JobID)
if err != nil {
log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err)
return err
}

if result != nil {
oldStatus := task.Status
task.Status = result.Status
if task.StartTime == 0 && result.Lease.UpdateTime > 0 {
task.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000)
}
if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) {
task.EndTime = timeutil.TimeStampNow()
}
task.CorrectCreateUnix()
task.ComputeAndSetDuration()
if oldStatus != task.Status {
notification.NotifyChangeCloudbrainStatus(task, oldStatus)
}
if task.FlavorCode == "" {
task.FlavorCode = result.Flavor
}
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err)
return err
}
}

return nil
}

*/

+ 220
- 0
modules/modelarts_cd/resty.go View File

@@ -0,0 +1,220 @@
package modelarts_cd

import (
"bytes"
"code.gitea.io/gitea/modules/modelarts_gateway/core"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

var (
httpClient *http.Client
HOST string
TOKEN string
)

const (
errorCodeExceedLimit = "ModelArts.0118"

//notebook 2.0
urlNotebook2 = "/notebooks"

//error code
modelartsIllegalToken = "ModelArts.6401"
NotebookNotFound = "ModelArts.6404"
NotebookNoPermission = "ModelArts.6407"
NotebookInvalid = "ModelArts.6400"
UnknownErrorPrefix = "UNKNOWN:"
)

func getHttpClient() *http.Client {
if httpClient == nil {
httpClient = &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
}
}
return httpClient
}

func GetNotebook(jobID string) (*models.GetNotebook2Result, error) {
var result models.GetNotebook2Result

client := getHttpClient()
s := core.Signer{
Key: setting.ModelartsCD.AccessKey,
Secret: setting.ModelartsCD.SecretKey,
}
r, _ := http.NewRequest(http.MethodGet,
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2+"/"+jobID,
nil)

r.Header.Add("content-type", "application/json")
s.Sign(r)

resp, err := client.Do(r)
if err != nil {
log.Error("client.Do failed: %s", err.Error())
return &result, fmt.Errorf("client.Do failed: %s", err.Error())
}

defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("ioutil.ReadAll failed: %s", err.Error())
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error())
}

err = json.Unmarshal(body, &result)
if err != nil {
log.Error("json.Unmarshal failed: %s", err.Error())
return &result, fmt.Errorf("son.Unmarshal failed: %s", err.Error())
}

if len(result.ErrorCode) != 0 {
log.Error("GetNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg)
return &result, fmt.Errorf("GetNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg)
}

return &result, nil
}

func ManageNotebook(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) {
var result models.NotebookActionResult

client := getHttpClient()
s := core.Signer{
Key: setting.ModelartsCD.AccessKey,
Secret: setting.ModelartsCD.SecretKey,
}
r, _ := http.NewRequest(http.MethodPost,
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2+"/"+jobID+"/"+param.Action+"?duration="+strconv.Itoa(autoStopDurationMs),
nil)

r.Header.Add("content-type", "application/json")
s.Sign(r)

resp, err := client.Do(r)
if err != nil {
log.Error("client.Do failed: %s", err.Error())
return &result, fmt.Errorf("client.Do failed: %s", err.Error())
}

defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("ioutil.ReadAll failed: %s", err.Error())
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error())
}

err = json.Unmarshal(body, &result)
if err != nil {
log.Error("json.Unmarshal failed: %s", err.Error())
return &result, fmt.Errorf("son.Unmarshal failed: %s", err.Error())
}

if len(result.ErrorCode) != 0 {
log.Error("ManageNotebook2 failed(%s): %s", result.ErrorCode, result.ErrorMsg)
return &result, fmt.Errorf("ManageNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg)
}

return &result, nil
}

func DelNotebook(jobID string) (*models.NotebookDelResult, error) {
var result models.NotebookDelResult

client := getHttpClient()
s := core.Signer{
Key: setting.ModelartsCD.AccessKey,
Secret: setting.ModelartsCD.SecretKey,
}

r, _ := http.NewRequest(http.MethodDelete,
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2+"/"+jobID,
nil)

r.Header.Add("content-type", "application/json")
s.Sign(r)

resp, err := client.Do(r)
if err != nil {
log.Error("client.Do failed: %s", err.Error())
return &result, fmt.Errorf("client.Do failed: %s", err.Error())
}

defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("ioutil.ReadAll failed: %s", err.Error())
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error())
}

err = json.Unmarshal(body, &result)
if err != nil {
log.Error("json.Unmarshal failed: %s", err.Error())
return &result, fmt.Errorf("son.Unmarshal failed: %s", err.Error())
}

if len(result.ErrorCode) != 0 {
log.Error("DelNotebook2 failed(%s): %s", result.ErrorCode, result.ErrorMsg)
return &result, fmt.Errorf("DelNotebook2 failed(%s): %s", result.ErrorCode, result.ErrorMsg)
}

return &result, nil
}

func createNotebook(createJobParams models.CreateNotebookWithoutPoolParams) (*models.CreateNotebookResult, error) {
var result models.CreateNotebookResult
client := getHttpClient()
s := core.Signer{
Key: setting.ModelartsCD.AccessKey,
Secret: setting.ModelartsCD.SecretKey,
}

req, _ := json.Marshal(createJobParams)
r, _ := http.NewRequest(http.MethodPost,
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2,
ioutil.NopCloser(bytes.NewBuffer(req)))

r.Header.Add("content-type", "application/json")
s.Sign(r)

resp, err := client.Do(r)
if err != nil {
log.Error("client.Do failed: %s", err.Error())
return &result, fmt.Errorf("client.Do failed: %s", err.Error())
}

defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("ioutil.ReadAll failed: %s", err.Error())
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error())
}

err = json.Unmarshal(body, &result)
if err != nil {
log.Error("json.Unmarshal failed: %s", err.Error())
return &result, fmt.Errorf("json.Unmarshal failed: %s", err.Error())
}

if len(result.ErrorCode) != 0 {
log.Error("createNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg)
if result.ErrorCode == errorCodeExceedLimit {
result.ErrorMsg = "所选规格使用数量已超过最大配额限制。"
}
return &result, fmt.Errorf("createNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg)
}

return &result, nil
}

+ 42
- 0
modules/modelarts_gateway/core/escape.go View File

@@ -0,0 +1,42 @@
// based on https://github.com/golang/go/blob/master/src/net/url/url.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package core

func shouldEscape(c byte) bool {
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c == '-' || c == '~' || c == '.' {
return false
}
return true
}
func escape(s string) string {
hexCount := 0
for i := 0; i < len(s); i++ {
c := s[i]
if shouldEscape(c) {
hexCount++
}
}

if hexCount == 0 {
return s
}

t := make([]byte, len(s)+2*hexCount)
j := 0
for i := 0; i < len(s); i++ {
switch c := s[i]; {
case shouldEscape(c):
t[j] = '%'
t[j+1] = "0123456789ABCDEF"[c>>4]
t[j+2] = "0123456789ABCDEF"[c&15]
j += 3
default:
t[j] = s[i]
j++
}
}
return string(t)
}

+ 208
- 0
modules/modelarts_gateway/core/signer.go View File

@@ -0,0 +1,208 @@
// HWS API Gateway Signature
// based on https://github.com/datastream/aws/blob/master/signv4.go
// Copyright (c) 2014, Xianjie

package core

import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"fmt"
"io/ioutil"
"net/http"
"sort"
"strings"
"time"
)

const (
BasicDateFormat = "20060102T150405Z"
Algorithm = "SDK-HMAC-SHA256"
HeaderXDate = "X-Sdk-Date"
HeaderHost = "host"
HeaderAuthorization = "Authorization"
HeaderContentSha256 = "X-Sdk-Content-Sha256"
)

func hmacsha256(key []byte, data string) ([]byte, error) {
h := hmac.New(sha256.New, []byte(key))
if _, err := h.Write([]byte(data)); err != nil {
return nil, err
}
return h.Sum(nil), nil
}

// Build a CanonicalRequest from a regular request string
//
// CanonicalRequest =
// HTTPRequestMethod + '\n' +
// CanonicalURI + '\n' +
// CanonicalQueryString + '\n' +
// CanonicalHeaders + '\n' +
// SignedHeaders + '\n' +
// HexEncode(Hash(RequestPayload))
func CanonicalRequest(r *http.Request, signedHeaders []string) (string, error) {
var hexencode string
var err error
if hex := r.Header.Get(HeaderContentSha256); hex != "" {
hexencode = hex
} else {
data, err := RequestPayload(r)
if err != nil {
return "", err
}
hexencode, err = HexEncodeSHA256Hash(data)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", r.Method, CanonicalURI(r), CanonicalQueryString(r), CanonicalHeaders(r, signedHeaders), strings.Join(signedHeaders, ";"), hexencode), err
}

// CanonicalURI returns request uri
func CanonicalURI(r *http.Request) string {
pattens := strings.Split(r.URL.Path, "/")
var uri []string
for _, v := range pattens {
uri = append(uri, escape(v))
}
urlpath := strings.Join(uri, "/")
if len(urlpath) == 0 || urlpath[len(urlpath)-1] != '/' {
urlpath = urlpath + "/"
}
return urlpath
}

// CanonicalQueryString
func CanonicalQueryString(r *http.Request) string {
var keys []string
query := r.URL.Query()
for key := range query {
keys = append(keys, key)
}
sort.Strings(keys)
var a []string
for _, key := range keys {
k := escape(key)
sort.Strings(query[key])
for _, v := range query[key] {
kv := fmt.Sprintf("%s=%s", k, escape(v))
a = append(a, kv)
}
}
queryStr := strings.Join(a, "&")
r.URL.RawQuery = queryStr
return queryStr
}

// CanonicalHeaders
func CanonicalHeaders(r *http.Request, signerHeaders []string) string {
var a []string
header := make(map[string][]string)
for k, v := range r.Header {
header[strings.ToLower(k)] = v
}
for _, key := range signerHeaders {
value := header[key]
if strings.EqualFold(key, HeaderHost) {
value = []string{r.Host}
}
sort.Strings(value)
for _, v := range value {
a = append(a, key+":"+strings.TrimSpace(v))
}
}
return fmt.Sprintf("%s\n", strings.Join(a, "\n"))
}

// SignedHeaders
func SignedHeaders(r *http.Request) []string {
var a []string
for key := range r.Header {
a = append(a, strings.ToLower(key))
}
sort.Strings(a)
return a
}

// RequestPayload
func RequestPayload(r *http.Request) ([]byte, error) {
if r.Body == nil {
return []byte(""), nil
}
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return []byte(""), err
}
r.Body = ioutil.NopCloser(bytes.NewBuffer(b))
return b, err
}

// Create a "String to Sign".
func StringToSign(canonicalRequest string, t time.Time) (string, error) {
hash := sha256.New()
_, err := hash.Write([]byte(canonicalRequest))
if err != nil {
return "", err
}
return fmt.Sprintf("%s\n%s\n%x",
Algorithm, t.UTC().Format(BasicDateFormat), hash.Sum(nil)), nil
}

// Create the HWS Signature.
func SignStringToSign(stringToSign string, signingKey []byte) (string, error) {
hm, err := hmacsha256(signingKey, stringToSign)
return fmt.Sprintf("%x", hm), err
}

// HexEncodeSHA256Hash returns hexcode of sha256
func HexEncodeSHA256Hash(body []byte) (string, error) {
hash := sha256.New()
if body == nil {
body = []byte("")
}
_, err := hash.Write(body)
return fmt.Sprintf("%x", hash.Sum(nil)), err
}

// Get the finalized value for the "Authorization" header. The signature parameter is the output from SignStringToSign
func AuthHeaderValue(signature, accessKey string, signedHeaders []string) string {
return fmt.Sprintf("%s Access=%s, SignedHeaders=%s, Signature=%s", Algorithm, accessKey, strings.Join(signedHeaders, ";"), signature)
}

// Signature HWS meta
type Signer struct {
Key string
Secret string
}

// SignRequest set Authorization header
func (s *Signer) Sign(r *http.Request) error {
var t time.Time
var err error
var dt string
if dt = r.Header.Get(HeaderXDate); dt != "" {
t, err = time.Parse(BasicDateFormat, dt)
}
if err != nil || dt == "" {
t = time.Now()
r.Header.Set(HeaderXDate, t.UTC().Format(BasicDateFormat))
}
signedHeaders := SignedHeaders(r)
canonicalRequest, err := CanonicalRequest(r, signedHeaders)
if err != nil {
return err
}
stringToSign, err := StringToSign(canonicalRequest, t)
if err != nil {
return err
}
signature, err := SignStringToSign(stringToSign, []byte(s.Secret))
if err != nil {
return err
}
authValue := AuthHeaderValue(signature, s.Key, signedHeaders)
r.Header.Set(HeaderAuthorization, authValue)
return nil
}

+ 75
- 7
modules/setting/setting.go View File

@@ -75,6 +75,26 @@ type C2NetSqInfos struct {
C2NetSqInfo []*C2NetSequenceInfo `json:"sequence"` C2NetSqInfo []*C2NetSequenceInfo `json:"sequence"`
} }


type StFlavorInfos struct {
FlavorInfo []*FlavorInfo `json:"flavor_info"`
}

type FlavorInfo struct {
Id int `json:"id"`
Value string `json:"value"`
Desc string `json:"desc"`
}

type StImageInfosModelArts struct {
ImageInfo []*ImageInfoModelArts `json:"image_info"`
}

type ImageInfoModelArts struct {
Id string `json:"id"`
Value string `json:"value"`
Desc string `json:"desc"`
}

var ( var (
// AppVer settings // AppVer settings
AppVer string AppVer string
@@ -538,18 +558,31 @@ var (
AllowedOrg string AllowedOrg string
ProfileID string ProfileID string
PoolInfos string PoolInfos string
Flavor string
FlavorInfos string
DebugHost string DebugHost string
ImageInfos string ImageInfos string
Capacity int Capacity int
MaxTempQueryTimes int MaxTempQueryTimes int
StFlavorInfo *StFlavorInfos
StImageInfos *StImageInfosModelArts
//train-job //train-job
ResourcePools string ResourcePools string
Engines string Engines string
EngineVersions string EngineVersions string
FlavorInfos string
TrainJobFLAVORINFOS string TrainJobFLAVORINFOS string
ModelArtsSpecialPools string ModelArtsSpecialPools string
ModelArtsMultiNode string

// modelarts-cd config
ModelartsCD = struct {
Enabled bool
EndPoint string
ProjectID string
AccessKey string
SecretKey string
ImageInfos string
FlavorInfos string
}{}


//grampus config //grampus config
Grampus = struct { Grampus = struct {
@@ -1432,9 +1465,8 @@ func NewContext() {
AllowedOrg = sec.Key("ORGANIZATION").MustString("") AllowedOrg = sec.Key("ORGANIZATION").MustString("")
ProfileID = sec.Key("PROFILE_ID").MustString("") ProfileID = sec.Key("PROFILE_ID").MustString("")
PoolInfos = sec.Key("POOL_INFOS").MustString("") PoolInfos = sec.Key("POOL_INFOS").MustString("")
Flavor = sec.Key("FLAVOR").MustString("")
ImageInfos = sec.Key("IMAGE_INFOS").MustString("") ImageInfos = sec.Key("IMAGE_INFOS").MustString("")
Capacity = sec.Key("IMAGE_INFOS").MustInt(100)
Capacity = sec.Key("CAPACITY").MustInt(100)
MaxTempQueryTimes = sec.Key("MAX_TEMP_QUERY_TIMES").MustInt(30) MaxTempQueryTimes = sec.Key("MAX_TEMP_QUERY_TIMES").MustInt(30)
ResourcePools = sec.Key("Resource_Pools").MustString("") ResourcePools = sec.Key("Resource_Pools").MustString("")
Engines = sec.Key("Engines").MustString("") Engines = sec.Key("Engines").MustString("")
@@ -1442,6 +1474,7 @@ func NewContext() {
FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("") FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("")
TrainJobFLAVORINFOS = sec.Key("TrainJob_FLAVOR_INFOS").MustString("") TrainJobFLAVORINFOS = sec.Key("TrainJob_FLAVOR_INFOS").MustString("")
ModelArtsSpecialPools = sec.Key("SPECIAL_POOL").MustString("") ModelArtsSpecialPools = sec.Key("SPECIAL_POOL").MustString("")
ModelArtsMultiNode=sec.Key("MULTI_NODE").MustString("")


sec = Cfg.Section("elk") sec = Cfg.Section("elk")
ElkUrl = sec.Key("ELKURL").MustString("") ElkUrl = sec.Key("ELKURL").MustString("")
@@ -1489,8 +1522,8 @@ func NewContext() {
Course.OrgName = sec.Key("org_name").MustString("") Course.OrgName = sec.Key("org_name").MustString("")
Course.TeamName = sec.Key("team_name").MustString("") Course.TeamName = sec.Key("team_name").MustString("")


GetGrampusConfig()
getGrampusConfig()
getModelartsCDConfig()
getModelConvertConfig() getModelConvertConfig()
} }


@@ -1513,7 +1546,22 @@ func getModelConvertConfig() {
ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35) ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35)
} }


func GetGrampusConfig() {
func getModelartsCDConfig() {
sec := Cfg.Section("modelarts-cd")

ModelartsCD.Enabled = sec.Key("ENABLED").MustBool(false)
ModelartsCD.EndPoint = sec.Key("ENDPOINT").MustString("https://modelarts.cn-southwest-228.cdzs.cn")
ModelartsCD.ProjectID = sec.Key("PROJECT_ID").MustString("")
ModelartsCD.AccessKey = sec.Key("ACCESS_KEY").MustString("")
ModelartsCD.SecretKey = sec.Key("SECRET_KEY").MustString("")
ModelartsCD.ImageInfos = sec.Key("IMAGE_INFOS").MustString("")
ModelartsCD.FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("")

getNotebookImageInfos()
getNotebookFlavorInfos()
}

func getGrampusConfig() {
sec := Cfg.Section("grampus") sec := Cfg.Section("grampus")


Grampus.Env = sec.Key("ENV").MustString("TEST") Grampus.Env = sec.Key("ENV").MustString("TEST")
@@ -1647,6 +1695,26 @@ func ensureLFSDirectory() {
} }
} }


func getNotebookImageInfos() {
if StImageInfos == nil {
if ModelartsCD.Enabled {
json.Unmarshal([]byte(ModelartsCD.ImageInfos), &StImageInfos)
} else {
json.Unmarshal([]byte(ImageInfos), &StImageInfos)
}
}
}

func getNotebookFlavorInfos() {
if StFlavorInfo == nil {
if ModelartsCD.Enabled {
json.Unmarshal([]byte(ModelartsCD.FlavorInfos), &StFlavorInfo)
} else {
json.Unmarshal([]byte(FlavorInfos), &StFlavorInfo)
}
}
}

// NewServices initializes the services // NewServices initializes the services
func NewServices() { func NewServices() {
InitDBConfig() InitDBConfig()


+ 13
- 7
options/locale/locale_en-US.ini View File

@@ -960,6 +960,7 @@ unfavorite=Unlike
favorite=Like favorite=Like
disassociate=Disassociate disassociate=Disassociate
benchmark_dataset_tip=Note: first use the dataset function to upload the model, and then select the model from the dataset list. benchmark_dataset_tip=Note: first use the dataset function to upload the model, and then select the model from the dataset list.
file_deleted=The file has been deleted


[repo] [repo]
owner = Owner owner = Owner
@@ -1079,6 +1080,7 @@ balance.total_view = Total Balance
balance.available = Available Balance: balance.available = Available Balance:
cloudbrain1 = cloudbrain1 cloudbrain1 = cloudbrain1
cloudbrain2 = cloudbrain2 cloudbrain2 = cloudbrain2
cdCenter = cd_ai_center
cloudbrain_selection = select cloudbrain cloudbrain_selection = select cloudbrain
cloudbrain_platform_selection = Select the cloudbrain platform you want to use: cloudbrain_platform_selection = Select the cloudbrain platform you want to use:
confirm_choice = Confirm confirm_choice = Confirm
@@ -1141,7 +1143,7 @@ modelarts.train_job.compute_node=Compute Node
modelarts.create_model = Create Model modelarts.create_model = Create Model
modelarts.model_label=Model Label modelarts.model_label=Model Label
modelarts.infer_dataset = Inference Dataset modelarts.infer_dataset = Inference Dataset
modelarts.train_job.label_place=Input labels, multiple labels are separated by spaces


modelarts.train_job.basic_info=Basic Info modelarts.train_job.basic_info=Basic Info
modelarts.train_job.job_status=Job Status modelarts.train_job.job_status=Job Status
@@ -1213,6 +1215,7 @@ modelarts.infer_job.select_model = Select Model
modelarts.infer_job.boot_file_helper=The startup file is the entry file for your program execution and must end in.py.Such as inference.py, main.py, example/inference.py, case/main.py. modelarts.infer_job.boot_file_helper=The startup file is the entry file for your program execution and must end in.py.Such as inference.py, main.py, example/inference.py, case/main.py.
modelarts.infer_job.tooltip = The model has been deleted and cannot be viewed. modelarts.infer_job.tooltip = The model has been deleted and cannot be viewed.
modelarts.download_log=Download log file modelarts.download_log=Download log file
modelarts.no_node_right = The value of 'Amount of Compute Node' is wrong, you have no right to use the current value of 'Amount of Compute Node'.




debug_task_not_created = Debug task has not been created debug_task_not_created = Debug task has not been created
@@ -1222,7 +1225,10 @@ model_Evaluation_not_created = Model evaluation has not been created
repo_not_initialized = Code version: You have not initialized the code repository, please <a href="%s"> initialized </a> first ; repo_not_initialized = Code version: You have not initialized the code repository, please <a href="%s"> initialized </a> first ;
debug_task_running_limit =Running time: no more than 4 hours, it will automatically stop if it exceeds 4 hours; debug_task_running_limit =Running time: no more than 4 hours, it will automatically stop if it exceeds 4 hours;
dataset_desc = Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment; dataset_desc = Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;
platform_instructions = Instructions for use: You can refer to the <a href="https://git.openi.org.cn/zeizei/OpenI_Learning"> OpenI_Learning </a> course of Openi AI collaboration platform.
platform_instructions = Instructions for use: You can refer to the <a href="https://git.openi.org.cn/zeizei/OpenI_Learning"> OpenI_Learning </a> course of Qizhi AI collaboration platform.
platform_instructions1 = Instructions for use: You can refer to the
platform_instructions2 = OpenI_Learning
platform_instructions3 = course of Openi AI collaboration platform.
model_not_exist = Model file: You do not have a model file yet, please generate and <a href="%s/modelmanage/show_model">export the model</a> through the <a href="%s/modelarts/train-job">training task</a> first ; model_not_exist = Model file: You do not have a model file yet, please generate and <a href="%s/modelmanage/show_model">export the model</a> through the <a href="%s/modelarts/train-job">training task</a> first ;
benchmark_leaderboards = Benchmark leaderboards benchmark_leaderboards = Benchmark leaderboards


@@ -1245,11 +1251,11 @@ model.convert=Model Transformation
model.list=Model List model.list=Model List
model.manage.create_new_convert_task=Create Model Transformation Task model.manage.create_new_convert_task=Create Model Transformation Task


model.manage.notcreatemodel=No model has been created.
model.manage.notcreatemodel=No model has been created
model.manage.init1=Code version: You have not initialized the code repository, please model.manage.init1=Code version: You have not initialized the code repository, please
model.manage.init2=initialized first ; model.manage.init2=initialized first ;
model.manage.createtrainjob_tip=Training task: you haven't created a training task, please create it first model.manage.createtrainjob_tip=Training task: you haven't created a training task, please create it first
model.manage.createtrainjob=Training task
model.manage.createtrainjob=Training task.
model.manage.delete=Delete Model model.manage.delete=Delete Model
model.manage.delete_confirm=Are you sure to delete this model? Once this model is deleted, it cannot be restored. model.manage.delete_confirm=Are you sure to delete this model? Once this model is deleted, it cannot be restored.
model.manage.select.trainjob=Select train task model.manage.select.trainjob=Select train task
@@ -1261,9 +1267,9 @@ model.manage.modellabel=Model label
model.manage.modeldesc=Model description model.manage.modeldesc=Model description
model.manage.baseinfo=Base Information model.manage.baseinfo=Base Information
modelconvert.notcreate=No model conversion task has been created. modelconvert.notcreate=No model conversion task has been created.
modelconvert.importfirst1=Please import first
modelconvert.importfirst2=download model
modelconvert.importfirst3=, then converts it.
modelconvert.importfirst1=Please import the
modelconvert.importfirst2=model
modelconvert.importfirst3=first, then converts it.
modelconvert.download=Download modelconvert.download=Download
modelconvert.taskname=Task name modelconvert.taskname=Task name
modelconvert.modelname=Model name modelconvert.modelname=Model name


+ 9
- 2
options/locale/locale_zh-CN.ini View File

@@ -966,6 +966,7 @@ unfavorite=取消收藏
favorite=收藏 favorite=收藏
disassociate=取消关联 disassociate=取消关联
benchmark_dataset_tip=说明:先使用数据集功能上传模型,然后从数据集列表选模型。 benchmark_dataset_tip=说明:先使用数据集功能上传模型,然后从数据集列表选模型。
file_deleted=文件已经被删除


[repo] [repo]
owner=拥有者 owner=拥有者
@@ -1080,6 +1081,7 @@ balance.total_view=余额总览
balance.available=可用余额: balance.available=可用余额:
cloudbrain1=云脑1 cloudbrain1=云脑1
cloudbrain2=云脑2 cloudbrain2=云脑2
cdCenter=成都智算中心
intelligent_net=智算网络 intelligent_net=智算网络
cloudbrain_selection=云脑选择 cloudbrain_selection=云脑选择
cloudbrain_platform_selection=选择您准备使用的云脑平台: cloudbrain_platform_selection=选择您准备使用的云脑平台:
@@ -1226,6 +1228,7 @@ modelarts.infer_job.select_model = 选择模型
modelarts.infer_job.boot_file_helper=启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如inference.py、main.py、example/inference.py、case/main.py。 modelarts.infer_job.boot_file_helper=启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如inference.py、main.py、example/inference.py、case/main.py。
modelarts.infer_job.tooltip = 该模型已删除,无法查看。 modelarts.infer_job.tooltip = 该模型已删除,无法查看。
modelarts.download_log=下载日志文件 modelarts.download_log=下载日志文件
modelarts.no_node_right = 计算节点数的值配置错误,您没有权限使用当前配置的计算节点数。




debug_task_not_created = 未创建过调试任务 debug_task_not_created = 未创建过调试任务
@@ -1236,6 +1239,10 @@ repo_not_initialized = 代码版本:您还没有初始化代码仓库,请先
debug_task_running_limit = 运行时长:最长不超过4个小时,超过4个小时将自动停止; debug_task_running_limit = 运行时长:最长不超过4个小时,超过4个小时将自动停止;
dataset_desc = 数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境; dataset_desc = 数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境;
platform_instructions = 使用说明:可以参考启智AI协作平台<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">小白训练营课程</a>。 platform_instructions = 使用说明:可以参考启智AI协作平台<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">小白训练营课程</a>。
platform_instructions1 = 使用说明:可以参考启智AI协作平台
platform_instructions2 = 小白训练营课程
platform_instructions3 = 。

model_not_exist = 模型文件:您还没有模型文件,请先通过<a href="%s/modelarts/train-job">训练任务</a>产生并 <a href="%s/modelmanage/show_model">导出模型</a> ; model_not_exist = 模型文件:您还没有模型文件,请先通过<a href="%s/modelarts/train-job">训练任务</a>产生并 <a href="%s/modelmanage/show_model">导出模型</a> ;
benchmark_leaderboards = 基准测试排行榜 benchmark_leaderboards = 基准测试排行榜


@@ -1262,7 +1269,7 @@ model.manage.notcreatemodel=未创建过模型
model.manage.init1=代码版本:您还没有初始化代码仓库,请先 model.manage.init1=代码版本:您还没有初始化代码仓库,请先
model.manage.init2=创建代码版本; model.manage.init2=创建代码版本;
model.manage.createtrainjob_tip=训练任务:您还没创建过训练任务,请先创建 model.manage.createtrainjob_tip=训练任务:您还没创建过训练任务,请先创建
model.manage.createtrainjob=训练任务
model.manage.createtrainjob=训练任务
model.manage.delete=删除模型 model.manage.delete=删除模型
model.manage.delete_confirm=你确认删除该模型么?此模型一旦删除不可恢复。 model.manage.delete_confirm=你确认删除该模型么?此模型一旦删除不可恢复。
model.manage.select.trainjob=选择训练任务 model.manage.select.trainjob=选择训练任务
@@ -1275,7 +1282,7 @@ model.manage.modeldesc=模型描述
model.manage.baseinfo=基本信息 model.manage.baseinfo=基本信息
modelconvert.notcreate=未创建过模型转换任务 modelconvert.notcreate=未创建过模型转换任务
modelconvert.importfirst1=请您先导入 modelconvert.importfirst1=请您先导入
modelconvert.importfirst2=模型下载
modelconvert.importfirst2=模型
modelconvert.importfirst3=,然后再对其进行转换。 modelconvert.importfirst3=,然后再对其进行转换。
modelconvert.download=下载 modelconvert.download=下载
modelconvert.taskname=任务名称 modelconvert.taskname=任务名称


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

@@ -92,13 +92,13 @@ func CloudBrains(ctx *context.Context) {
return return
} }


models.LoadSpecs4CloudbrainInfo(ciTasks)

for i, task := range ciTasks { for i, task := range ciTasks {
ciTasks[i].CanDebug = true ciTasks[i].CanDebug = true
ciTasks[i].CanDel = true ciTasks[i].CanDel = true
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource
ciTasks[i].Cloudbrain.AiCenter = repo.GetCloudbrainAiCenter(task.Cloudbrain, ctx) ciTasks[i].Cloudbrain.AiCenter = repo.GetCloudbrainAiCenter(task.Cloudbrain, ctx)
_, cardType, _ := repo.GetCloudbrainCardNumAndType(task.Cloudbrain)
ciTasks[i].Cloudbrain.CardType = cardType
ciTasks[i].Cloudbrain.Cluster = repo.GetCloudbrainCluster(task.Cloudbrain, ctx) ciTasks[i].Cloudbrain.Cluster = repo.GetCloudbrainCluster(task.Cloudbrain, ctx)
} }




+ 139
- 30
routers/api/v1/repo/cloudbrain.go View File

@@ -405,52 +405,159 @@ func CloudbrainDownloadLogFile(ctx *context.Context) {


func CloudbrainGetLog(ctx *context.Context) { func CloudbrainGetLog(ctx *context.Context) {
ID := ctx.Params(":id") ID := ctx.Params(":id")
startLine := ctx.QueryInt("base_line")
lines := ctx.QueryInt("lines")
endLine := startLine + lines
order := ctx.Query("order")
if order == "asc" {
endLine = startLine
startLine = endLine - lines
if startLine < 0 {
startLine = 0
}
}
job, err := models.GetCloudbrainByID(ID) job, err := models.GetCloudbrainByID(ID)
if err != nil { if err != nil {
log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"]) log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err) ctx.ServerError(err.Error(), err)
return return
} }
result := getLogFromModelDir(job.JobName, startLine, endLine)
if result == nil {
log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
return
lines := ctx.QueryInt("lines")
baseLine := ctx.Query("base_line")
order := ctx.Query("order")
var result map[string]interface{}
resultPath := "/model"
if job.JobType == string(models.JobTypeInference) {
resultPath = "/result"
}
if baseLine == "" && order == "desc" {
result = getLastLogFromModelDir(job.JobName, lines, resultPath)
} else {
startLine := ctx.QueryInt("base_line")
endLine := startLine + lines
if order == "asc" {
if baseLine == "" {
startLine = 0
endLine = lines
} else {
endLine = startLine
startLine = endLine - lines
if startLine < 0 {
startLine = 0
}
}
}
result = getLogFromModelDir(job.JobName, startLine, endLine, resultPath)
if result == nil {
log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
return
}
} }

re := map[string]interface{}{ re := map[string]interface{}{
"JobID": ID, "JobID": ID,
"LogFileName": result["FileName"], "LogFileName": result["FileName"],
"StartLine": startLine,
"EndLine": result["endLine"],
"StartLine": result["StartLine"],
"EndLine": result["EndLine"],
"Content": result["Content"], "Content": result["Content"],
"Lines": result["lines"],
"Lines": result["Lines"],
"CanLogDownload": result["FileName"] != "", "CanLogDownload": result["FileName"] != "",
} }
//result := CloudbrainGetLogByJobId(job.JobID, job.JobName) //result := CloudbrainGetLogByJobId(job.JobID, job.JobName)

ctx.JSON(http.StatusOK, re) ctx.JSON(http.StatusOK, re)
} }


func getLogFromModelDir(jobName string, startLine int, endLine int) map[string]interface{} {
prefix := "/" + setting.CBCodePathPrefix + jobName + "/model"
func getAllLineFromFile(path string) int {
count := 0
reader, err := os.Open(path)
defer reader.Close()
if err == nil {
r := bufio.NewReader(reader)
for {
_, error := r.ReadString('\n')
if error == io.EOF {
log.Info("read file completed.")
break
}
if error != nil {
log.Info("read file error." + error.Error())
break
}
count = count + 1
}
} else {
log.Info("error:" + err.Error())
}
return count
}

func getLastLogFromModelDir(jobName string, lines int, resultPath string) map[string]interface{} {
prefix := "/" + setting.CBCodePathPrefix + jobName + resultPath
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "") files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
if err != nil { if err != nil {
log.Error("query cloudbrain model failed: %v", err) log.Error("query cloudbrain model failed: %v", err)
return nil return nil
} }


re := ""
fileName := ""
count := 0
allLines := 0
startLine := 0
for _, file := range files {
if strings.HasSuffix(file.FileName, "log.txt") {
fileName = file.FileName
path := storage.GetMinioPath(jobName+resultPath+"/", file.FileName)
allLines = getAllLineFromFile(path)
startLine = allLines - lines
if startLine < 0 {
startLine = 0
}
count = allLines - startLine
log.Info("path=" + path)
reader, err := os.Open(path)
defer reader.Close()
if err == nil {
r := bufio.NewReader(reader)
for i := 0; i < allLines; i++ {
line, error := r.ReadString('\n')
if error == io.EOF {
log.Info("read file completed.")
break
}
if error != nil {
log.Info("read file error." + error.Error())
break
}
if error == nil {
if i >= startLine {
re = re + line
}
}
}
} else {
log.Info("error:" + err.Error())
}
break
}
}

return map[string]interface{}{
"JobName": jobName,
"Content": re,
"FileName": fileName,
"Lines": count,
"EndLine": allLines,
"StartLine": startLine,
}
}

func getLogFromModelDir(jobName string, startLine int, endLine int, resultPath string) map[string]interface{} {
prefix := "/" + setting.CBCodePathPrefix + jobName + resultPath
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "")
if err != nil {
log.Error("query cloudbrain model failed: %v", err)
return nil
}
if startLine == endLine {
return map[string]interface{}{
"JobName": jobName,
"Content": "",
"FileName": "",
"Lines": 0,
"EndLine": startLine,
"StartLine": startLine,
}
}
re := "" re := ""
fileName := "" fileName := ""
count := 0 count := 0
@@ -458,7 +565,7 @@ func getLogFromModelDir(jobName string, startLine int, endLine int) map[string]i
for _, file := range files { for _, file := range files {
if strings.HasSuffix(file.FileName, "log.txt") { if strings.HasSuffix(file.FileName, "log.txt") {
fileName = file.FileName fileName = file.FileName
path := storage.GetMinioPath(jobName+"/model/", file.FileName)
path := storage.GetMinioPath(jobName+resultPath+"/", file.FileName)
log.Info("path=" + path) log.Info("path=" + path)
reader, err := os.Open(path) reader, err := os.Open(path)
defer reader.Close() defer reader.Close()
@@ -467,7 +574,6 @@ func getLogFromModelDir(jobName string, startLine int, endLine int) map[string]i
for i := 0; i < endLine; i++ { for i := 0; i < endLine; i++ {
line, error := r.ReadString('\n') line, error := r.ReadString('\n')
log.Info("line=" + line) log.Info("line=" + line)
fileEndLine = i
if error == io.EOF { if error == io.EOF {
log.Info("read file completed.") log.Info("read file completed.")
break break
@@ -478,11 +584,13 @@ func getLogFromModelDir(jobName string, startLine int, endLine int) map[string]i
} }
if error == nil { if error == nil {
if i >= startLine { if i >= startLine {
fileEndLine = i
re = re + line re = re + line
count++ count++
} }
} }
} }
fileEndLine = fileEndLine + 1
} else { } else {
log.Info("error:" + err.Error()) log.Info("error:" + err.Error())
} }
@@ -491,11 +599,12 @@ func getLogFromModelDir(jobName string, startLine int, endLine int) map[string]i
} }


return map[string]interface{}{ return map[string]interface{}{
"JobName": jobName,
"Content": re,
"FileName": fileName,
"lines": count,
"endLine": fileEndLine,
"JobName": jobName,
"Content": re,
"FileName": fileName,
"Lines": count,
"EndLine": fileEndLine,
"StartLine": startLine,
} }
} }




+ 12
- 7
routers/repo/cloudbrain.go View File

@@ -787,7 +787,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
} }


} }
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, false)
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false)
ctx.Data["task"] = task ctx.Data["task"] = task
labelName := strings.Fields(task.LabelName) labelName := strings.Fields(task.LabelName)
ctx.Data["LabelName"] = labelName ctx.Data["LabelName"] = labelName
@@ -2369,7 +2369,8 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tplCloudBrainBenchmarkNew, &form) ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tplCloudBrainBenchmarkNew, &form)
return return
} }

log.Info("Command=" + command)
log.Info("ModelPath=" + storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"))
req := cloudbrain.GenerateCloudBrainTaskReq{ req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx, Ctx: ctx,
DisplayJobName: displayJobName, DisplayJobName: displayJobName,
@@ -2512,6 +2513,8 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form) ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return return
} }
log.Info("Command=" + command)
log.Info("ModelPath=" + storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"))
req := cloudbrain.GenerateCloudBrainTaskReq{ req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx, Ctx: ctx,
DisplayJobName: displayJobName, DisplayJobName: displayJobName,
@@ -2639,7 +2642,7 @@ func getInferenceJobCommand(form auth.CreateCloudBrainInferencForm) (string, err


param += " --modelname" + "=" + form.CkptName param += " --modelname" + "=" + form.CkptName


command += "python /code/" + bootFile + param + " > " + cloudbrain.ResultPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile
command += "python /code/" + bootFile + param + " | tee " + cloudbrain.ResultPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile


return command, nil return command, nil
} }
@@ -2668,7 +2671,7 @@ func getTrainJobCommand(form auth.CreateCloudBrainForm) (string, error) {
} }
} }


command += "python /code/" + bootFile + param + " | tee " + cloudbrain.ModelMountPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile
command += "python /code/" + bootFile + param + " > " + cloudbrain.ModelMountPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile


return command, nil return command, nil
} }
@@ -2713,6 +2716,8 @@ func GetCloudbrainAiCenter(task models.Cloudbrain, ctx *context.Context) string
return ctx.Tr("repo.cloudbrain1") return ctx.Tr("repo.cloudbrain1")
} else if task.Type == models.TypeCloudBrainTwo { } else if task.Type == models.TypeCloudBrainTwo {
return ctx.Tr("repo.cloudbrain2") return ctx.Tr("repo.cloudbrain2")
} else if task.Type == models.TypeCDCenter {
return ctx.Tr("repo.cdCenter")
} else if task.Type == models.TypeC2Net { } else if task.Type == models.TypeC2Net {
return getCutStringAiCenterByAiCenter(task.AiCenter) return getCutStringAiCenterByAiCenter(task.AiCenter)
} }
@@ -2727,7 +2732,7 @@ func getCutStringAiCenterByAiCenter(aiCenter string) string {


} }
func GetCloudbrainCluster(task models.Cloudbrain, ctx *context.Context) string { func GetCloudbrainCluster(task models.Cloudbrain, ctx *context.Context) string {
if task.Type == models.TypeCloudBrainOne || task.Type == models.TypeCloudBrainTwo {
if task.Type == models.TypeCloudBrainOne || task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeCDCenter {
return ctx.Tr("cloudbrain.resource_cluster_openi") return ctx.Tr("cloudbrain.resource_cluster_openi")
} else if task.Type == models.TypeC2Net { } else if task.Type == models.TypeC2Net {
return ctx.Tr("cloudbrain.resource_cluster_c2net") return ctx.Tr("cloudbrain.resource_cluster_c2net")
@@ -2814,10 +2819,10 @@ func GetCloudbrainFlavorName(task models.Cloudbrain) (string, error) {
return CloudbrainOneFlavorName, nil return CloudbrainOneFlavorName, nil
} }
} }
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeC2Net) && task.FlavorName != "" {
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeC2Net || task.Type == models.TypeCDCenter) && task.FlavorName != "" {
replaceFlavorName := strings.ReplaceAll(task.FlavorName, ":", ":") replaceFlavorName := strings.ReplaceAll(task.FlavorName, ":", ":")
return replaceFlavorName, nil return replaceFlavorName, nil
} else if task.Type == models.TypeCloudBrainTwo && task.FlavorName == "" && task.FlavorCode != "" {
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeCDCenter) && task.FlavorName == "" && task.FlavorCode != "" {
cloudbrainTwoFlavorName := getFlavorNameByFlavorCode(task.FlavorCode) cloudbrainTwoFlavorName := getFlavorNameByFlavorCode(task.FlavorCode)
return cloudbrainTwoFlavorName, nil return cloudbrainTwoFlavorName, nil
} else if task.Type == models.TypeCloudBrainTwo && task.JobType == string(models.JobTypeDebug) && task.FlavorName == "" && task.FlavorCode == "" { } else if task.Type == models.TypeCloudBrainTwo && task.JobType == string(models.JobTypeDebug) && task.FlavorName == "" && task.FlavorCode == "" {


+ 2
- 7
routers/repo/dataset.go View File

@@ -45,15 +45,10 @@ func newFilterPrivateAttachments(ctx *context.Context, list []*models.Attachment
repo.GetOwner() repo.GetOwner()
} }
permission := false permission := false
if repo.Owner.IsOrganization() && ctx.User != nil {
if repo.Owner.IsUserPartOfOrg(ctx.User.ID) {
log.Info("user is member of org.")
permission = true
}
}
if !permission && ctx.User != nil { if !permission && ctx.User != nil {
isCollaborator, _ := repo.IsCollaborator(ctx.User.ID) isCollaborator, _ := repo.IsCollaborator(ctx.User.ID)
if isCollaborator {
isInRepoTeam,_:=repo.IsInRepoTeam(ctx.User.ID)
if isCollaborator ||isInRepoTeam {
log.Info("Collaborator user may visit the attach.") log.Info("Collaborator user may visit the attach.")
permission = true permission = true
} }


+ 1
- 1
routers/repo/grampus.go View File

@@ -754,7 +754,7 @@ func GrampusTrainJobShow(ctx *context.Context) {
taskList = append(taskList, task) taskList = append(taskList, task)
prepareSpec4Show(ctx, task) prepareSpec4Show(ctx, task)
ctx.Data["version_list_task"] = taskList ctx.Data["version_list_task"] = taskList
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, false)
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false)
ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task) ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task)
ctx.Data["displayJobName"] = task.DisplayJobName ctx.Data["displayJobName"] = task.DisplayJobName




+ 194
- 95
routers/repo/modelarts.go View File

@@ -2,10 +2,12 @@ package repo


import ( import (
"archive/zip" "archive/zip"
"code.gitea.io/gitea/modules/modelarts_cd"
"code.gitea.io/gitea/services/cloudbrain/resource" "code.gitea.io/gitea/services/cloudbrain/resource"
"code.gitea.io/gitea/services/reward/point/account" "code.gitea.io/gitea/services/reward/point/account"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@@ -61,18 +63,11 @@ func DebugJobIndex(ctx *context.Context) {
if page <= 0 { if page <= 0 {
page = 1 page = 1
} }
typeCloudBrain := models.TypeCloudBrainAll
jobTypeNot := false jobTypeNot := false
if listType == models.GPUResource {
typeCloudBrain = models.TypeCloudBrainOne
} else if listType == models.NPUResource {
typeCloudBrain = models.TypeCloudBrainTwo
} else if listType == models.AllResource {
typeCloudBrain = models.TypeCloudBrainAll
} else {
log.Error("listType(%s) error", listType)
ctx.ServerError("listType error", errors.New("listType error"))
return
var computeResource string
if listType != models.AllResource {
computeResource = listType
} }


var jobTypes []string var jobTypes []string
@@ -82,10 +77,11 @@ func DebugJobIndex(ctx *context.Context) {
Page: page, Page: page,
PageSize: setting.UI.IssuePagingNum, PageSize: setting.UI.IssuePagingNum,
}, },
RepoID: repo.ID,
Type: typeCloudBrain,
JobTypeNot: jobTypeNot,
JobTypes: jobTypes,
RepoID: repo.ID,
ComputeResource: computeResource,
Type: models.TypeCloudBrainAll,
JobTypeNot: jobTypeNot,
JobTypes: jobTypes,
}) })
if err != nil { if err != nil {
ctx.ServerError("Get debugjob faild:", err) ctx.ServerError("Get debugjob faild:", err)
@@ -135,11 +131,7 @@ func notebookNewDataPrepare(ctx *context.Context) error {
return err return err
} }
ctx.Data["attachments"] = attachs ctx.Data["attachments"] = attachs

if modelarts.ImageInfos == nil {
json.Unmarshal([]byte(setting.ImageInfos), &modelarts.ImageInfos)
}
ctx.Data["images"] = modelarts.ImageInfos.ImageInfo
ctx.Data["images"] = setting.StImageInfos.ImageInfo


prepareCloudbrainTwoDebugSpecs(ctx) prepareCloudbrainTwoDebugSpecs(ctx)


@@ -152,11 +144,15 @@ func notebookNewDataPrepare(ctx *context.Context) error {
} }


func prepareCloudbrainTwoDebugSpecs(ctx *context.Context) { func prepareCloudbrainTwoDebugSpecs(ctx *context.Context) {
aiCenterCode := models.AICenterOfCloudBrainTwo
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
}
noteBookSpecs, _ := resource.FindAvailableSpecs(ctx.User.ID, models.FindSpecsOptions{ noteBookSpecs, _ := resource.FindAvailableSpecs(ctx.User.ID, models.FindSpecsOptions{
JobType: models.JobTypeDebug, JobType: models.JobTypeDebug,
ComputeResource: models.NPU, ComputeResource: models.NPU,
Cluster: models.OpenICluster, Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo,
AiCenterCode: aiCenterCode,
}) })
ctx.Data["Specs"] = noteBookSpecs ctx.Data["Specs"] = noteBookSpecs
} }
@@ -245,12 +241,15 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm
return return
} }
} }

var aiCenterCode = models.AICenterOfCloudBrainTwo
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{ spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeDebug, JobType: models.JobTypeDebug,
ComputeResource: models.NPU, ComputeResource: models.NPU,
Cluster: models.OpenICluster, Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
AiCenterCode: aiCenterCode})
if err != nil || spec == nil { if err != nil || spec == nil {
notebookNewDataPrepare(ctx) notebookNewDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsNotebookNew, &form) ctx.RenderWithErr("Resource specification not available", tplModelArtsNotebookNew, &form)
@@ -263,7 +262,12 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm
return return
} }


err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec)
if setting.ModelartsCD.Enabled {
err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec)
} else {
err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec)
}

if err != nil { if err != nil {
log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"])
notebookNewDataPrepare(ctx) notebookNewDataPrepare(ctx)
@@ -301,7 +305,7 @@ func NotebookShow(ctx *context.Context) {
datasetDownload := make([]models.DatasetDownload, 0) datasetDownload := make([]models.DatasetDownload, 0)
if ctx.IsSigned { if ctx.IsSigned {
if task.Uuid != "" && task.UserID == ctx.User.ID { if task.Uuid != "" && task.UserID == ctx.User.ID {
datasetDownload = GetCloudBrainDataSetInfo(task.Uuid, true)
datasetDownload = GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, true)
} }
} }
user, err := models.GetUserByID(task.UserID) user, err := models.GetUserByID(task.UserID)
@@ -330,36 +334,52 @@ func NotebookShow(ctx *context.Context) {
ctx.HTML(200, tplModelArtsNotebookShow) ctx.HTML(200, tplModelArtsNotebookShow)
} }


func GetCloudBrainDataSetInfo(uuid string, isNeedDown bool) []models.DatasetDownload {
func GetCloudBrainDataSetInfo(uuid string, datasetname string, isNeedDown bool) []models.DatasetDownload {
datasetDownload := make([]models.DatasetDownload, 0) datasetDownload := make([]models.DatasetDownload, 0)

if len(uuid) == 0 {
return datasetDownload
}
uuidList := strings.Split(uuid, ";") uuidList := strings.Split(uuid, ";")
for _, uuidStr := range uuidList {
datasetnameList := strings.Split(datasetname, ";")
for i, uuidStr := range uuidList {
name := ""
link := ""
url := ""
isDelete := false
attachment, err := models.GetAttachmentByUUID(uuidStr) attachment, err := models.GetAttachmentByUUID(uuidStr)
if err != nil { if err != nil {
log.Error("GetAttachmentByUUID failed:%v", err.Error()) log.Error("GetAttachmentByUUID failed:%v", err.Error())
return datasetDownload
}
dataset, err := models.GetDatasetByID(attachment.DatasetID)
if err != nil {
log.Error("GetDatasetByID failed:%v", err.Error())
return datasetDownload
}
repo, err := models.GetRepositoryByID(dataset.RepoID)
if err != nil {
log.Error("GetRepositoryByID failed:%v", err.Error())
return datasetDownload
}
url := ""
if isNeedDown {
url = attachment.S3DownloadURL()
if len(datasetnameList) <= i || len(datasetname) == 0 {
continue
}
name = datasetnameList[i]
isDelete = true
} else {
name = attachment.Name
dataset, err := models.GetDatasetByID(attachment.DatasetID)
if err != nil {
log.Error("GetDatasetByID failed:%v", err.Error())
} else {
repo, err := models.GetRepositoryByID(dataset.RepoID)
if err != nil {
log.Error("GetRepositoryByID failed:%v", err.Error())
} else {
link = repo.Link() + "/datasets"
}
}
if isNeedDown {
url = attachment.S3DownloadURL()
}
} }

datasetDownload = append(datasetDownload, models.DatasetDownload{ datasetDownload = append(datasetDownload, models.DatasetDownload{
DatasetName: attachment.Name,
DatasetName: name,
DatasetDownloadLink: url, DatasetDownloadLink: url,
RepositoryLink: repo.Link() + "/datasets",
RepositoryLink: link,
IsDelete: isDelete,
}) })
} }
log.Info("dataset length=" + fmt.Sprint(len(datasetDownload)))
return datasetDownload return datasetDownload
} }


@@ -377,36 +397,16 @@ func setShowSpecBySpecialPoolConfig(ctx *context.Context, findSpec bool, task *m
} }
} }


func NotebookDebug(ctx *context.Context) {
var jobID = ctx.Params(":jobid")

result, err := modelarts.GetJob(jobID)
if err != nil {
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
return
}

res, err := modelarts.GetJobToken(jobID)
if err != nil {
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
return
}

urls := strings.Split(result.Spec.Annotations.Url, "/")
urlPrefix := result.Spec.Annotations.TargetDomain
for i, url := range urls {
if i > 2 {
urlPrefix += "/" + url
}
}

debugUrl := urlPrefix + "?token=" + res.Token
ctx.Redirect(debugUrl)
}

func NotebookDebug2(ctx *context.Context) { func NotebookDebug2(ctx *context.Context) {
var err error
var result *models.GetNotebook2Result
task := ctx.Cloudbrain task := ctx.Cloudbrain
result, err := modelarts.GetNotebook2(task.JobID)
if task.Type == models.TypeCloudBrainTwo {
result, err = modelarts.GetNotebook2(task.JobID)
} else if task.Type == models.TypeCDCenter {
result, err = modelarts_cd.GetNotebook(task.JobID)
}

if err != nil { if err != nil {
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil) ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
return return
@@ -454,11 +454,16 @@ func NotebookRestart(ctx *context.Context) {
errorMsg = "Resource specification not available" errorMsg = "Resource specification not available"
break break
} }

aiCenterCode := models.AICenterOfCloudBrainTwo
if task.Type == models.TypeCDCenter {
aiCenterCode = models.AICenterOfChengdu
}
spec, err = resource.GetAndCheckSpec(ctx.User.ID, oldSpec.ID, models.FindSpecsOptions{ spec, err = resource.GetAndCheckSpec(ctx.User.ID, oldSpec.ID, models.FindSpecsOptions{
JobType: models.JobType(task.JobType), JobType: models.JobType(task.JobType),
ComputeResource: models.NPU, ComputeResource: models.NPU,
Cluster: models.OpenICluster, Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
AiCenterCode: aiCenterCode})
if err != nil || spec == nil { if err != nil || spec == nil {
log.Error("NotebookManage GetAndCheckSpec error.task.id = %d", task.ID) log.Error("NotebookManage GetAndCheckSpec error.task.id = %d", task.ID)
errorMsg = "Resource specification not support any more" errorMsg = "Resource specification not support any more"
@@ -474,7 +479,13 @@ func NotebookRestart(ctx *context.Context) {
Action: models.ActionStart, Action: models.ActionStart,
} }


res, err := modelarts.ManageNotebook2(task.JobID, param)
var res *models.NotebookActionResult
if task.Type == models.TypeCloudBrainTwo {
res, err = modelarts.ManageNotebook2(task.JobID, param)
} else if task.Type == models.TypeCDCenter {
res, err = modelarts_cd.ManageNotebook(task.JobID, param)
}

if err != nil { if err != nil {
log.Error("ManageNotebook2(%s) failed:%v", task.DisplayJobName, err.Error(), ctx.Data["MsgID"]) log.Error("ManageNotebook2(%s) failed:%v", task.DisplayJobName, err.Error(), ctx.Data["MsgID"])
/* 暂不处理再次调试502的场景,详情见方案 /* 暂不处理再次调试502的场景,详情见方案
@@ -559,7 +570,14 @@ func NotebookStop(ctx *context.Context) {
Action: models.ActionStop, Action: models.ActionStop,
} }


res, err := modelarts.ManageNotebook2(task.JobID, param)
var err error
var res *models.NotebookActionResult
if task.Type == models.TypeCloudBrainTwo {
res, err = modelarts.ManageNotebook2(task.JobID, param)
} else if task.Type == models.TypeCDCenter {
res, err = modelarts_cd.ManageNotebook(task.JobID, param)
}

if err != nil { if err != nil {
log.Error("ManageNotebook2(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) log.Error("ManageNotebook2(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"])
resultCode = "-1" resultCode = "-1"
@@ -609,7 +627,13 @@ func NotebookDel(ctx *context.Context) {
return return
} }


_, err := modelarts.DelNotebook2(task.JobID)
var err error
if task.Type == models.TypeCloudBrainTwo {
_, err = modelarts.DelNotebook2(task.JobID)
} else if task.Type == models.TypeCDCenter {
_, err = modelarts_cd.DelNotebook(task.JobID)
}

if err != nil { if err != nil {
log.Error("DelNotebook2(%s) failed:%v", task.JobName, err.Error()) log.Error("DelNotebook2(%s) failed:%v", task.JobName, err.Error())
if strings.Contains(err.Error(), modelarts.NotebookNotFound) || strings.Contains(err.Error(), modelarts.NotebookNoPermission) || strings.Contains(err.Error(), modelarts.NotebookInvalid) { if strings.Contains(err.Error(), modelarts.NotebookNotFound) || strings.Contains(err.Error(), modelarts.NotebookNoPermission) || strings.Contains(err.Error(), modelarts.NotebookInvalid) {
@@ -760,6 +784,8 @@ func trainJobNewDataPrepare(ctx *context.Context) error {
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount ctx.Data["WaitCount"] = waitCount


setMultiNodeIfConfigureMatch(ctx)

return nil return nil
} }


@@ -773,6 +799,18 @@ func prepareCloudbrainTwoTrainSpecs(ctx *context.Context) {
ctx.Data["Specs"] = noteBookSpecs ctx.Data["Specs"] = noteBookSpecs
} }


func setMultiNodeIfConfigureMatch(ctx *context.Context) {
modelarts.InitMultiNode()
if modelarts.MultiNodeConfig != nil {
for _, info := range modelarts.MultiNodeConfig.Info {
if isInOrg, _ := models.IsOrganizationMemberByOrgName(info.Org, ctx.User.ID); isInOrg {
ctx.Data["WorkNode"] = info.Node
break
}
}
}
}

func setSpecBySpecialPoolConfig(ctx *context.Context, jobType string) { func setSpecBySpecialPoolConfig(ctx *context.Context, jobType string) {
modelarts.InitSpecialPool() modelarts.InitSpecialPool()


@@ -881,6 +919,7 @@ func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArts
ctx.Data["datasetType"] = models.TypeCloudBrainTwo ctx.Data["datasetType"] = models.TypeCloudBrainTwo
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount ctx.Data["WaitCount"] = waitCount
setMultiNodeIfConfigureMatch(ctx)


return nil return nil
} }
@@ -944,6 +983,11 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error {
ctx.Data["engine_versions"] = versionInfos.Version ctx.Data["engine_versions"] = versionInfos.Version


prepareCloudbrainTwoTrainSpecs(ctx) prepareCloudbrainTwoTrainSpecs(ctx)
spec, _ := resource.GetCloudbrainSpec(task.ID)
if spec != nil {
log.Info("spec_id = %d", spec.ID)
ctx.Data["spec_id"] = spec.ID
}


var Parameters modelarts.Parameters var Parameters modelarts.Parameters
if err = json.Unmarshal([]byte(task.Parameters), &Parameters); err != nil { if err = json.Unmarshal([]byte(task.Parameters), &Parameters); err != nil {
@@ -959,14 +1003,17 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error {
} }
_, _, datasetNames, _, err := getDatasUrlListByUUIDS(task.Uuid) _, _, datasetNames, _, err := getDatasUrlListByUUIDS(task.Uuid)
if err != nil { if err != nil {
ctx.ServerError("GetAllUserAttachments failed:", err)
return err
log.Info("query dataset error," + err.Error())
//ctx.ServerError("GetAllUserAttachments failed:", err)
//return err
} else {
ctx.Data["dataset_name"] = datasetNames
} }
ctx.Data["branches"] = branches ctx.Data["branches"] = branches
ctx.Data["branch_name"] = task.BranchName ctx.Data["branch_name"] = task.BranchName
ctx.Data["description"] = task.Description ctx.Data["description"] = task.Description
ctx.Data["boot_file"] = task.BootFile ctx.Data["boot_file"] = task.BootFile
ctx.Data["dataset_name"] = datasetNames
ctx.Data["work_server_number"] = task.WorkServerNumber ctx.Data["work_server_number"] = task.WorkServerNumber
ctx.Data["flavor_name"] = task.FlavorName ctx.Data["flavor_name"] = task.FlavorName
ctx.Data["engine_name"] = task.EngineName ctx.Data["engine_name"] = task.EngineName
@@ -1099,6 +1146,13 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
VersionCount := modelarts.VersionCountOne VersionCount := modelarts.VersionCountOne
EngineName := form.EngineName EngineName := form.EngineName


errStr := checkMultiNode(ctx.User.ID, form.WorkServerNumber)
if errStr != "" {
trainJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr(errStr), tplModelArtsTrainJobNew, &form)
return
}

count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID) count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID)
if err != nil { if err != nil {
log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -1344,6 +1398,48 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job")
} }


func checkMultiNode(userId int64, serverNum int) string {
if serverNum == 1 {
return ""
}
modelarts.InitMultiNode()
var isServerNumValid = false
if modelarts.MultiNodeConfig != nil {
for _, info := range modelarts.MultiNodeConfig.Info {
if isInOrg, _ := models.IsOrganizationMemberByOrgName(info.Org, userId); isInOrg {
if isInNodes(info.Node, serverNum) {
isServerNumValid = true
break
}

}
}
}
if isServerNumValid {
return ""
} else {
return "repo.modelarts.no_node_right"
}
}
func checkInferenceJobMultiNode(userId int64, serverNum int) string {
if serverNum == 1 {
return ""
}

return "repo.modelarts.no_node_right"

}

func isInNodes(nodes []int, num int) bool {
for _, node := range nodes {
if node == num {
return true
}
}
return false

}

func getUserCommand(engineId int, req *modelarts.GenerateTrainJobReq) (string, string) { func getUserCommand(engineId int, req *modelarts.GenerateTrainJobReq) (string, string) {
userImageUrl := "" userImageUrl := ""
userCommand := "" userCommand := ""
@@ -1378,6 +1474,13 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
ctx.Data["PageIsTrainJob"] = true ctx.Data["PageIsTrainJob"] = true
var jobID = ctx.Params(":jobid") var jobID = ctx.Params(":jobid")


errStr := checkMultiNode(ctx.User.ID, form.WorkServerNumber)
if errStr != "" {
versionErrorDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr(errStr), tplModelArtsTrainJobVersionNew, &form)
return
}

count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID) count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID)
if err != nil { if err != nil {
log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -1723,10 +1826,6 @@ func paramCheckCreateTrainJob(form auth.CreateModelArtsTrainJobForm) error {
return errors.New("启动文件必须是python文件") return errors.New("启动文件必须是python文件")
} }


if form.WorkServerNumber > 2 || form.WorkServerNumber < 1 {
log.Error("the WorkServerNumber(%d) must be in (1,2)", form.WorkServerNumber)
return errors.New("计算节点数必须在1-2之间")
}
if form.BranchName == "" { if form.BranchName == "" {
log.Error("the branch must not be null!", form.BranchName) log.Error("the branch must not be null!", form.BranchName)
return errors.New("代码分支不能为空!") return errors.New("代码分支不能为空!")
@@ -1832,7 +1931,7 @@ func TrainJobShow(ctx *context.Context) {
} else { } else {
VersionListTasks[i].Parameters = "" VersionListTasks[i].Parameters = ""
} }
datasetList = append(datasetList, GetCloudBrainDataSetInfo(task.Uuid, false))
datasetList = append(datasetList, GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false))
VersionListTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) VersionListTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain)
VersionListTasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) VersionListTasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain)


@@ -2030,6 +2129,13 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference
ckptUrl := "/" + form.TrainUrl + form.CkptName ckptUrl := "/" + form.TrainUrl + form.CkptName
log.Info("ckpt url:" + ckptUrl) log.Info("ckpt url:" + ckptUrl)


errStr := checkInferenceJobMultiNode(ctx.User.ID, form.WorkServerNumber)
if errStr != "" {
inferenceJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr(errStr), tplModelArtsInferenceJobNew, &form)
return
}

count, err := models.GetCloudbrainInferenceJobCountByUserID(ctx.User.ID) count, err := models.GetCloudbrainInferenceJobCountByUserID(ctx.User.ID)
if err != nil { if err != nil {
log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -2264,7 +2370,7 @@ func checkModelArtsSpecialPool(ctx *context.Context, flavorCode string, jobType
if !isMatchPool { if !isMatchPool {
isMatchSpec := false isMatchSpec := false
if jobType == string(models.JobTypeDebug) { if jobType == string(models.JobTypeDebug) {
for _, flavor := range modelarts.FlavorInfos.FlavorInfo {
for _, flavor := range setting.StFlavorInfo.FlavorInfo {
if flavor.Value == flavorCode { if flavor.Value == flavorCode {
isMatchSpec = true isMatchSpec = true
break break
@@ -2477,14 +2583,7 @@ func inferenceJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModel
return err return err
} }
ctx.Data["engine_versions"] = versionInfos.Version ctx.Data["engine_versions"] = versionInfos.Version

var flavorInfos modelarts.Flavor
if err = json.Unmarshal([]byte(setting.TrainJobFLAVORINFOS), &flavorInfos); err != nil {
ctx.ServerError("json.Unmarshal failed:", err)
return err
}
ctx.Data["flavor_infos"] = flavorInfos.Info
setSpecBySpecialPoolConfig(ctx, string(models.JobTypeInference))
prepareCloudbrainTwoInferenceSpecs(ctx)


configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom)
if err != nil { if err != nil {
@@ -2567,7 +2666,7 @@ func InferenceJobShow(ctx *context.Context) {
ctx.Data["displayJobName"] = task.DisplayJobName ctx.Data["displayJobName"] = task.DisplayJobName
ctx.Data["task"] = task ctx.Data["task"] = task
ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task) ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task)
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, false)
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false)
tempUids := []int64{} tempUids := []int64{}
tempUids = append(tempUids, task.UserID) tempUids = append(tempUids, task.UserID)
JobCreater, err := models.GetUserNamesByIDs(tempUids) JobCreater, err := models.GetUserNamesByIDs(tempUids)


+ 1
- 3
routers/user/home.go View File

@@ -836,14 +836,12 @@ func Cloudbrains(ctx *context.Context) {
ctx.ServerError("Get job failed:", err) ctx.ServerError("Get job failed:", err)
return return
} }
models.LoadSpecs4CloudbrainInfo(ciTasks)
for i, task := range ciTasks { for i, task := range ciTasks {
ciTasks[i].CanDebug = true ciTasks[i].CanDebug = true
ciTasks[i].CanDel = true ciTasks[i].CanDel = true
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource
ciTasks[i].Cloudbrain.AiCenter = repo.GetCloudbrainAiCenter(task.Cloudbrain, ctx) ciTasks[i].Cloudbrain.AiCenter = repo.GetCloudbrainAiCenter(task.Cloudbrain, ctx)
_, cardType, _ := repo.GetCloudbrainCardNumAndType(task.Cloudbrain)
ciTasks[i].Cloudbrain.CardType = cardType
ciTasks[i].Cloudbrain.Cluster = repo.GetCloudbrainCluster(task.Cloudbrain, ctx) ciTasks[i].Cloudbrain.Cluster = repo.GetCloudbrainCluster(task.Cloudbrain, ctx)


} }


+ 13
- 2
services/cloudbrain/resource/resource_specification.go View File

@@ -438,8 +438,12 @@ func findCloudbrainOneSpecFromRemote(task *models.Cloudbrain) (*models.Specifica
var shmMB float32 var shmMB float32
if jobRes.Config.TaskRoles != nil && len(jobRes.Config.TaskRoles) > 0 { if jobRes.Config.TaskRoles != nil && len(jobRes.Config.TaskRoles) > 0 {
shmMB = float32(jobRes.Config.TaskRoles[0].ShmMB) / 1024 shmMB = float32(jobRes.Config.TaskRoles[0].ShmMB) / 1024
if jobRes.Config.TaskRoles[0].ShmMB == 103600 {
shmMB = 100
} else if jobRes.Config.TaskRoles[0].ShmMB == 51800 {
shmMB = 50
}
} }

opt := models.FindSpecsOptions{ opt := models.FindSpecsOptions{
ComputeResource: task.ComputeResource, ComputeResource: task.ComputeResource,
Cluster: models.OpenICluster, Cluster: models.OpenICluster,
@@ -538,6 +542,12 @@ func findCloudbrainOneSpecFromConfig(task *models.Cloudbrain) (*models.Specifica
task.ComputeResource = models.GPU task.ComputeResource = models.GPU
} }


shareMemMiB := float32(specConfig.ShareMemMiB) / 1024
if specConfig.ShareMemMiB == 103600 {
shareMemMiB = 100
} else if specConfig.ShareMemMiB == 51800 {
shareMemMiB = 50
}
opt := models.FindSpecsOptions{ opt := models.FindSpecsOptions{
JobType: models.JobType(task.JobType), JobType: models.JobType(task.JobType),
ComputeResource: task.ComputeResource, ComputeResource: task.ComputeResource,
@@ -550,7 +560,7 @@ func findCloudbrainOneSpecFromConfig(task *models.Cloudbrain) (*models.Specifica
UseCpuCores: true, UseCpuCores: true,
MemGiB: float32(specConfig.MemMiB) / 1024, MemGiB: float32(specConfig.MemMiB) / 1024,
UseMemGiB: true, UseMemGiB: true,
ShareMemGiB: float32(specConfig.ShareMemMiB) / 1024,
ShareMemGiB: shareMemMiB,
UseShareMemGiB: true, UseShareMemGiB: true,
RequestAll: true, RequestAll: true,
} }
@@ -639,5 +649,6 @@ func InitQueueAndSpec(opt models.FindSpecsOptions, aiCenterName string, remark s
GPUMemGiB: opt.GPUMemGiB, GPUMemGiB: opt.GPUMemGiB,
ShareMemGiB: opt.ShareMemGiB, ShareMemGiB: opt.ShareMemGiB,
Status: models.SpecOffShelf, Status: models.SpecOffShelf,
IsAvailable: true,
}) })
} }

+ 12
- 4
templates/admin/cloudbrain/list.tmpl View File

@@ -1,4 +1,5 @@
{{template "base/head" .}} {{template "base/head" .}}
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<!-- 弹窗 --> <!-- 弹窗 -->
<div id="mask"> <div id="mask">
<div id="loadingPage"> <div id="loadingPage">
@@ -175,10 +176,17 @@
</div> </div>
<!-- XPU类型 --> <!-- XPU类型 -->
<div class="one wide column text center nowrap" style="width:8% !important;"> <div class="one wide column text center nowrap" style="width:8% !important;">
<span style="font-size: 12px;" title="{{.CardType}}">
{{if .CardType}}{{.CardType}}{{else}}--{{end}}
</span>
</div>
<span style="font-size: 12px;" title="" class="card_type_{{.DisplayJobName}}_{{$JobID}}"></span>
</div>
<script>
(function(){
var spec = {{.Spec}} || {};
var cardType = getListValueWithKey(ACC_CARD_TYPE, spec.AccCardType) || '--';
var spanEl = document.querySelector('.card_type_{{.DisplayJobName}}_{{$JobID}}');
spanEl.setAttribute('title', cardType);
spanEl.innerText = cardType;
})();
</script>
<!-- 创建者 --> <!-- 创建者 -->
<div class="one wide column text center nowrap" style="width:4% !important;"> <div class="one wide column text center nowrap" style="width:4% !important;">
{{if .User.Name}} {{if .User.Name}}


+ 1
- 1
templates/custom/wait_count_train.tmpl View File

@@ -18,7 +18,7 @@
></i> ></i>
<span id="gpu-nums" style="font-size: 12px" <span id="gpu-nums" style="font-size: 12px"
>{{.ctx.i18n.Tr "repo.wait_count_start"}} >{{.ctx.i18n.Tr "repo.wait_count_start"}}
{{if .type}}
{{if .ctx.QueuesDetail}}
{{ $gpuQueue }} {{ $gpuQueue }}
{{else}} {{else}}
{{.ctx.WaitCount}} {{.ctx.WaitCount}}


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

@@ -130,7 +130,7 @@
<div class="required min_title inline field" style="margin-top:2rem;"> <div class="required min_title inline field" style="margin-top:2rem;">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48" <select id="__specs__" class="ui search dropdown width48"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}"
{{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}
name="spec_id"> name="spec_id">
</select> </select>
@@ -202,7 +202,7 @@
<div class="required unite inline min_title fields" style="width: 90%;margin-left: 5.7rem;">&nbsp; <div class="required unite inline min_title fields" style="width: 90%;margin-left: 5.7rem;">&nbsp;
<div class="required eight wide field"> <div class="required eight wide field">
<label style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</label> <label style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</label>
<select class="ui fluid selection search dropdown" id="benchmark_types_id" <select class="ui fluid selection search dropdown" id="benchmark_types_id"
name="benchmark_types_id"> name="benchmark_types_id">
{{range .benchmark_types}} {{range .benchmark_types}}
@@ -240,7 +240,7 @@
<div class="required min_title inline field"> <div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48" <select id="__specs__" class="ui search dropdown width48"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}"
{{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}
name="spec_id"> name="spec_id">
</select> </select>
@@ -345,6 +345,7 @@
} }
} }
} }
var isValidate = false;
function validate() { function validate() {
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -368,12 +369,18 @@
} }
] ]
}, },
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
}
}, },
onSuccess: function () { onSuccess: function () {
// $('.ui.page.dimmer').dimmer('show') // $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function (e) { onFailure: function (e) {
isValidate = false;
return false; return false;
} }
}) })
@@ -395,4 +402,4 @@
shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}}, shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}},
}); });
})(); })();
</script>
</script>

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

@@ -256,8 +256,9 @@
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);">
<a class="active item" <a class="active item"
data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item" data-tab="second{{$k}}"
onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a>
<a class="item log_bottom" data-tab="second{{$k}}"
data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a>
</div> </div>
<div class="ui tab active" data-tab="first{{$k}}"> <div class="ui tab active" data-tab="first{{$k}}">
<div style="padding-top: 10px;"> <div style="padding-top: 10px;">
@@ -524,19 +525,42 @@
</div> </div>
<div class="ui tab" data-tab="second{{$k}}"> <div class="ui tab" data-tab="second{{$k}}">
<div> <div>
<div class="ui message message{{.VersionName}}" style="display: none;">
<div id="header"></div>
</div>
<div class="ui attached log" id="log{{.VersionName}}"
style="height: 300px !important; overflow: auto;">
<input type="hidden" name="end_line" value>
<input type="hidden" name="start_line" value>
<pre id="log_file{{.VersionName}}"></pre>
</div>

</div>

</div>
<a id="{{.VersionName}}-log-down"
class='{{if $.canDownload}}ti-download-file{{else}}disabled{{end}}'
href="/api/v1/repos/{{$.RepoRelPath}}/cloudbrain/{{.ID}}/download_log_file">
<i class="ri-download-cloud-2-line"></i>
<span style="margin-left: 0.3rem;">{{$.i18n.Tr "repo.modelarts.download_log"}}</span>
</a>
</div>
<div
style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;">
<span>
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;"
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a>
</span>
<span class="log-info-{{.VersionName}}">
<a title="滚动到底部" style="position: absolute; bottom: 10px;right: -32px;cursor: pointer;"
class="log_bottom" data-version="{{.VersionName}}"><i
class="icon-to-bottom"></i></a>
</span>
<div class="ui message message{{.VersionName}}" style="display: none;">
<div id="header"></div>
</div>
<div class="ui attached log log-scroll" id="log{{.VersionName}}" data-version="{{.VersionName}}"
style="height: 300px !important; overflow: auto;">
<div class="ui inverted active dimmer">
<div class="ui loader"></div>
</div>
<input type="hidden" name="end_line" value>
<input type="hidden" name="start_line" value>
<pre id="log_file{{.VersionName}}"></pre>
</div>
</div>
</div>


</div> </div>
</div> </div>


+ 9
- 1
templates/repo/cloudbrain/inference/new.tmpl View File

@@ -254,7 +254,7 @@
</div>--> </div>-->
<div class="required min_title inline field"> <div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}>
<select id="__specs__" class="ui search dropdown width48" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" ovalue="{{.spec_id}}" name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}>
</select> </select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;"> <div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;">
@@ -452,6 +452,8 @@
msg = JSON.stringify(msg) msg = JSON.stringify(msg)
$('#store_run_para').val(msg) $('#store_run_para').val(msg)
} }

var isValidate = false;
function validate(){ function validate(){
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -505,12 +507,18 @@
type: 'empty', type: 'empty',
} }
] ]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
} }
}, },
onSuccess: function(){ onSuccess: function(){
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })


+ 49
- 5
templates/repo/cloudbrain/inference/show.tmpl View File

@@ -228,7 +228,7 @@
</h4> </h4>
{{with .task}} {{with .task}}
<div class="ui accordion border-according" id="accordion{{.VersionName}}" <div class="ui accordion border-according" id="accordion{{.VersionName}}"
data-repopath="{{$.RepoRelPath}}/cloudbrain/inference-job" data-jobid="{{.JobID}}" data-version="{{.VersionName}}">
data-repopath="{{$.RepoRelPath}}/cloudbrain" data-jobid="{{.ID}}" data-version="{{.VersionName}}">
<input type="hidden" id="jobId_input" name="jobId_input" value="{{.JobID}}"> <input type="hidden" id="jobId_input" name="jobId_input" value="{{.JobID}}">
<div class="active title padding0"> <div class="active title padding0">
<div class="according-panel-heading"> <div class="according-panel-heading">
@@ -264,7 +264,8 @@
data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a>
<a class="item" data-tab="second" <a class="item" data-tab="second"
onclick="javascript:parseInfo()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a> onclick="javascript:parseInfo()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a>
<a class="item log_bottom" data-tab="third"
data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a>
<a class="item load-model-file" data-tab="four" <a class="item load-model-file" data-tab="four"
data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/inference-job/{{.JobID}}/result_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/inference-job/{{.JobID}}/result_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a>
</div> </div>
@@ -496,7 +497,13 @@
<tbody> <tbody>
{{range $m ,$n := $.datasetDownload}} {{range $m ,$n := $.datasetDownload}}
<tr> <tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
</tr> </tr>
{{end}} {{end}}
@@ -514,7 +521,7 @@
<div class="ui message message{{.VersionName}}" style="display: none;"> <div class="ui message message{{.VersionName}}" style="display: none;">
<div id="header"></div> <div id="header"></div>
</div> </div>
<div class="ui attached log" id="log{{.VersionName}}"
<div class="ui attached"
style="height: 390px !important; overflow: auto;"> style="height: 390px !important; overflow: auto;">
<input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}"> <input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}">
<input type="hidden" id="ExitDiagnostics" value="{{$.ExitDiagnostics}}"> <input type="hidden" id="ExitDiagnostics" value="{{$.ExitDiagnostics}}">
@@ -527,7 +534,44 @@


</div> </div>


<div class="ui tab" data-tab="third">
<div>
<a id="{{.VersionName}}-log-down"
class='{{if $.canDownload}}ti-download-file{{else}}disabled{{end}}'
href="/api/v1/repos/{{$.RepoRelPath}}/cloudbrain/{{.ID}}/download_log_file">
<i class="ri-download-cloud-2-line"></i>
<span style="margin-left: 0.3rem;">{{$.i18n.Tr "repo.modelarts.download_log"}}</span>
</a>
</div>
<div
style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;">
<span>
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;"
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a>
</span>
<span class="log-info-{{.VersionName}}">
<a title="滚动到底部" style="position: absolute; bottom: 10px;right: -32px;cursor: pointer;"
class="log_bottom" data-version="{{.VersionName}}"><i
class="icon-to-bottom"></i></a>
</span>
<div class="ui message message{{.VersionName}}" style="display: none;">
<div id="header"></div>
</div>
<div class="ui attached log log-scroll" id="log{{.VersionName}}" data-version="{{.VersionName}}"
style="height: 300px !important; overflow: auto;">
<div class="ui inverted active dimmer">
<div class="ui loader"></div>
</div>
<input type="hidden" name="end_line" value>
<input type="hidden" name="start_line" value>
<pre id="log_file{{.VersionName}}"></pre>
</div>
</div>
</div>


<div class="ui tab" data-tab="four"> <div class="ui tab" data-tab="four">
<input type="hidden" name="model{{.VersionName}}" value="-1"> <input type="hidden" name="model{{.VersionName}}" value="-1">


+ 23
- 15
templates/repo/cloudbrain/new.tmpl View File

@@ -1,6 +1,6 @@
{{template "base/head" .}} {{template "base/head" .}}
<style> <style>
/* 遮罩层css效果图 */ /* 遮罩层css效果图 */
.inline.required.field.cloudbrain_benchmark { .inline.required.field.cloudbrain_benchmark {
display: none; display: none;
@@ -13,7 +13,7 @@
.inline.required.field.cloudbrain_brainscore { .inline.required.field.cloudbrain_brainscore {
display: none; display: none;
} }


</style> </style>


@@ -55,8 +55,8 @@
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" /> d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg> </svg>
Ascend NPU</a> Ascend NPU</a>
</div>
</div>
</div>
</div>
<div class="inline field"> <div class="inline field">
<label></label> <label></label>
{{template "custom/task_wait_count" .}} {{template "custom/task_wait_count" .}}
@@ -111,7 +111,7 @@
{{end}} {{end}}
{{end}} {{end}}
</select> </select>
</div>
</div>
<!--<div class="inline required field"> <!--<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.gpu_type"}}</label> <label>{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<select id="cloudbrain_gpu_type" class="ui search dropdown gpu-type" placeholder="选择GPU类型" <select id="cloudbrain_gpu_type" class="ui search dropdown gpu-type" placeholder="选择GPU类型"
@@ -128,7 +128,7 @@
<div id="select-multi-dataset"> <div id="select-multi-dataset">


</div> </div>
<!--<div class="inline required field"> <!--<div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label> <label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown" <select id="cloudbrain_resource_spec" class="ui search dropdown"
@@ -141,11 +141,11 @@
{{end}} {{end}}
</select> </select>
</div>--> </div>-->
<div class="inline required field"> <div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label> <label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown" <select id="__specs__" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}"
{{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}
name="spec_id"> name="spec_id">
</select> </select>
@@ -218,10 +218,11 @@
context.value = '' context.value = ''
$(".icon.icons").css("visibility", "hidden") $(".icon.icons").css("visibility", "hidden")
} }
var isValidate = false;
function validate(){ function validate(){
$('.ui.form').form({ $('.ui.form').form({
on: 'blur', on: 'blur',
fields: {
fields: {
display_job_name:{ display_job_name:{
identifier : 'display_job_name', identifier : 'display_job_name',
rules: [ rules: [
@@ -229,11 +230,17 @@
type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]', type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]',
} }
] ]
},
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
}
}, },
onSuccess: function(){
onSuccess: function(){
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })
@@ -241,6 +248,7 @@
validate(); validate();
let createFlag = false let createFlag = false
form.onsubmit = function (e) { form.onsubmit = function (e) {
if (!isValidate) return false;
if(createFlag) return false if(createFlag) return false
let value_task = $("input[name='display_job_name']").val() let value_task = $("input[name='display_job_name']").val()
let value_image = $("input[name='image']").val() let value_image = $("input[name='image']").val()
@@ -264,7 +272,7 @@
if (document.readyState === "complete") { if (document.readyState === "complete") {
document.getElementById("mask").style.display = "none" document.getElementById("mask").style.display = "none"
} }
} }


$('#cloudbrain_benchmark_category') $('#cloudbrain_benchmark_category')
@@ -301,14 +309,14 @@
} }
}) })
}) })
$('.ui.green.button').click(function () { $('.ui.green.button').click(function () {
if (!$('input[name="isBranches"]').val()) { if (!$('input[name="isBranches"]').val()) {
return false return false
} }
selected_value = $("#cloudbrain_benchmark_category").val() selected_value = $("#cloudbrain_benchmark_category").val()
$('#store_category').attr("value", selected_value) $('#store_category').attr("value", selected_value)
validate();
}) })


;(function() { ;(function() {
@@ -322,4 +330,4 @@
shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}}, shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}},
}); });
})(); })();
</script>
</script>

+ 7
- 1
templates/repo/cloudbrain/show.tmpl View File

@@ -494,7 +494,13 @@
<tbody> <tbody>
{{range $m ,$n := $.datasetDownload}} {{range $m ,$n := $.datasetDownload}}
<tr> <tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
</tr> </tr>
{{end}} {{end}}


+ 8
- 1
templates/repo/cloudbrain/trainjob/new.tmpl View File

@@ -258,7 +258,7 @@


<div class="required min_title inline field"> <div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui dropdown width48" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}"
<select id="__specs__" class="ui dropdown width48" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" ovalue="{{.spec_id}}"
{{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}
name="spec_id"> name="spec_id">
</select> </select>
@@ -365,6 +365,7 @@
$('select.dropdown') $('select.dropdown')
.dropdown(); .dropdown();


var isValidate = false;
function validate() { function validate() {
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -410,13 +411,19 @@
type: 'empty', type: 'empty',
} }
] ]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
} }
}, },
onSuccess: function () { onSuccess: function () {
// $('.ui.page.dimmer').dimmer('show') // $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function (e) { onFailure: function (e) {
isValidate = false;
return false; return false;
} }
}) })


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

@@ -460,7 +460,13 @@
<tbody> <tbody>
{{range $m ,$n := $.datasetDownload}} {{range $m ,$n := $.datasetDownload}}
<tr> <tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
</tr> </tr>
{{end}} {{end}}
@@ -590,7 +596,7 @@
<input type="hidden" name="trainTaskCreate" value="true"> <input type="hidden" name="trainTaskCreate" value="true">


<div class="required inline field"> <div class="required inline field">
<label>{{.i18n.Tr "repo.model.manage.createtrainjob"}}</label>
<label>{{.i18n.Tr "repo.modelarts.train_job"}}</label>
<input type="hidden" class="width83" id="JobId" name="JobId" readonly required> <input type="hidden" class="width83" id="JobId" name="JobId" readonly required>
<input type="hidden" id="VersionName" name="VersionName" value="V0001"> <input type="hidden" id="VersionName" name="VersionName" value="V0001">
<input style="width: 45%;" id="JobName" readonly required> <input style="width: 45%;" id="JobName" readonly required>


+ 9
- 2
templates/repo/grampus/trainjob/gpu/new.tmpl View File

@@ -106,7 +106,7 @@
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/>
</svg> </svg>
Ascend NPU</a> Ascend NPU</a>
</div>
</div>
</div> </div>
<div class="min_title inline field" style="margin-top:-10px;"> <div class="min_title inline field" style="margin-top:-10px;">
<label class="label-fix-width" style="font-weight: normal;"></label> <label class="label-fix-width" style="font-weight: normal;"></label>
@@ -206,7 +206,7 @@
</div>--> </div>-->
<div class="required min_title inline field" id="flavor_name"> <div class="required min_title inline field" id="flavor_name">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<select class="ui dropdown width48" id="__specs__" style='width:385px' name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
<select class="ui dropdown width48" id="__specs__" style='width:385px' name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;"> <div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span> <span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
@@ -305,6 +305,7 @@
$('select.dropdown') $('select.dropdown')
.dropdown(); .dropdown();


var isValidate = false;
function validate(){ function validate(){
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -351,13 +352,19 @@
type : 'integer[1..25]', type : 'integer[1..25]',
} }
] ]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
} }
}, },
onSuccess: function(){ onSuccess: function(){
// $('.ui.page.dimmer').dimmer('show') // $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })


+ 8
- 1
templates/repo/grampus/trainjob/npu/new.tmpl View File

@@ -218,7 +218,7 @@
</div>--> </div>-->
<div class="required min_title inline field" id="flavor_name"> <div class="required min_title inline field" id="flavor_name">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<select class="ui dropdown width48" id="__specs__" style='width:385px' name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
<select class="ui dropdown width48" id="__specs__" style='width:385px' name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;"> <div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span> <span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
@@ -331,6 +331,7 @@
$('select.dropdown') $('select.dropdown')
.dropdown(); .dropdown();


var isValidate = false;
function validate(){ function validate(){
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -368,13 +369,19 @@
type : 'integer[1..25]', type : 'integer[1..25]',
} }
] ]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
} }
}, },
onSuccess: function(){ onSuccess: function(){
// $('.ui.page.dimmer').dimmer('show') // $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })


+ 7
- 2
templates/repo/grampus/trainjob/show.tmpl View File

@@ -417,7 +417,12 @@
<td class="ti-text-form-content"> <td class="ti-text-form-content">
<div class="text-span text-span-w"> <div class="text-span text-span-w">
{{range $m ,$n := $.datasetDownload}} {{range $m ,$n := $.datasetDownload}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
{{end}} {{end}}
</div> </div>
</td> </td>
@@ -549,7 +554,7 @@
<input type="hidden" name="trainTaskCreate" value="true"> <input type="hidden" name="trainTaskCreate" value="true">


<div class="required inline field"> <div class="required inline field">
<label>{{.i18n.Tr "repo.model.manage.createtrainjob"}}</label>
<label>{{.i18n.Tr "repo.modelarts.train_job"}}</label>
<input type="hidden" class="width83" id="JobId" name="JobId" readonly required> <input type="hidden" class="width83" id="JobId" name="JobId" readonly required>
<input type="hidden" id="VersionName" name="VersionName" value="V0001"> <input type="hidden" id="VersionName" name="VersionName" value="V0001">
<input style="width: 45%;" id="JobName" readonly required> <input style="width: 45%;" id="JobName" readonly required>


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

@@ -275,7 +275,7 @@
</div>--> </div>-->
<div class="required min_title inline field" id="flaver_name"> <div class="required min_title inline field" id="flaver_name">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<select class="ui dropdown width48" id="__specs__" name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
<select class="ui dropdown width48" id="__specs__" name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;"> <div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span> <span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
@@ -474,6 +474,8 @@
$("input#ai_engine_name").val(name1) $("input#ai_engine_name").val(name1)
$("input#ai_flaver_name").val(name2) $("input#ai_flaver_name").val(name2)
} }

var isValidate = false;
function validate(){ function validate(){
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -527,12 +529,18 @@
type: 'empty', type: 'empty',
} }
] ]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
} }
}, },
onSuccess: function(){ onSuccess: function(){
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })


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

@@ -439,7 +439,14 @@ td, th {
<tbody> <tbody>
{{range $m ,$n := $.datasetDownload}} {{range $m ,$n := $.datasetDownload}}
<tr> <tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
</tr> </tr>
{{end}} {{end}}


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

@@ -79,7 +79,7 @@
</div>--> </div>-->
<div class="inline required field"> <div class="inline required field">
<label>{{.i18n.Tr "cloudbrain.specification"}}</label> <label>{{.i18n.Tr "cloudbrain.specification"}}</label>
<select id="__specs__" class="ui search dropdown"
<select id="__specs__" class="ui search dropdown" ovalue="{{.spec_id}}"
{{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' name="spec_id"></select> placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' name="spec_id"></select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
@@ -91,6 +91,7 @@
</span> </span>
</div> </div>
{{end}} {{end}}
<select id="__specs__" class="ui search dropdown" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' name="spec_id" ovalue="{{.spec_id}}"></select>
</div> </div>
<!--<div class="inline required field"> <!--<div class="inline required field">
<label>数据集存放路径</label> <label>数据集存放路径</label>
@@ -120,10 +121,11 @@


$('#messageInfo').css('display','none') $('#messageInfo').css('display','none')


var isValidate = false;
function validate(){ function validate(){
$('.ui.form').form({ $('.ui.form').form({
on: 'blur', on: 'blur',
fields: {
fields: {
display_job_name:{ display_job_name:{
identifier : 'display_job_name', identifier : 'display_job_name',
rules: [ rules: [
@@ -131,11 +133,17 @@
type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]', type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]',
} }
] ]
},
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
}
}, },
onSuccess: function(){
onSuccess: function(){
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })
@@ -143,7 +151,8 @@
validate(); validate();
let createFlag = false let createFlag = false
form.onsubmit = function(e){ form.onsubmit = function(e){
if(createFlag) return false
if(!isValidate) return false;
if(createFlag) return false;
let value_task = $("input[name='display_job_name']").val() let value_task = $("input[name='display_job_name']").val()
let re = /^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/ let re = /^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/
let flag = re.test(value_task) let flag = re.test(value_task)


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

@@ -437,7 +437,14 @@
<tbody> <tbody>
{{range $.datasetDownload}} {{range $.datasetDownload}}
<tr> <tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
<td style="word-wrap: break-word;word-break: break-all;">{{.DatasetDownloadLink}}</td> <td style="word-wrap: break-word;word-break: break-all;">{{.DatasetDownloadLink}}</td>
<td class="center aligned"><a class="ui poping up clipboard" id="clipboard-btn-dataset" data-original="{{$.i18n.Tr "repo.copy_link"}}" data-success="{{$.i18n.Tr "repo.copy_link_success"}}" data-error="{{$.i18n.Tr "repo.copy_link_error"}}" data-content="{{$.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-text="{{.DatasetDownloadLink}}">{{$.i18n.Tr "dataset.download_copy"}}</a></td> <td class="center aligned"><a class="ui poping up clipboard" id="clipboard-btn-dataset" data-original="{{$.i18n.Tr "repo.copy_link"}}" data-success="{{$.i18n.Tr "repo.copy_link_success"}}" data-error="{{$.i18n.Tr "repo.copy_link_error"}}" data-content="{{$.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-text="{{.DatasetDownloadLink}}">{{$.i18n.Tr "dataset.download_copy"}}</a></td>
</tr> </tr>


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

@@ -109,7 +109,7 @@
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" /> d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg> </svg>
Ascend NPU</a> Ascend NPU</a>
</div>
</div>
</div> </div>
<div class="min_title inline field" style="margin-top:-10px;"> <div class="min_title inline field" style="margin-top:-10px;">
<label class="label-fix-width" style="font-weight: normal;"></label> <label class="label-fix-width" style="font-weight: normal;"></label>
@@ -283,7 +283,7 @@
</div>--> </div>-->
<div class="required inline min_title field" id="flaver_name"> <div class="required inline min_title field" id="flaver_name">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<select class="ui dropdown width48" id="__specs__" name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
<select class="ui dropdown width48" id="__specs__" name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;"> <div class="cloudbrain_resource_spec_blance_tip width48" style="padding:0 5px;margin:6px 0;margin-left:155px;font-size:12px;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span> <span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
@@ -303,8 +303,24 @@
id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1" id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1"
readonly> readonly>
<div class="field" id="trainjob_work_server_num_select" name="work_server_number_select"> <div class="field" id="trainjob_work_server_num_select" name="work_server_number_select">
<select class="ui dropdown width" style='width: 100%;' name="work_server_id">
<select class="ui dropdown width" style='width: 100%;' name="work_server_id">
{{if .WorkNode}}
{{range .WorkNode}}

{{if $.work_server_number}}
{{if eq . $.work_server_number }}
<option name="server_id" selected value="{{.}}">{{.}}</option>
{{else}}
<option name="server_id" value="{{.}}">{{.}}</option>
{{end}}
{{else}}
<option name="server_id" value="{{.}}">{{.}}</option>
{{end}}
{{end}}

{{else}}
<option name="server_id" value="1">1</option> <option name="server_id" value="1">1</option>
{{end}}
</select> </select>
</div> </div>


@@ -457,6 +473,7 @@
$('select.dropdown') $('select.dropdown')
.dropdown(); .dropdown();


var isValidate = false;
function validate() { function validate() {
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -494,13 +511,19 @@
type: 'integer[1..25]', type: 'integer[1..25]',
} }
] ]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
} }
}, },
onSuccess: function () { onSuccess: function () {
// $('.ui.page.dimmer').dimmer('show') // $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function (e) { onFailure: function (e) {
isValidate = false;
return false; return false;
} }
}) })


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

@@ -503,7 +503,13 @@
{{if eq $k $m}} {{if eq $k $m}}
{{range $f ,$g := $n}} {{range $f ,$g := $n}}
<tr> <tr>
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td>
<td style="word-wrap: break-word;word-break: break-all;">
{{if eq .IsDelete true}}
{{.DatasetName}}({{$.i18n.Tr "dataset.file_deleted"}})
{{else}}
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a>
{{end}}
</td>
</tr> </tr>
{{end}} {{end}}
{{end}} {{end}}
@@ -618,7 +624,7 @@


<div class="two inline fields "> <div class="two inline fields ">
<div class="required ten wide field"> <div class="required ten wide field">
<label style="margin-left: -23px;">{{.i18n.Tr "repo.model.manage.createtrainjob"}}</label>
<label style="margin-left: -23px;">{{.i18n.Tr "repo.modelarts.train_job"}}</label>
<input type="hidden" class="width83" id="JobId" name="JobId" readonly required> <input type="hidden" class="width83" id="JobId" name="JobId" readonly required>
<input class="width83" id="JobName" readonly required> <input class="width83" id="JobName" readonly required>




+ 11
- 51
templates/repo/modelarts/trainjob/version_new.tmpl View File

@@ -72,7 +72,7 @@
{{end}} {{end}}
<input type="hidden" id="ai_engine_name" name="engine_names" value=""> <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="ai_flaver_name" name="flaver_names" value="">
<input type="hidden" id="display_job_name" name="display_job_name" value="{{.display_job_name}}">
<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> <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required min_title inline field"> <div class="required min_title inline field">
<label class="" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label> <label class="" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
@@ -107,7 +107,7 @@
d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" /> d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z" />
</svg> </svg>
Ascend NPU</a> Ascend NPU</a>
</div>
</div>
</div> </div>
<div style="display: flex;align-items: center;margin-left: 156px;margin-top: -0.5rem;"> <div style="display: flex;align-items: center;margin-left: 156px;margin-top: -0.5rem;">
{{template "custom/task_wait_count" .}} {{template "custom/task_wait_count" .}}
@@ -263,7 +263,7 @@
</div>--> </div>-->
<div class="required unite min_title inline field" id="flaver_name"> <div class="required unite min_title inline field" id="flaver_name">
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<select id="__specs__" class="ui dropdown width80" style='width:385px' name="spec_id" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
<select id="__specs__" class="ui dropdown width80" style='width:385px' name="spec_id" ovalue="{{.spec_id}}" {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}}></select>
{{if .CloudBrainPaySwitch}} {{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip width80" style="padding:0 5px;margin:6px 0;margin-left:60px;font-size:12px;"> <div class="cloudbrain_resource_spec_blance_tip width80" style="padding:0 5px;margin:6px 0;margin-left:60px;font-size:12px;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span> <span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
@@ -440,53 +440,7 @@
$('select.dropdown') $('select.dropdown')
.dropdown(); .dropdown();


$('.ui.form')
.form({
on: 'blur',
inline:true,
fields: {
boot_file: {
identifier : 'boot_file',
rules: [
{
type: 'regExp[/.+\.py$/g]',
prompt : '启动文件必须为.py结尾'
}
]
},
job_name:{
identifier : 'job_name',
rules: [
{
type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]',
prompt : '只包含大小写字母、数字、_和-,最长36个字符。'
}
]
},
display_job_name:{
identifier : 'display_job_name',
rules: [
{
type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]',
prompt : '只包含大小写字母、数字、_和-,最长36个字符。'
}
]
},
attachment:{
identifier : 'attachment',
rules: [
{
type: 'empty',
prompt : '选择一个数据集'
}
]

},
},
})



var isValidate = false;
function validate(){ function validate(){
$('.ui.form') $('.ui.form')
.form({ .form({
@@ -530,12 +484,18 @@
] ]


}, },
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
}
}, },
onSuccess: function(){ onSuccess: function(){
// $('.ui.page.dimmer').dimmer('show') // $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block" document.getElementById("mask").style.display = "block"
isValidate = true;
}, },
onFailure: function(e){ onFailure: function(e){
isValidate = false;
return false; return false;
} }
}) })
@@ -565,7 +525,7 @@
$("input#ai_flaver_name").val(name2) $("input#ai_flaver_name").val(name2)


} }
validate() validate()
$('.ui.create_train_job.green.button').click(function(e) { $('.ui.create_train_job.green.button').click(function(e) {
get_name() get_name()


+ 2
- 2
templates/repo/modelmanage/convertIndex.tmpl View File

@@ -50,9 +50,9 @@
<div class="bgtask-content-header">{{$.i18n.Tr "repo.modelconvert.notcreate"}}</div> <div class="bgtask-content-header">{{$.i18n.Tr "repo.modelconvert.notcreate"}}</div>
<div class="bgtask-content"> <div class="bgtask-content">
{{if eq .MODEL_COUNT 0}} {{if eq .MODEL_COUNT 0}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.modelconvert.importfirst1"}}<a href="{{.RepoLink}}/modelmanage/show_model">{{$.i18n.Tr "repo.modelconvert.importfirst2"}}</a>{{$.i18n.Tr "repo.modelconvert.importfirst3"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.modelconvert.importfirst1"}}<a href="{{.RepoLink}}/modelmanage/show_model">&nbsp;{{$.i18n.Tr "repo.modelconvert.importfirst2"}}&nbsp;</a>{{$.i18n.Tr "repo.modelconvert.importfirst3"}}</div>
{{end}} {{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions"}}</div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions1"}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">&nbsp;{{$.i18n.Tr "repo.platform_instructions2"}}&nbsp;</a>{{$.i18n.Tr "repo.platform_instructions3"}}</div>


</div> </div>
</div> </div>


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

@@ -71,9 +71,9 @@
{{end}} {{end}}
{{if eq $.TRAIN_COUNT 0}} {{if eq $.TRAIN_COUNT 0}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.createtrainjob_tip"}}<a <div class="bgtask-content-txt">{{$.i18n.Tr "repo.model.manage.createtrainjob_tip"}}<a
href="{{.RepoLink}}/modelarts/train-job">{{$.i18n.Tr "repo.model.manage.createtrainjob"}}</a></div>
href="{{.RepoLink}}/modelarts/train-job">&nbsp;{{$.i18n.Tr "repo.model.manage.createtrainjob"}}</a></div>
{{end}} {{end}}
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions"}}</a></div>
<div class="bgtask-content-txt">{{$.i18n.Tr "repo.platform_instructions1"}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">&nbsp;{{$.i18n.Tr "repo.platform_instructions2"}}&nbsp;</a>{{$.i18n.Tr "repo.platform_instructions3"}}</div>


</div> </div>
<div style="display: none;"> <div style="display: none;">
@@ -330,7 +330,7 @@
.modal({ .modal({
centered: false, centered: false,
onShow: function () { onShow: function () {
$('#model_header').text("导入新模型")
$('#model_header').text({{.i18n.Tr "repo.model.manage.import_new_model"}})
$('input[name="Version"]').addClass('model_disabled') $('input[name="Version"]').addClass('model_disabled')
$('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) $('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" })
$("#job-name").empty() $("#job-name").empty()


+ 1
- 1
templates/repo/modelmanage/showinfo.tmpl View File

@@ -125,7 +125,7 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.createtrainjob"}}</td>
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job"}}</td>
<td class="ti-text-form-content word-elipsis"> <td class="ti-text-form-content word-elipsis">
<a id="DisplayJobNameHref" class="title" style="font-size: 14px;" target="_blank"> <a id="DisplayJobNameHref" class="title" style="font-size: 14px;" target="_blank">
<span id="DisplayJobName" class="fitted" style="width: 90%;vertical-align: middle;"></span> <span id="DisplayJobName" class="fitted" style="width: 90%;vertical-align: middle;"></span>


+ 12
- 5
templates/user/dashboard/cloudbrains.tmpl View File

@@ -1,5 +1,6 @@
{{template "base/head" .}} {{template "base/head" .}}
<!-- 提示框 --> <!-- 提示框 -->
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<div class="alert"></div> <div class="alert"></div>
<div class="explore users"> <div class="explore users">
<div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}" <div class="cloudbrain_debug" style="display: none;" data-debug="{{$.i18n.Tr "repo.debug"}}"
@@ -159,11 +160,17 @@
</div> </div>
<!-- XPU类型 --> <!-- XPU类型 -->
<div class="one wide column text center nowrap" style="width:10% !important;"> <div class="one wide column text center nowrap" style="width:10% !important;">
<span style="font-size: 12px;" title="{{.CardType}}">
{{if .CardType}}{{.CardType}}{{else}}--{{end}}
</span>
</div>

<span style="font-size: 12px;" title="" class="card_type_{{.DisplayJobName}}_{{$JobID}}"></span>
</div>
<script>
(function(){
var spec = {{.Spec}} || {};
var cardType = getListValueWithKey(ACC_CARD_TYPE, spec.AccCardType) || '--';
var spanEl = document.querySelector('.card_type_{{.DisplayJobName}}_{{$JobID}}');
spanEl.setAttribute('title', cardType);
spanEl.innerText = cardType;
})();
</script>
<!-- 项目 --> <!-- 项目 -->
<div class="two wide column text center nowrap" style="width: 11%!important;"> <div class="two wide column text center nowrap" style="width: 11%!important;">
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}" <a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}"


+ 2
- 1
web_src/js/components/Model.vue View File

@@ -197,11 +197,12 @@ export default {
this.getModelList() this.getModelList()
}, },
showcreateVue(name,version,label){ showcreateVue(name,version,label){
let title= this.i18n.model_create_version_title;
$('.ui.modal.second') $('.ui.modal.second')
.modal({ .modal({
centered: false, centered: false,
onShow:function(){ onShow:function(){
$('#model_header').text("创建模型新版本")
$('#model_header').text(title)
$('input[name="Name"]').addClass('model_disabled') $('input[name="Name"]').addClass('model_disabled')
$('input[name="Name"]').attr('readonly','readonly') $('input[name="Name"]').attr('readonly','readonly')
$('input[name="modelSelectedFile"]').attr('readonly','readonly') $('input[name="modelSelectedFile"]').attr('readonly','readonly')


+ 1
- 1
web_src/js/components/dataset/referenceDataset.vue View File

@@ -248,7 +248,7 @@
> >
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
<el-tab-pane :label="i18n.public_dataset" name="first"> <el-tab-pane :label="i18n.public_dataset" name="first">
<el-row v-loading="loadingPublicPage">
<el-row v-loading="loadingPublicPage" style="min-height: 50px">
<el-checkbox-group <el-checkbox-group
v-model="checkList" v-model="checkList"
style="font-size: 14px; line-height: 1" style="font-size: 14px; line-height: 1"


+ 5
- 2
web_src/js/components/dataset/selectDataset.vue View File

@@ -546,7 +546,7 @@
> >
{{ i18n.dataset_selected }} {{ i18n.dataset_selected }}
</div> </div>
<div style="flex: 1; margin-top: 1.5rem">
<div style="flex: 1; margin: 1.5rem 0; overflow-y: auto">
<el-checkbox-group v-model="checkList"> <el-checkbox-group v-model="checkList">
<el-checkbox <el-checkbox
v-for="(item, index) in selectDatasetArray" v-for="(item, index) in selectDatasetArray"
@@ -985,7 +985,10 @@ export default {
let hasSelectDatasetName = $(".cloudbrain-type") let hasSelectDatasetName = $(".cloudbrain-type")
.data("dataset-name") .data("dataset-name")
.split(";"); .split(";");
if (this.hasSelectDatasetList.length !== 0) {
if (
this.hasSelectDatasetList.length !== 0 &&
hasSelectDatasetName[0] !== ""
) {
this.saveStatusList = this.hasSelectDatasetList; this.saveStatusList = this.hasSelectDatasetList;
this.checkList = hasSelectDatasetName; this.checkList = hasSelectDatasetName;
this.hasSelectDatasetList.forEach((item, index) => { this.hasSelectDatasetList.forEach((item, index) => {


+ 5
- 1
web_src/js/features/i18nVue.js View File

@@ -95,6 +95,8 @@ export const i18nVue = {
model_create_new_ver: "创建新版本", model_create_new_ver: "创建新版本",
model_download: "下载", model_download: "下载",
model_delete: "删除", model_delete: "删除",
model_create_title: "导入新模型",
model_create_version_title: "创建模型新版本",
}, },
US: { US: {
computer_vision: "computer vision", computer_vision: "computer vision",
@@ -152,7 +154,7 @@ export const i18nVue = {


dataset_instructions_for_use: dataset_instructions_for_use:
"Instructions for use: You can refer to OpenI AI Collaboration Platform ", "Instructions for use: You can refer to OpenI AI Collaboration Platform ",
dataset_camp_course: " Newcomer Training Camp Course",
dataset_camp_course: " OpenI_Learning",
dataset_link_success: "Linked dataset succeeded!", dataset_link_success: "Linked dataset succeeded!",
dataset_link_failed: "Linked dataset Failed!", dataset_link_failed: "Linked dataset Failed!",
dataset_over_nums: "Linked over ? datasets!", dataset_over_nums: "Linked over ? datasets!",
@@ -196,5 +198,7 @@ export const i18nVue = {
model_create_new_ver: "New Version", model_create_new_ver: "New Version",
model_download: "Download", model_download: "Download",
model_delete: "Delete", model_delete: "Delete",
model_create_title: "Import new model",
model_create_version_title: "Create a new version of the model",
}, },
}; };

+ 2
- 0
web_src/js/standalone/specsuse.js View File

@@ -22,11 +22,13 @@ window.renderSpecsSelect = (specsSel, data, showPoint, langObj) => {
specsSel.empty(); specsSel.empty();
data = data || []; data = data || [];
showPoint = specsSel.attr('blance') ? true : false; showPoint = specsSel.attr('blance') ? true : false;
var oValue = specsSel.attr('ovalue');
for (var i = 0, iLen = data.length; i < iLen; i++) { for (var i = 0, iLen = data.length; i < iLen; i++) {
var spec = data[i]; var spec = data[i];
var specStr = window.renderSpecStr(spec, showPoint, langObj); var specStr = window.renderSpecStr(spec, showPoint, langObj);
specsSel.append(`<option name="spec_id" value="${spec.ID}" queueCode="${spec.QueueCode}" unitprice="${spec.UnitPrice}">${specStr}</option>`); specsSel.append(`<option name="spec_id" value="${spec.ID}" queueCode="${spec.QueueCode}" unitprice="${spec.UnitPrice}">${specStr}</option>`);
} }
oValue && specsSel.val(oValue);
if (showPoint) { if (showPoint) {
specsSel.on('change', function (e) { specsSel.on('change', function (e) {
var cloudbrain_resource_spec_blance_tip_el = $('.cloudbrain_resource_spec_blance_tip'); var cloudbrain_resource_spec_blance_tip_el = $('.cloudbrain_resource_spec_blance_tip');


+ 1
- 1
web_src/vuepages/const/index.js View File

@@ -10,7 +10,7 @@ export const JOB_TYPE = [{ k: 'DEBUG', v: i18n.t('debugTask') }, { k: 'TRAIN', v


// 资源管理 // 资源管理
export const CLUSTERS = [{ k: 'OpenI', v: i18n.t('resourcesManagement.OpenI') }, { k: 'C2Net', v: i18n.t('resourcesManagement.C2Net') }]; export const CLUSTERS = [{ k: 'OpenI', v: i18n.t('resourcesManagement.OpenI') }, { k: 'C2Net', v: i18n.t('resourcesManagement.C2Net') }];
export const AI_CENTER = [{ k: 'OpenIOne', v: i18n.t('resourcesManagement.OpenIOne') }, { k: 'OpenITwo', v: i18n.t('resourcesManagement.OpenITwo') }, { k: 'chendu', v: i18n.t('resourcesManagement.chenduCenter') }, { k: 'pclcci', v: i18n.t('resourcesManagement.pclcci') }, { k: 'hefei', v: i18n.t('resourcesManagement.hefeiCenter') }, { k: 'xuchang', v: i18n.t('resourcesManagement.xuchangCenter') }];
export const AI_CENTER = [{ k: 'OpenIOne', v: i18n.t('resourcesManagement.OpenIOne') }, { k: 'OpenITwo', v: i18n.t('resourcesManagement.OpenITwo') }, { k: 'OpenIChengdu', v: i18n.t('resourcesManagement.OpenIChengdu') }, { k: 'pclcci', v: i18n.t('resourcesManagement.pclcci') }, { k: 'hefei', v: i18n.t('resourcesManagement.hefeiCenter') }, { k: 'xuchang', v: i18n.t('resourcesManagement.xuchangCenter') }];
export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'MLU', v: 'MLU' }]; export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'MLU', v: 'MLU' }];
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'RTX3080', v: 'RTX3080' }]; export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'RTX3080', v: 'RTX3080' }];
export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }]; export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }];

+ 2
- 1
web_src/vuepages/langs/config/en-US.js View File

@@ -82,7 +82,8 @@ const en = {
C2Net: 'C2Net', C2Net: 'C2Net',
OpenIOne: 'OpenI One', OpenIOne: 'OpenI One',
OpenITwo: 'OpenI Two', OpenITwo: 'OpenI Two',
chenduCenter: 'ChenDu AI Center',
OpenIChengdu: 'OpenI ChengDu AI Chenter',
chengduCenter: 'ChengDu AI Center',
pclcci: 'PCL Cloud Computer Institute', pclcci: 'PCL Cloud Computer Institute',
hefeiCenter: 'HeFei AI Center', hefeiCenter: 'HeFei AI Center',
xuchangCenter: 'XuChang AI Center', xuchangCenter: 'XuChang AI Center',


+ 2
- 1
web_src/vuepages/langs/config/zh-CN.js View File

@@ -82,7 +82,8 @@ const zh = {
C2Net: '智算集群', C2Net: '智算集群',
OpenIOne: '云脑一', OpenIOne: '云脑一',
OpenITwo: '云脑二', OpenITwo: '云脑二',
chenduCenter: '成都人工智能计算中心',
OpenIChengdu: '启智成都智算',
chengduCenter: '成都智算',
pclcci: '鹏城云计算所', pclcci: '鹏城云计算所',
hefeiCenter: '合肥类脑类脑智能开放平台', hefeiCenter: '合肥类脑类脑智能开放平台',
xuchangCenter: '中原人工智能计算中心', xuchangCenter: '中原人工智能计算中心',


+ 3
- 2
web_src/vuepages/pages/resources/components/QueueDialog.vue View File

@@ -10,7 +10,8 @@
<span>{{ $t('resourcesManagement.resQueueName') }}</span> <span>{{ $t('resourcesManagement.resQueueName') }}</span>
</div> </div>
<div class="content"> <div class="content">
<el-input v-model="dataInfo.QueueCode" placeholder="" :disabled="type === 'edit'" maxlength="255"></el-input>
<el-input v-model="dataInfo.QueueCode" placeholder="" :disabled="type === 'edit'" maxlength="255">
</el-input>
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@@ -101,7 +102,7 @@ export default {
return { return {
dialogShow: false, dialogShow: false,
clusterList: [CLUSTERS[0]], clusterList: [CLUSTERS[0]],
computingCenterList: [AI_CENTER[0], AI_CENTER[1]],
computingCenterList: [AI_CENTER[0], AI_CENTER[1], AI_CENTER[2]],
computingTypeList: [...COMPUTER_RESOURCES], computingTypeList: [...COMPUTER_RESOURCES],
cardTypeList: [...ACC_CARD_TYPE], cardTypeList: [...ACC_CARD_TYPE],




+ 1
- 1
web_src/vuepages/pages/resources/components/SceneDialog.vue View File

@@ -88,7 +88,7 @@
<script> <script>
import BaseDialog from '~/components/BaseDialog.vue'; import BaseDialog from '~/components/BaseDialog.vue';
import { getResQueueCode, getResSpecificationList, addResScene, updateResScene } from '~/apis/modules/resources'; import { getResQueueCode, getResSpecificationList, addResScene, updateResScene } from '~/apis/modules/resources';
import { JOB_TYPE, CLUSTERS, AI_CENTER, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const';
import { JOB_TYPE, CLUSTERS, ACC_CARD_TYPE, SPECIFICATION_STATUS } from '~/const';
import { getListValueWithKey } from '~/utils'; import { getListValueWithKey } from '~/utils';


export default { export default {


Loading…
Cancel
Save