# 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.jstags/v1.22.9.2^2
| @@ -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 | |||||
| } | |||||
| @@ -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) | |||||
| } | } | ||||
| } | } | ||||
| @@ -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 { | ||||
| @@ -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 | ||||
| @@ -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 { | ||||
| @@ -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" | ||||
| @@ -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 | ||||
| ) | ) | ||||
| @@ -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 | ||||
| @@ -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 | |||||
| } | |||||
| */ | |||||
| @@ -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 | |||||
| } | |||||
| @@ -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) | |||||
| } | |||||
| @@ -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,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() | ||||
| @@ -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 | ||||
| @@ -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=任务名称 | ||||
| @@ -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) | ||||
| } | } | ||||
| @@ -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, | |||||
| } | } | ||||
| } | } | ||||
| @@ -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 == "" { | ||||
| @@ -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 | ||||
| } | } | ||||
| @@ -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 | ||||
| @@ -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) | ||||
| @@ -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) | ||||
| } | } | ||||
| @@ -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, | |||||
| }) | }) | ||||
| } | } | ||||
| @@ -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}} | ||||
| @@ -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}} | ||||
| @@ -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;"> | <div class="required unite inline min_title fields" style="width: 90%;margin-left: 5.7rem;"> | ||||
| <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> | |||||
| @@ -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> | ||||
| @@ -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; | ||||
| } | } | ||||
| }) | }) | ||||
| @@ -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"> | ||||
| @@ -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> | |||||
| @@ -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}} | ||||
| @@ -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; | ||||
| } | } | ||||
| }) | }) | ||||
| @@ -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> | ||||
| @@ -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; | ||||
| } | } | ||||
| }) | }) | ||||
| @@ -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; | ||||
| } | } | ||||
| }) | }) | ||||
| @@ -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> | ||||
| @@ -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; | ||||
| } | } | ||||
| }) | }) | ||||
| @@ -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}} | ||||
| @@ -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) | ||||
| @@ -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> | ||||
| @@ -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; | ||||
| } | } | ||||
| }) | }) | ||||
| @@ -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> | ||||
| @@ -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() | ||||
| @@ -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"> {{$.i18n.Tr "repo.modelconvert.importfirst2"}} </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"> {{$.i18n.Tr "repo.platform_instructions2"}} </a>{{$.i18n.Tr "repo.platform_instructions3"}}</div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -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"> {{$.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"> {{$.i18n.Tr "repo.platform_instructions2"}} </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() | ||||
| @@ -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> | ||||
| @@ -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}}" | ||||
| @@ -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') | ||||
| @@ -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" | ||||
| @@ -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) => { | ||||
| @@ -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", | |||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -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'); | ||||
| @@ -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') }]; | ||||
| @@ -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', | ||||
| @@ -82,7 +82,8 @@ const zh = { | |||||
| C2Net: '智算集群', | C2Net: '智算集群', | ||||
| OpenIOne: '云脑一', | OpenIOne: '云脑一', | ||||
| OpenITwo: '云脑二', | OpenITwo: '云脑二', | ||||
| chenduCenter: '成都人工智能计算中心', | |||||
| OpenIChengdu: '启智成都智算', | |||||
| chengduCenter: '成都智算', | |||||
| pclcci: '鹏城云计算所', | pclcci: '鹏城云计算所', | ||||
| hefeiCenter: '合肥类脑类脑智能开放平台', | hefeiCenter: '合肥类脑类脑智能开放平台', | ||||
| xuchangCenter: '中原人工智能计算中心', | xuchangCenter: '中原人工智能计算中心', | ||||
| @@ -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], | ||||
| @@ -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 { | ||||