| @@ -439,6 +439,19 @@ func GetModelArtsUserAttachments(userID int64) ([]*AttachmentUsername, error) { | |||
| return getModelArtsUserAttachments(x, userID) | |||
| } | |||
| func getModelArtsTrainAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) { | |||
| attachments := make([]*AttachmentUsername, 0, 10) | |||
| if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ | |||
| "= `user`.id").Where("attachment.type = ? and (uploader_id= ? or is_private = ?) and attachment.decompress_state = ?", TypeCloudBrainTwo, userID, false, DecompressStateDone).Find(&attachments); err != nil { | |||
| return nil, err | |||
| } | |||
| return attachments, nil | |||
| } | |||
| func GetModelArtsTrainAttachments(userID int64) ([]*AttachmentUsername, error) { | |||
| return getModelArtsTrainAttachments(x, userID) | |||
| } | |||
| func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { | |||
| if !isSigned { | |||
| return false | |||
| @@ -19,6 +19,9 @@ type JobType string | |||
| type ModelArtsJobStatus string | |||
| const ( | |||
| NPUResource = "NPU" | |||
| GPUResource = "CPU/GPU" | |||
| JobWaiting CloudbrainStatus = "WAITING" | |||
| JobStopped CloudbrainStatus = "STOPPED" | |||
| JobSucceeded CloudbrainStatus = "SUCCEEDED" | |||
| @@ -88,6 +91,9 @@ type Cloudbrain struct { | |||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||
| Duration int64 | |||
| TrainJobDuration string | |||
| Image string //GPU镜像名称 | |||
| GpuQueue string //GPU类型即GPU队列 | |||
| ResourceSpecId int //GPU规格id | |||
| DeletedAt time.Time `xorm:"deleted"` | |||
| CanDebug bool `xorm:"-"` | |||
| CanDel bool `xorm:"-"` | |||
| @@ -1,7 +1,6 @@ | |||
| package models | |||
| import ( | |||
| "encoding/json" | |||
| "fmt" | |||
| "sort" | |||
| "strconv" | |||
| @@ -202,15 +201,7 @@ func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusi | |||
| return nil, 0 | |||
| } | |||
| log.Info("query return total:" + fmt.Sprint(allCount)) | |||
| if allCount == 0 { | |||
| CommitCodeSizeMap, err := GetAllUserKPIStats() | |||
| if err != nil { | |||
| log.Info("query commit code errr.") | |||
| } else { | |||
| log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) | |||
| } | |||
| RefreshUserStaticAllTabel(make(map[string]int), CommitCodeSizeMap) | |||
| } | |||
| pageSize := 1000 | |||
| totalPage := int(allCount) / pageSize | |||
| userBusinessAnalysisReturnList := UserBusinessAnalysisAllList{} | |||
| @@ -370,7 +361,7 @@ func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap ma | |||
| CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | |||
| CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | |||
| IssueCountMap := queryAction(start_unix, end_unix, 6) | |||
| IssueCountMap := queryCreateIssue(start_unix, end_unix) | |||
| CommentCountMap := queryComment(start_unix, end_unix) | |||
| FocusRepoCountMap := queryWatch(start_unix, end_unix) | |||
| @@ -395,7 +386,7 @@ func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap ma | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("`user`.*").Table("user").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| userList := make([]*User, 0) | |||
| sess.Find(&userList) | |||
| for i, userRecord := range userList { | |||
| @@ -528,7 +519,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| DataDate := startTime.Format("2006-01-02") | |||
| CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | |||
| CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | |||
| IssueCountMap := queryAction(start_unix, end_unix, 6) | |||
| IssueCountMap := queryCreateIssue(start_unix, end_unix) | |||
| CommentCountMap := queryComment(start_unix, end_unix) | |||
| FocusRepoCountMap := queryWatch(start_unix, end_unix) | |||
| @@ -559,7 +550,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("`user`.*").Table("user").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| userList := make([]*User, 0) | |||
| sess.Find(&userList) | |||
| @@ -709,7 +700,7 @@ func querySolveIssue(start_unix int64, end_unix int64) map[int64]int { | |||
| issueAssigneesList := make([]*IssueAssignees, 0) | |||
| sess.Select("issue_assignees.*").Table("issue_assignees"). | |||
| Join("inner", "issue", "issue.id=issue_assignees.issue_id"). | |||
| Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| Where(cond).OrderBy("issue_assignees.id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Find(&issueAssigneesList) | |||
| @@ -744,7 +735,7 @@ func queryPullRequest(start_unix int64, end_unix int64) map[int64]int { | |||
| indexTotal = 0 | |||
| for { | |||
| issueList := make([]*Issue, 0) | |||
| sess.Select("issue.*").Table("issue").Join("inner", "pull_request", "issue.id=pull_request.issue_id").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("issue.*").Table("issue").Join("inner", "pull_request", "issue.id=pull_request.issue_id").Where(cond).OrderBy("issue.id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Find(&issueList) | |||
| log.Info("query issue(PR) size=" + fmt.Sprint(len(issueList))) | |||
| for _, issueRecord := range issueList { | |||
| @@ -777,7 +768,7 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[i | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| actionList := make([]*Action, 0) | |||
| sess.Find(&actionList) | |||
| @@ -799,29 +790,30 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[i | |||
| return resultMap | |||
| } | |||
| func queryAction(start_unix int64, end_unix int64, actionType int64) map[int64]int { | |||
| func queryCreateIssue(start_unix int64, end_unix int64) map[int64]int { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| resultMap := make(map[int64]int) | |||
| cond := "op_type=" + fmt.Sprint(actionType) + " and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||
| cond := "is_pull=false and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||
| count, err := sess.Where(cond).Count(new(Action)) | |||
| count, err := sess.Where(cond).Count(new(Issue)) | |||
| if err != nil { | |||
| log.Info("query Action error. return.") | |||
| log.Info("query Issue error. return.") | |||
| return resultMap | |||
| } | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| actionList := make([]*Action, 0) | |||
| sess.Find(&actionList) | |||
| log.Info("query action size=" + fmt.Sprint(len(actionList))) | |||
| for _, actionRecord := range actionList { | |||
| if _, ok := resultMap[actionRecord.UserID]; !ok { | |||
| resultMap[actionRecord.UserID] = 1 | |||
| sess.Select("id,poster_id").Table("issue").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| issueList := make([]*Issue, 0) | |||
| sess.Find(&issueList) | |||
| log.Info("query issue size=" + fmt.Sprint(len(issueList))) | |||
| for _, issueRecord := range issueList { | |||
| if _, ok := resultMap[issueRecord.PosterID]; !ok { | |||
| resultMap[issueRecord.PosterID] = 1 | |||
| } else { | |||
| resultMap[actionRecord.UserID] += 1 | |||
| resultMap[issueRecord.PosterID] += 1 | |||
| } | |||
| } | |||
| indexTotal += Page_SIZE | |||
| @@ -830,6 +822,7 @@ func queryAction(start_unix int64, end_unix int64, actionType int64) map[int64]i | |||
| } | |||
| } | |||
| return resultMap | |||
| } | |||
| func queryComment(start_unix int64, end_unix int64) map[int64]int { | |||
| @@ -846,7 +839,7 @@ func queryComment(start_unix int64, end_unix int64) map[int64]int { | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,type,poster_id").Table("comment").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,type,poster_id").Table("comment").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| commentList := make([]*Comment, 0) | |||
| sess.Find(&commentList) | |||
| log.Info("query Comment size=" + fmt.Sprint(len(commentList))) | |||
| @@ -882,7 +875,7 @@ func queryWatch(start_unix int64, end_unix int64) map[int64]int { | |||
| indexTotal = 0 | |||
| for { | |||
| watchList := make([]*Watch, 0) | |||
| sess.Select("id,user_id,repo_id").Table("watch").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,user_id,repo_id").Table("watch").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Find(&watchList) | |||
| log.Info("query Watch size=" + fmt.Sprint(len(watchList))) | |||
| @@ -920,7 +913,7 @@ func queryStar(start_unix int64, end_unix int64) map[int64]int { | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,uid,repo_id").Table("star").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,uid,repo_id").Table("star").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| starList := make([]*Star, 0) | |||
| sess.Find(&starList) | |||
| @@ -956,7 +949,7 @@ func queryFollow(start_unix int64, end_unix int64) map[int64]int { | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,user_id,follow_id").Table("follow").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,user_id,follow_id").Table("follow").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| followList := make([]*Follow, 0) | |||
| sess.Find(&followList) | |||
| @@ -992,7 +985,7 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,uploader_id,size").Table("attachment").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,uploader_id,size").Table("attachment").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| attachmentList := make([]*Attachment, 0) | |||
| sess.Find(&attachmentList) | |||
| @@ -1028,7 +1021,7 @@ func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,owner_id,name").Table("repository").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| sess.Select("id,owner_id,name").Table("repository").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| repoList := make([]*Repository, 0) | |||
| sess.Find(&repoList) | |||
| log.Info("query Repository size=" + fmt.Sprint(len(repoList))) | |||
| @@ -1099,8 +1092,7 @@ func queryUserRepoOpenIIndex(start_unix int64, end_unix int64) map[int64]float64 | |||
| } | |||
| } | |||
| userMapJson, _ := json.Marshal(userMap) | |||
| log.Info("userMapJson=" + string(userMapJson)) | |||
| log.Info("user openi index size=" + fmt.Sprint(len(userMap))) | |||
| return userMap | |||
| } | |||
| @@ -1119,7 +1111,7 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| statictisSess.Select("id,u_id").Table("user_login_log").Where(cond).Limit(Page_SIZE, int(indexTotal)) | |||
| statictisSess.Select("id,u_id").Table("user_login_log").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||
| userLoginLogList := make([]*UserLoginLog, 0) | |||
| statictisSess.Find(&userLoginLogList) | |||
| log.Info("query user login size=" + fmt.Sprint(len(userLoginLogList))) | |||
| @@ -1135,7 +1127,7 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { | |||
| break | |||
| } | |||
| } | |||
| log.Info("user login size=" + fmt.Sprint(len(resultMap))) | |||
| return resultMap | |||
| } | |||
| @@ -1,6 +1,8 @@ | |||
| package cloudbrain | |||
| import ( | |||
| "code.gitea.io/gitea/modules/storage" | |||
| "encoding/json" | |||
| "errors" | |||
| "strconv" | |||
| @@ -107,6 +109,9 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||
| uuid | |||
| var resourceSpec *models.ResourceSpec | |||
| if ResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||
| } | |||
| for _, spec := range ResourceSpecs.ResourceSpec { | |||
| if resourceSpecId == spec.Id { | |||
| resourceSpec = spec | |||
| @@ -185,28 +190,143 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||
| }, | |||
| }) | |||
| if err != nil { | |||
| log.Error("CreateJob failed:", err.Error()) | |||
| log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"]) | |||
| return err | |||
| } | |||
| if jobResult.Code != Success { | |||
| log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg) | |||
| log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"]) | |||
| return errors.New(jobResult.Msg) | |||
| } | |||
| var jobID = jobResult.Payload["jobId"].(string) | |||
| err = models.CreateCloudbrain(&models.Cloudbrain{ | |||
| Status: string(models.JobWaiting), | |||
| UserID: ctx.User.ID, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobID, | |||
| JobName: jobName, | |||
| SubTaskName: SubTaskName, | |||
| JobType: jobType, | |||
| Type: models.TypeCloudBrainOne, | |||
| Uuid: uuid, | |||
| Status: string(models.JobWaiting), | |||
| UserID: ctx.User.ID, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobID, | |||
| JobName: jobName, | |||
| SubTaskName: SubTaskName, | |||
| JobType: jobType, | |||
| Type: models.TypeCloudBrainOne, | |||
| Uuid: uuid, | |||
| Image: image, | |||
| GpuQueue: gpuQueue, | |||
| ResourceSpecId: resourceSpecId, | |||
| ComputeResource: models.GPUResource, | |||
| }) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| func RestartTask(ctx *context.Context, task *models.Cloudbrain) error { | |||
| dataActualPath := setting.Attachment.Minio.RealPath + | |||
| setting.Attachment.Minio.Bucket + "/" + | |||
| setting.Attachment.Minio.BasePath + | |||
| models.AttachmentRelativePath(task.Uuid) + | |||
| task.Uuid | |||
| jobName := task.JobName | |||
| var resourceSpec *models.ResourceSpec | |||
| if ResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||
| } | |||
| for _, spec := range ResourceSpecs.ResourceSpec { | |||
| if task.ResourceSpecId == spec.Id { | |||
| resourceSpec = spec | |||
| } | |||
| } | |||
| if resourceSpec == nil { | |||
| log.Error("no such resourceSpecId(%d)", task.ResourceSpecId, ctx.Data["MsgID"]) | |||
| return errors.New("no such resourceSpec") | |||
| } | |||
| jobResult, err := CreateJob(jobName, models.CreateJobParams{ | |||
| JobName: jobName, | |||
| RetryCount: 1, | |||
| GpuType: task.GpuQueue, | |||
| Image: task.Image, | |||
| TaskRoles: []models.TaskRole{ | |||
| { | |||
| Name: SubTaskName, | |||
| TaskNumber: 1, | |||
| MinSucceededTaskCount: 1, | |||
| MinFailedTaskCount: 1, | |||
| CPUNumber: resourceSpec.CpuNum, | |||
| GPUNumber: resourceSpec.GpuNum, | |||
| MemoryMB: resourceSpec.MemMiB, | |||
| ShmMB: resourceSpec.ShareMemMiB, | |||
| Command: Command, | |||
| NeedIBDevice: false, | |||
| IsMainRole: false, | |||
| UseNNI: false, | |||
| }, | |||
| }, | |||
| Volumes: []models.Volume{ | |||
| { | |||
| HostPath: models.StHostPath{ | |||
| Path: storage.GetMinioPath(jobName, CodeMountPath + "/"), | |||
| MountPath: CodeMountPath, | |||
| ReadOnly: false, | |||
| }, | |||
| }, | |||
| { | |||
| HostPath: models.StHostPath{ | |||
| Path: dataActualPath, | |||
| MountPath: DataSetMountPath, | |||
| ReadOnly: true, | |||
| }, | |||
| }, | |||
| { | |||
| HostPath: models.StHostPath{ | |||
| Path: storage.GetMinioPath(jobName, ModelMountPath + "/"), | |||
| MountPath: ModelMountPath, | |||
| ReadOnly: false, | |||
| }, | |||
| }, | |||
| { | |||
| HostPath: models.StHostPath{ | |||
| Path: storage.GetMinioPath(jobName, BenchMarkMountPath + "/"), | |||
| MountPath: BenchMarkMountPath, | |||
| ReadOnly: true, | |||
| }, | |||
| }, | |||
| { | |||
| HostPath: models.StHostPath{ | |||
| Path: storage.GetMinioPath(jobName, Snn4imagenetMountPath + "/"), | |||
| MountPath: Snn4imagenetMountPath, | |||
| ReadOnly: true, | |||
| }, | |||
| }, | |||
| { | |||
| HostPath: models.StHostPath{ | |||
| Path: storage.GetMinioPath(jobName, BrainScoreMountPath + "/"), | |||
| MountPath: BrainScoreMountPath, | |||
| ReadOnly: true, | |||
| }, | |||
| }, | |||
| }, | |||
| }) | |||
| if err != nil { | |||
| log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"]) | |||
| return err | |||
| } | |||
| if jobResult.Code != Success { | |||
| log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"]) | |||
| return errors.New(jobResult.Msg) | |||
| } | |||
| var jobID = jobResult.Payload["jobId"].(string) | |||
| task.JobID = jobID | |||
| task.Status = string(models.JobWaiting) | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", jobName, err.Error(), ctx.Data["MsgID"]) | |||
| return err | |||
| } | |||
| @@ -48,12 +48,8 @@ const ( | |||
| PerPage = 10 | |||
| IsLatestVersion = "1" | |||
| NotLatestVersion = "0" | |||
| // ComputeResource = "NPU" | |||
| NPUResource = "NPU" | |||
| GPUResource = "CPU/GPU" | |||
| AllResource = "all" | |||
| DebugType = -1 | |||
| VersionCount = 1 | |||
| DebugType = -1 | |||
| VersionCount = 1 | |||
| SortByCreateTime = "create_time" | |||
| ConfigTypeCustom = "custom" | |||
| @@ -215,14 +211,15 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin | |||
| } | |||
| err = models.CreateCloudbrain(&models.Cloudbrain{ | |||
| Status: string(models.JobWaiting), | |||
| UserID: ctx.User.ID, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobResult.ID, | |||
| JobName: jobName, | |||
| JobType: string(models.JobTypeDebug), | |||
| Type: models.TypeCloudBrainTwo, | |||
| Uuid: uuid, | |||
| Status: string(models.JobWaiting), | |||
| UserID: ctx.User.ID, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobResult.ID, | |||
| JobName: jobName, | |||
| JobType: string(models.JobTypeDebug), | |||
| Type: models.TypeCloudBrainTwo, | |||
| Uuid: uuid, | |||
| ComputeResource: models.NPUResource, | |||
| }) | |||
| if err != nil { | |||
| @@ -277,7 +274,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| DatasetName: attach.Name, | |||
| CommitID: req.CommitID, | |||
| IsLatestVersion: req.IsLatestVersion, | |||
| ComputeResource: NPUResource, | |||
| ComputeResource: models.NPUResource, | |||
| EngineID: req.EngineID, | |||
| TrainUrl: req.TrainUrl, | |||
| BranchName: req.BranchName, | |||
| @@ -360,7 +357,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job | |||
| CommitID: req.CommitID, | |||
| IsLatestVersion: req.IsLatestVersion, | |||
| PreVersionName: req.PreVersionName, | |||
| ComputeResource: NPUResource, | |||
| ComputeResource: models.GPUResource, | |||
| EngineID: req.EngineID, | |||
| TrainUrl: req.TrainUrl, | |||
| BranchName: req.BranchName, | |||
| @@ -174,7 +174,7 @@ sendjob: | |||
| return &result, nil | |||
| } | |||
| func StopJob(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { | |||
| func ManageNotebook(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { | |||
| checkSetting() | |||
| client := getRestyClient() | |||
| var result models.NotebookActionResult | |||
| @@ -207,8 +207,8 @@ sendjob: | |||
| } | |||
| if len(response.ErrorCode) != 0 { | |||
| log.Error("StopJob failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||
| return &result, fmt.Errorf("StopJob failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||
| log.Error("ManageNotebook failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||
| return &result, fmt.Errorf("ManageNotebook failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||
| } | |||
| return &result, nil | |||
| @@ -21,7 +21,8 @@ type Fields struct { | |||
| Format string `json:"format"` | |||
| } | |||
| type MatchPhrase struct { | |||
| Message string `json:"message"` | |||
| Message string `json:"message,omitempty"` | |||
| TagName string `json:"tagName.keyword,omitempty"` | |||
| } | |||
| type Should struct { | |||
| MatchPhrase MatchPhrase `json:"match_phrase"` | |||
| @@ -144,7 +145,7 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje | |||
| inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1) | |||
| inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField | |||
| inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat | |||
| inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 3) | |||
| inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 4) | |||
| //限定查询时间 | |||
| var timeRange Range | |||
| timeRange.Timestamptest.Gte = Gte | |||
| @@ -159,6 +160,24 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje | |||
| var projectName FilterMatchPhrase | |||
| projectName.ProjectName = Project | |||
| inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[2].FilterMatchPhrase = &projectName | |||
| //限定页面 | |||
| var bool Bool | |||
| bool.Should = make([]Should, 14) | |||
| bool.Should[0].MatchPhrase.TagName = "%{[request][3]}" | |||
| bool.Should[1].MatchPhrase.TagName = "datasets?type=0" | |||
| bool.Should[2].MatchPhrase.TagName = "datasets?type=1" | |||
| bool.Should[3].MatchPhrase.TagName = "issues" | |||
| bool.Should[4].MatchPhrase.TagName = "labels" | |||
| bool.Should[5].MatchPhrase.TagName = "pulls" | |||
| bool.Should[6].MatchPhrase.TagName = "wiki" | |||
| bool.Should[7].MatchPhrase.TagName = "activity" | |||
| bool.Should[8].MatchPhrase.TagName = "cloudbrain" | |||
| bool.Should[9].MatchPhrase.TagName = "modelarts" | |||
| bool.Should[10].MatchPhrase.TagName = "blockchain" | |||
| bool.Should[11].MatchPhrase.TagName = "watchers" | |||
| bool.Should[12].MatchPhrase.TagName = "stars" | |||
| bool.Should[13].MatchPhrase.TagName = "forks" | |||
| inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[3].Bool = &bool | |||
| return inputStruct | |||
| } | |||
| @@ -80,3 +80,7 @@ func (l *LocalStorage) HasObject(path string) (bool, error) { | |||
| func (l *LocalStorage) UploadObject(fileName, filePath string) error { | |||
| return nil | |||
| } | |||
| func (l *LocalStorage) DeleteDir(dir string) error { | |||
| return nil | |||
| } | |||
| @@ -11,6 +11,9 @@ import ( | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "github.com/minio/minio-go" | |||
| ) | |||
| @@ -76,6 +79,29 @@ func (m *MinioStorage) Delete(path string) error { | |||
| return m.client.RemoveObject(m.bucket, m.buildMinioPath(path)) | |||
| } | |||
| // Delete delete a file | |||
| func (m *MinioStorage) DeleteDir(dir string) error { | |||
| objectsCh := make(chan string) | |||
| // Send object names that are needed to be removed to objectsCh | |||
| go func() { | |||
| defer close(objectsCh) | |||
| // List all objects from a bucket-name with a matching prefix. | |||
| for object := range m.client.ListObjects(m.bucket, dir, true, nil) { | |||
| if object.Err != nil { | |||
| log.Error("ListObjects failed:%v", object.Err) | |||
| } | |||
| objectsCh <- object.Key | |||
| } | |||
| }() | |||
| for rErr := range m.client.RemoveObjects(m.bucket, objectsCh) { | |||
| log.Error("Error detected during deletion: ", rErr) | |||
| } | |||
| return nil | |||
| } | |||
| //Get Presigned URL for get object | |||
| func (m *MinioStorage) PresignedGetURL(path string, fileName string) (string, error) { | |||
| // Set request parameters for content-disposition. | |||
| @@ -128,3 +154,7 @@ func (m *MinioStorage) UploadObject(fileName, filePath string) error { | |||
| _, err := m.client.FPutObject(m.bucket, fileName, filePath, minio.PutObjectOptions{}) | |||
| return err | |||
| } | |||
| func GetMinioPath(jobName, suffixPath string) string { | |||
| return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath | |||
| } | |||
| @@ -23,6 +23,7 @@ type ObjectStorage interface { | |||
| Save(path string, r io.Reader) (int64, error) | |||
| Open(path string) (io.ReadCloser, error) | |||
| Delete(path string) error | |||
| DeleteDir(dir string) error | |||
| PresignedGetURL(path string, fileName string) (string, error) | |||
| PresignedPutURL(path string) (string, error) | |||
| HasObject(path string) (bool, error) | |||
| @@ -778,6 +778,10 @@ datasets = Datasets | |||
| datasets.desc = Enable Dataset | |||
| cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. | |||
| model_manager = Model | |||
| model_noright=No right | |||
| model_rename=Duplicate model name, please modify model name. | |||
| debug=Debug | |||
| stop=Stop | |||
| delete=Delete | |||
| @@ -784,8 +784,10 @@ cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 | |||
| model_manager = 模型 | |||
| model_noright=无权限操作 | |||
| model_rename=模型名称重复,请修改模型名称 | |||
| debug=调试 | |||
| debug_again=再次调试 | |||
| stop=停止 | |||
| delete=删除 | |||
| model_download=模型下载 | |||
| @@ -11655,6 +11655,11 @@ | |||
| "autolinker": "~0.28.0" | |||
| } | |||
| }, | |||
| "remixicon": { | |||
| "version": "2.5.0", | |||
| "resolved": "https://registry.npmjs.org/remixicon/-/remixicon-2.5.0.tgz", | |||
| "integrity": "sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww==" | |||
| }, | |||
| "remove-bom-buffer": { | |||
| "version": "3.0.0", | |||
| "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", | |||
| @@ -42,6 +42,7 @@ | |||
| "postcss-preset-env": "6.7.0", | |||
| "postcss-safe-parser": "4.0.2", | |||
| "qs": "6.9.4", | |||
| "remixicon": "2.5.0", | |||
| "spark-md5": "3.0.1", | |||
| "svg-sprite-loader": "5.0.0", | |||
| "svgo": "1.3.2", | |||
| @@ -7,6 +7,7 @@ package repo | |||
| import ( | |||
| "net/http" | |||
| "os" | |||
| "strconv" | |||
| "strings" | |||
| @@ -14,6 +15,7 @@ import ( | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| ) | |||
| @@ -237,7 +239,7 @@ func DelTrainJobVersion(ctx *context.APIContext) { | |||
| JobID: jobID, | |||
| }) | |||
| if err != nil { | |||
| ctx.ServerError("get VersionListCount faild", err) | |||
| ctx.ServerError("get VersionListCount failed", err) | |||
| return | |||
| } | |||
| if VersionListCount > 0 { | |||
| @@ -255,6 +257,8 @@ func DelTrainJobVersion(ctx *context.APIContext) { | |||
| return | |||
| } | |||
| } | |||
| } else { //已删除该任务下的所有版本 | |||
| deleteJobStorage(task.JobName) | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| @@ -321,3 +325,21 @@ func ModelList(ctx *context.APIContext) { | |||
| "PageIsCloudBrain": true, | |||
| }) | |||
| } | |||
| func deleteJobStorage(jobName string) error { | |||
| //delete local | |||
| localJobPath := setting.JobPath + jobName | |||
| err := os.RemoveAll(localJobPath) | |||
| if err != nil { | |||
| log.Error("RemoveAll(%s) failed:%v", localJobPath, err) | |||
| } | |||
| //delete oss | |||
| dirPath := setting.CodePathPrefix + jobName + "/" | |||
| err = storage.ObsRemoveObject(setting.Bucket, dirPath) | |||
| if err != nil { | |||
| log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) | |||
| } | |||
| return nil | |||
| } | |||
| @@ -105,6 +105,23 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||
| return nil | |||
| } | |||
| func SaveNewNameModel(ctx *context.Context) { | |||
| name := ctx.Query("Name") | |||
| if name == "" { | |||
| ctx.Error(500, fmt.Sprintf("name or version is null.")) | |||
| return | |||
| } | |||
| aimodels := models.QueryModelByName(name, ctx.Repo.Repository.ID) | |||
| if len(aimodels) > 0 { | |||
| ctx.Error(500, ctx.Tr("repo.model_rename")) | |||
| return | |||
| } | |||
| SaveModel(ctx) | |||
| log.Info("save model end.") | |||
| } | |||
| func SaveModel(ctx *context.Context) { | |||
| log.Info("save model start.") | |||
| JobId := ctx.Query("JobId") | |||
| @@ -206,7 +206,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| } | |||
| repo := ctx.Repo.Repository | |||
| downloadCode(repo, codePath) | |||
| uploadCodeToMinio(codePath+"/", jobName, "/code/") | |||
| uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") | |||
| modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" | |||
| mkModelPath(modelPath) | |||
| @@ -236,15 +236,89 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/") | |||
| } | |||
| err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, codePath, getMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
| getMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), getMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
| getMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, resourceSpecId) | |||
| err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, resourceSpecId) | |||
| if err != nil { | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func CloudBrainRestart(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var resultCode = "0" | |||
| var errorMsg = "" | |||
| var status = "" | |||
| for { | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID(%s) failed:%v", jobID, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| if task.Status != string(models.JobStopped) && task.Status != string(models.JobSucceeded) && task.Status != string(models.JobFailed) { | |||
| log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "the job is not stopped" | |||
| break | |||
| } | |||
| if task.Image == "" || task.GpuQueue == "" || task.Type != models.TypeCloudBrainOne { | |||
| log.Error("the job(%s) version is too old", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "the job's version is too old and can not be restarted" | |||
| break | |||
| } | |||
| if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()){ | |||
| log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "you have no right to restart the job" | |||
| break | |||
| } | |||
| count, err := models.GetCloudbrainCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "the user already has running or waiting task" | |||
| break | |||
| } | |||
| } | |||
| err = cloudbrain.RestartTask(ctx, task) | |||
| if err != nil { | |||
| log.Error("RestartTask failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| status = task.Status | |||
| jobID = task.JobID | |||
| break | |||
| } | |||
| ctx.JSON(200, map[string]string{ | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "job_id": jobID, | |||
| }) | |||
| } | |||
| func CloudBrainShow(ctx *context.Context) { | |||
| @@ -351,32 +425,53 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain | |||
| func CloudBrainStop(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| ctx.ServerError("GetCloudbrainByJobID failed", err) | |||
| return | |||
| } | |||
| var resultCode = "0" | |||
| var errorMsg = "" | |||
| var status = "" | |||
| if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) { | |||
| log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | |||
| ctx.ServerError("the job has been stopped", errors.New("the job has been stopped")) | |||
| return | |||
| } | |||
| for { | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| err = cloudbrain.StopJob(jobID) | |||
| if err != nil { | |||
| log.Error("StopJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"]) | |||
| ctx.ServerError("StopJob failed", err) | |||
| return | |||
| } | |||
| if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) { | |||
| log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| task.Status = string(models.JobStopped) | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.ServerError("UpdateJob failed", err) | |||
| return | |||
| err = cloudbrain.StopJob(jobID) | |||
| if err != nil { | |||
| log.Error("StopJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| task.Status = string(models.JobStopped) | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| status = task.Status | |||
| break | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.JSON(200, map[string]string{ | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "job_id": jobID, | |||
| }) | |||
| } | |||
| func StopJobsByUserID(userID int64) { | |||
| @@ -423,7 +518,7 @@ func StopJobs(cloudBrains []*models.Cloudbrain) { | |||
| Action: models.ActionStop, | |||
| } | |||
| err := retry(3, time.Second*30, func() error { | |||
| _, err := modelarts.StopJob(taskInfo.JobID, param) | |||
| _, err := modelarts.ManageNotebook(taskInfo.JobID, param) | |||
| return err | |||
| }) | |||
| logErrorAndUpdateJobStatus(err, taskInfo) | |||
| @@ -478,7 +573,9 @@ func CloudBrainDel(ctx *context.Context) { | |||
| ctx.ServerError("DeleteJob failed", err) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| deleteJobStorage(task.JobName, models.TypeCloudBrainOne) | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func CloudBrainShowModels(ctx *context.Context) { | |||
| @@ -560,7 +657,7 @@ func getImages(ctx *context.Context, imageType string) { | |||
| func GetModelDirs(jobName string, parentDir string) (string, error) { | |||
| var req string | |||
| modelActualPath := getMinioPath(jobName, cloudbrain.ModelMountPath+"/") | |||
| modelActualPath := storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/") | |||
| if parentDir == "" { | |||
| req = "baseDir=" + modelActualPath | |||
| } else { | |||
| @@ -570,10 +667,6 @@ func GetModelDirs(jobName string, parentDir string) (string, error) { | |||
| return getDirs(req) | |||
| } | |||
| func getMinioPath(jobName, suffixPath string) string { | |||
| return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath | |||
| } | |||
| func CloudBrainDownloadModel(ctx *context.Context) { | |||
| parentDir := ctx.Query("parentDir") | |||
| fileName := ctx.Query("fileName") | |||
| @@ -756,6 +849,35 @@ func mkModelPath(modelPath string) error { | |||
| return nil | |||
| } | |||
| func deleteJobStorage(jobName string, cloudbrainType int) error { | |||
| //delete local | |||
| localJobPath := setting.JobPath + jobName | |||
| err := os.RemoveAll(localJobPath) | |||
| if err != nil { | |||
| log.Error("RemoveAll(%s) failed:%v", localJobPath, err) | |||
| } | |||
| //delete oss | |||
| if cloudbrainType == models.TypeCloudBrainOne { | |||
| dirPath := setting.CBCodePathPrefix + jobName + "/" | |||
| err = storage.Attachments.DeleteDir(dirPath) | |||
| if err != nil { | |||
| log.Error("DeleteDir(%s) failed:%v", localJobPath, err) | |||
| } | |||
| } else if cloudbrainType == models.TypeCloudBrainTwo { | |||
| //dirPath := setting.CodePathPrefix + jobName + "/" | |||
| //err = storage.ObsRemoveObject(setting.Bucket, dirPath) | |||
| //if err != nil { | |||
| // log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) | |||
| //} | |||
| log.Info("no need to delete") | |||
| } else { | |||
| log.Error("cloudbrainType(%d) error", cloudbrainType) | |||
| } | |||
| return nil | |||
| } | |||
| func SyncCloudbrainStatus() { | |||
| cloudBrains, err := models.GetCloudBrainUnStoppedJob() | |||
| if err != nil { | |||
| @@ -268,6 +268,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) { | |||
| ctx.Data["CanWriteIssues"] = ctx.Repo.CanWriteIssuesOrPulls(false) | |||
| ctx.Data["CanWritePulls"] = ctx.Repo.CanWriteIssuesOrPulls(true) | |||
| ctx.Data["PageIsIssueList"] = true | |||
| ctx.HTML(200, tplMilestoneIssues) | |||
| } | |||
| @@ -42,6 +42,7 @@ const ( | |||
| func DebugJobIndex(ctx *context.Context) { | |||
| debugListType := ctx.Query("debugListType") | |||
| ctx.Data["ListType"] = debugListType | |||
| MustEnableCloudbrain(ctx) | |||
| repo := ctx.Repo.Repository | |||
| page := ctx.QueryInt("page") | |||
| @@ -50,11 +51,11 @@ func DebugJobIndex(ctx *context.Context) { | |||
| } | |||
| debugType := modelarts.DebugType | |||
| jobType := string(models.JobTypeDebug) | |||
| if debugListType == modelarts.GPUResource { | |||
| if debugListType == models.GPUResource { | |||
| debugType = models.TypeCloudBrainOne | |||
| jobType = "" | |||
| } | |||
| if debugListType == modelarts.NPUResource { | |||
| if debugListType == models.NPUResource { | |||
| debugType = models.TypeCloudBrainTwo | |||
| } | |||
| @@ -73,21 +74,13 @@ func DebugJobIndex(ctx *context.Context) { | |||
| } | |||
| for i, task := range ciTasks { | |||
| if task.Cloudbrain.Type == models.TypeCloudBrainOne { | |||
| ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||
| ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| ciTasks[i].Cloudbrain.ComputeResource = modelarts.GPUResource | |||
| } | |||
| if task.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||
| ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||
| ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| ciTasks[i].Cloudbrain.ComputeResource = modelarts.NPUResource | |||
| } | |||
| ciTasks[i].CanDebug = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | |||
| ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||
| } | |||
| pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
| pager.SetDefaultParams(ctx) | |||
| pager.AddParam(ctx, "debugListType", "ListType") | |||
| ctx.Data["Page"] = pager | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| ctx.Data["Tasks"] = ciTasks | |||
| @@ -156,7 +149,7 @@ func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func NotebookShow(ctx *context.Context) { | |||
| @@ -232,38 +225,105 @@ func NotebookDebug(ctx *context.Context) { | |||
| ctx.Redirect(debugUrl) | |||
| } | |||
| func NotebookStop(ctx *context.Context) { | |||
| func NotebookManage(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| log.Info(jobID) | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| ctx.ServerError("GetCloudbrainByJobID failed", err) | |||
| return | |||
| } | |||
| var action = ctx.Params(":action") | |||
| var resultCode = "0" | |||
| var errorMsg = "" | |||
| var status = "" | |||
| if task.Status != string(models.JobRunning) { | |||
| log.Error("the job(%s) is not running", task.JobName) | |||
| ctx.ServerError("the job is not running", errors.New("the job is not running")) | |||
| return | |||
| } | |||
| for { | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID failed:%v", err, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| param := models.NotebookAction{ | |||
| Action: models.ActionStop, | |||
| } | |||
| res, err := modelarts.StopJob(jobID, param) | |||
| if err != nil { | |||
| log.Error("StopJob(%s) failed:%v", task.JobName, err.Error()) | |||
| ctx.ServerError("StopJob failed", err) | |||
| return | |||
| } | |||
| if action == models.ActionStop { | |||
| if task.Status != string(models.ModelArtsRunning) { | |||
| log.Error("the job(%s) is not running", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "the job is not running" | |||
| break | |||
| } | |||
| task.Status = res.CurrentStatus | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.ServerError("UpdateJob failed", err) | |||
| return | |||
| if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin() && !ctx.IsUserRepoOwner()){ | |||
| log.Error("the user has no right ro stop the job", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "you have no right to stop the job" | |||
| break | |||
| } | |||
| } else if action == models.ActionRestart { | |||
| if task.Status != string(models.ModelArtsStopped) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsCreateFailed) { | |||
| log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "the job is not stopped" | |||
| break | |||
| } | |||
| if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()){ | |||
| log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "you have no right to restart the job" | |||
| break | |||
| } | |||
| count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "you have already a running or waiting task, can not create more" | |||
| break | |||
| } | |||
| } | |||
| action = models.ActionStart | |||
| } else { | |||
| log.Error("the action(%s) is illegal", action, ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "非法操作" | |||
| break | |||
| } | |||
| param := models.NotebookAction{ | |||
| Action: action, | |||
| } | |||
| res, err := modelarts.ManageNotebook(jobID, param) | |||
| if err != nil { | |||
| log.Error("ManageNotebook(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "启动失败" | |||
| break | |||
| } | |||
| task.Status = res.CurrentStatus | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| status = task.Status | |||
| break | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.JSON(200, map[string]string{ | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "job_id": jobID, | |||
| }) | |||
| } | |||
| func NotebookDel(ctx *context.Context) { | |||
| @@ -274,7 +334,7 @@ func NotebookDel(ctx *context.Context) { | |||
| return | |||
| } | |||
| if task.Status != string(models.JobStopped) { | |||
| if task.Status != string(models.ModelArtsCreateFailed) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsStopped) { | |||
| log.Error("the job(%s) has not been stopped", task.JobName) | |||
| ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped")) | |||
| return | |||
| @@ -293,7 +353,7 @@ func NotebookDel(ctx *context.Context) { | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func TrainJobIndex(ctx *context.Context) { | |||
| @@ -323,6 +383,7 @@ func TrainJobIndex(ctx *context.Context) { | |||
| for i, task := range tasks { | |||
| tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | |||
| tasks[i].ComputeResource = models.NPUResource | |||
| } | |||
| pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
| @@ -364,7 +425,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = jobName | |||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| @@ -433,7 +494,7 @@ func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArts | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = jobName | |||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| @@ -521,7 +582,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = task.JobName | |||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| @@ -610,7 +671,7 @@ func versionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrai | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = task.JobName | |||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
| attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| @@ -968,10 +968,11 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/cloudbrain", func() { | |||
| m.Group("/:jobid", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.CloudBrainShow) | |||
| m.Get("/debug", reqRepoCloudBrainWriter, repo.CloudBrainDebug) | |||
| m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDebug) | |||
| m.Post("/commit_image", cloudbrain.AdminOrOwnerOrJobCreaterRight, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage) | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDel) | |||
| m.Post("/restart", reqRepoCloudBrainWriter, repo.CloudBrainRestart) | |||
| m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) | |||
| m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | |||
| m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDownloadModel) | |||
| @@ -981,6 +982,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| }, context.RepoRef()) | |||
| m.Group("/modelmanage", func() { | |||
| m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | |||
| m.Post("/create_new_model", reqRepoModelManageWriter, repo.SaveNewNameModel) | |||
| m.Delete("/delete_model", repo.DeleteModel) | |||
| m.Put("/modify_model", repo.ModifyModelInfo) | |||
| m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) | |||
| @@ -1005,8 +1007,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/notebook", func() { | |||
| m.Group("/:jobid", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) | |||
| m.Get("/debug", reqRepoCloudBrainWriter, repo.NotebookDebug) | |||
| m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookStop) | |||
| m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.NotebookDebug) | |||
| m.Post("/:action", reqRepoCloudBrainWriter, repo.NotebookManage) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel) | |||
| }) | |||
| m.Get("/create", reqRepoCloudBrainWriter, repo.NotebookNew) | |||
| @@ -93,6 +93,14 @@ | |||
| display: none; | |||
| } | |||
| .icons{ | |||
| /* position: absolute !important; | |||
| right: 150px; | |||
| top: 14px; | |||
| z-index: 2; */ | |||
| } | |||
| </style> | |||
| <div id="mask"> | |||
| @@ -182,9 +190,10 @@ | |||
| </select> | |||
| </div> | |||
| <div class="inline required field"> | |||
| <div class="inline required field" style="position: relative;"> | |||
| <label>镜像</label> | |||
| <input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" required autofocus maxlength="254"> | |||
| <i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||
| <datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | |||
| {{range .images}} | |||
| <option name="image" value="{{.Place}}">{{.PlaceView}}</option> | |||
| @@ -261,9 +270,17 @@ | |||
| <script> | |||
| let form = document.getElementById('form_id'); | |||
| $('#messageInfo').css('display','none') | |||
| let inputs = document.querySelectorAll('input[list]'); | |||
| inputs[0].addEventListener('change', function() { | |||
| $(".icon.icons").css("visibility","visible") | |||
| }); | |||
| $('#messageInfo').css('display','none') | |||
| function clearValue(){ | |||
| context=inputs[0] | |||
| context.value='' | |||
| $(".icon.icons").css("visibility","hidden") | |||
| } | |||
| form.onsubmit = function(e){ | |||
| let value_task = $("input[name='job_name']").val() | |||
| let value_image = $("input[name='image']").val() | |||
| @@ -202,14 +202,20 @@ | |||
| <div class="rect5"></div> | |||
| </div> | |||
| </div> | |||
| <!-- 提示框 --> | |||
| <div class="alert"></div> | |||
| <div class="alert"></div> | |||
| <div class="repository release dataset-list view"> | |||
| {{template "repo/header" .}} | |||
| {{template "base/alert" .}} | |||
| <!-- 提示框 --> | |||
| <!-- 列表容器 --> | |||
| <div class="ui container"> | |||
| <div class="ui two column stackable grid "> | |||
| <div class="ui negative message" style="display: none;"> | |||
| <i class="close icon"></i> | |||
| <p></p> | |||
| </div> | |||
| <div class="ui two column stackable grid"> | |||
| <div class="column"> | |||
| <div class="ui blue small menu compact selectcloudbrain"> | |||
| <a class="active item" href="{{.RepoLink}}/debugjob?debugListType=all">{{$.i18n.Tr "repo.modelarts.notebook"}}</a> | |||
| @@ -282,7 +288,7 @@ | |||
| <div class="row"> | |||
| <!-- 任务名 --> | |||
| <div class="four wide column"> | |||
| <a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}' title="{{.JobName}}" style="font-size: 14px;"> | |||
| <a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}' title="{{.JobName}}" style="font-size: 14px;"> | |||
| <span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
| </a> | |||
| </div> | |||
| @@ -315,34 +321,44 @@ | |||
| </a> | |||
| {{end}} --> | |||
| <!-- 调试 --> | |||
| {{if .CanDebug}} | |||
| {{if eq .ComputeResource "CPU/GPU"}} | |||
| <a id="model-debug-{{.JobID}}" class='ui basic {{if ne .Status "RUNNING"}} disabled {{else}}blue {{end}}button' href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/debug" target="_blank"> | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| </a> | |||
| <form id="debugAgainForm-{{.JobID}}"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDebug}} | |||
| {{if eq .Status "RUNNING"}} | |||
| <a style="margin: 0 1rem;" id="model-debug-{{.JobID}}" class='ui basic blue button' onclick='debugAgain("{{.JobID}}","{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/")'> | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| </a> | |||
| {{else}} | |||
| <a id="model-debug-{{.JobID}}" class='ui basic {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' onclick='debugAgain("{{.JobID}}","{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/")'> | |||
| {{$.i18n.Tr "repo.debug_again"}} | |||
| </a> | |||
| {{end}} | |||
| {{else}} | |||
| <a id="model-debug-{{.JobID}}" class='ui basic {{if ne .Status "RUNNING"}} disabled {{else}}blue {{end}}button' href="{{$.RepoLink}}/modelarts/notebook/{{.JobID}}/debug" target="_blank"> | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| <a class="ui basic disabled button"> | |||
| {{$.i18n.Tr "repo.debug_again"}} | |||
| </a> | |||
| {{end}} | |||
| {{else}} | |||
| <a class="ui basic disabled button"> | |||
| {{$.i18n.Tr "repo.debug"}} | |||
| </a> | |||
| {{end}} | |||
| </form> | |||
| <!-- 停止 --> | |||
| <form id="stopForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/stop" method="post" style="margin-left:-1px;"> | |||
| <form id="stopForm-{{.JobID}}" style="margin-left:-1px;"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a id="stop-model-debug-{{.JobID}}" class='ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING"}}disabled {{else}}blue {{end}}button' onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{if eq .ComputeResource "CPU/GPU" }} | |||
| <a id="stop-model-debug-{{.JobID}}" class='ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING"}}disabled {{else}}blue {{end}}button' onclick='stopDebug("{{.JobID}}","{{$.RepoLink}}/cloudbrain/{{.JobID}}/stop")'> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{else}} | |||
| <a id="stop-model-debug-{{.JobID}}" class='ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING"}}disabled {{else}}blue {{end}}button' onclick='stopDebug("{{.JobID}}","{{$.RepoLink}}/modelarts/notebook/{{.JobID}}/stop")'> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{end}} | |||
| {{else}} | |||
| <a class="ui basic disabled button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | |||
| <a class="ui basic disabled button"> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{end}} | |||
| <input type="hidden" name="debugListType" value="all"> | |||
| </form> | |||
| <!-- 删除 --> | |||
| <form id="delForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/del" method="post"> | |||
| @@ -463,10 +479,21 @@ | |||
| <script> | |||
| // 调试和评分新开窗口 | |||
| const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||
| let url={{.RepoLink}} | |||
| let getParam=location.search.split('?debugListType=').pop() | |||
| let getParam=getQueryVariable('debugListType') | |||
| let dropdownValue = getParam==='all'||getParam==='' ? '全部' : getParam | |||
| localStorage.setItem('all',location.href) | |||
| function getQueryVariable(variable) | |||
| { | |||
| let query = window.location.search.substring(1); | |||
| let vars = query.split("&"); | |||
| for (let i=0;i<vars.length;i++) { | |||
| let pair = vars[i].split("="); | |||
| if(pair[0] == variable){return pair[1];} | |||
| } | |||
| return(false); | |||
| } | |||
| function stop(obj) { | |||
| if (obj.style.color != "rgb(204, 204, 204)") { | |||
| obj.target = '_blank' | |||
| @@ -489,6 +516,7 @@ | |||
| onApprove: function() { | |||
| document.getElementById(delId).submit() | |||
| flag = true | |||
| $('.alert').html('操作成功!').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut(); | |||
| }, | |||
| onHidden: function() { | |||
| if (flag == false) { | |||
| @@ -499,7 +527,69 @@ | |||
| .modal('show') | |||
| } | |||
| } | |||
| function debugAgain(JobID,debugUrl){ | |||
| if($('#' + JobID+ '-text').text()==="RUNNING"){ | |||
| window.open(debugUrl+'debug') | |||
| }else{ | |||
| $.ajax({ | |||
| type:"POST", | |||
| url:debugUrl+'restart', | |||
| data:$('#debugAgainForm-'+JobID).serialize(), | |||
| success:function(res){ | |||
| if(res.result_code==="0"){ | |||
| if(res.job_id!==JobID){ | |||
| location.reload() | |||
| }else{ | |||
| $('#' + JobID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + JobID+ '-text').text(res.status) | |||
| $('#model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#model-delete-'+JobID).removeClass('blue').addClass('disabled') | |||
| } | |||
| }else{ | |||
| $(".ui.negative.message").css("display","block") | |||
| $(".ui.negative.message p").text(res.error_msg) | |||
| setTimeout("$('.message .close').click()",3000) | |||
| } | |||
| }, | |||
| error :function(res){ | |||
| console.log(res) | |||
| } | |||
| }) | |||
| } | |||
| } | |||
| function stopDebug(JobID,stopUrl){ | |||
| $.ajax({ | |||
| type:"POST", | |||
| url:stopUrl, | |||
| data:$('#stopForm-'+JobID).serialize(), | |||
| success:function(res){ | |||
| if(res.result_code==="0"){ | |||
| $('#' + JobID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + JobID+ '-text').text(res.status) | |||
| if(res.status==="STOPPED"){ | |||
| $('#model-debug-'+JobID).removeClass('disabled').addClass('blue').text("再次调试").css("margin","0") | |||
| $('#model-image-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#stop-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#model-delete-'+JobID).removeClass('disabled').addClass('blue') | |||
| } | |||
| else{ | |||
| $('#model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#stop-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| } | |||
| }else{ | |||
| $("ui.negative.message").text(res.error_msg) | |||
| } | |||
| }, | |||
| error :function(res){ | |||
| console.log(res) | |||
| } | |||
| }) | |||
| } | |||
| // 加载任务状态 | |||
| var timeid = window.setInterval(loadJobStatus, 15000); | |||
| $(document).ready(loadJobStatus); | |||
| @@ -508,8 +598,9 @@ | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const computeResource = job.dataset.resource | |||
| const initArray = ['STOPPED','FAILED','START_FAILED','CREATE_FAILED'] | |||
| const initArray = ['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'] | |||
| if (initArray.includes(job.textContent.trim())) { | |||
| return | |||
| } | |||
| const diffResource = computeResource == "NPU" ? 'modelarts/notebook' : 'cloudbrain' | |||
| @@ -521,32 +612,30 @@ | |||
| $('#' + jobID+ '-text').text(status) | |||
| } | |||
| if(status==="RUNNING"){ | |||
| $('#model-debug-'+jobID).removeClass('disabled') | |||
| $('#model-debug-'+jobID).addClass('blue') | |||
| $('#model-image-'+jobID).removeClass('disabled') | |||
| $('#model-image-'+jobID).addClass('blue') | |||
| $('#model-debug-'+jobID).removeClass('disabled').addClass('blue').text('调试').css("margin","0 1rem") | |||
| $('#model-image-'+jobID).removeClass('disabled').addClass('blue') | |||
| } | |||
| if(status!=="RUNNING"){ | |||
| $('#model-debug-'+jobID).removeClass('blue') | |||
| $('#model-debug-'+jobID).addClass('disabled') | |||
| $('#model-image-'+jobID).removeClass('blue') | |||
| $('#model-image-'+jobID).addClass('disabled') | |||
| // $('#model-debug-'+jobID).removeClass('blue') | |||
| // $('#model-debug-'+jobID).addClass('disabled') | |||
| $('#model-image-'+jobID).removeClass('blue').addClass('disabled') | |||
| } | |||
| if(["CREATING","STOPPING","WAITING","STARTING"].includes(status)){ | |||
| $('#model-debug-'+jobID).removeClass('blue').addClass('disabled') | |||
| } | |||
| if(['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'].includes(status)){ | |||
| $('#model-debug-'+jobID).removeClass('disabled').addClass('blue').text('再次调试').css("margin","0") | |||
| } | |||
| if(["RUNNING","WAITING"].includes(status)){ | |||
| $('#stop-model-debug-'+jobID).removeClass('disabled') | |||
| $('#stop-model-debug-'+jobID).addClass('blue') | |||
| $('#stop-model-debug-'+jobID).removeClass('disabled').addClass('blue') | |||
| } | |||
| if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED"].includes(status)){ | |||
| $('#stop-model-debug-'+jobID).removeClass('blue') | |||
| $('#stop-model-debug-'+jobID).addClass('disabled') | |||
| $('#stop-model-debug-'+jobID).removeClass('blue').addClass('disabled') | |||
| } | |||
| if(status==="STOPPED" || status==="FAILED"|| status==="START_FAILED"){ | |||
| $('#model-delete-'+jobID).removeClass('disabled') | |||
| $('#model-delete-'+jobID).addClass('blue') | |||
| $('#model-delete-'+jobID).removeClass('disabled').addClass('blue') | |||
| }else{ | |||
| $('#model-delete-'+jobID).removeClass('blue') | |||
| $('#model-delete-'+jobID).addClass('disabled') | |||
| $('#model-delete-'+jobID).removeClass('blue').addClass('disabled') | |||
| } | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| @@ -554,6 +643,7 @@ | |||
| }); | |||
| }; | |||
| $(document).ready(function(){ | |||
| dropdownValue = dropdownValue==="CPU%2FGPU"? 'CPU/GPU' : dropdownValue | |||
| $('.default.text').text(dropdownValue) | |||
| $('.ui.dropdown') | |||
| .dropdown({ | |||
| @@ -564,6 +654,12 @@ | |||
| location.href = `${url}/debugjob?debugListType=${value}` | |||
| } | |||
| }) | |||
| $('.message .close') | |||
| .on('click', function() { | |||
| $(this) | |||
| .closest('.message') | |||
| .transition('fade') | |||
| }) | |||
| }) | |||
| @@ -601,7 +697,6 @@ | |||
| // 显示弹窗,弹出相应的信息 | |||
| function showmask() { | |||
| var image_tag = !$('#image_tag').val() | |||
| console.log("image_tag",image_tag) | |||
| if(image_tag){ | |||
| return | |||
| } | |||
| @@ -612,8 +707,6 @@ | |||
| var responseText = $("iframe")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML; | |||
| var json1 = JSON.parse(responseText) | |||
| $('#mask').css('display', 'none') | |||
| parent.location.href | |||
| if (json1.result_code === "0") { | |||
| $('.alert').html('操作成功!').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut(); | |||
| } else { | |||
| @@ -337,7 +337,8 @@ | |||
| {{end}} | |||
| <div class="ui right"> | |||
| <a class="membersmore text grey" href="{{.RepoLink}}/contributors">全部 {{svg "octicon-chevron-right" 16}}</a> | |||
| <!-- <a class="membersmore text grey" href="{{.RepoLink}}/contributors">全部 {{svg "octicon-chevron-right" 16}}</a> --> | |||
| <a class="membersmore text grey" href="{{.RepoLink}}/contributors?type={{if .IsViewBranch}}branch{{else}}tag{{end}}&name={{.BranchName}}">全部 {{svg "octicon-chevron-right" 16}}</a> | |||
| </div> | |||
| </h4> | |||
| <div class="ui members" id="contributorInfo"> | |||
| @@ -121,7 +121,7 @@ | |||
| </div> | |||
| <!-- 任务运行时间 --> | |||
| <div class="two wide column text center padding0"> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}"></span> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}">{{.TrainJobDuration}}</span> | |||
| </div> | |||
| <!-- 计算资源 --> | |||
| <div class="two wide column text center padding0"> | |||
| @@ -253,35 +253,18 @@ | |||
| } | |||
| } | |||
| function loadJobDuration() { | |||
| $(".job-status").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const versionname = job.dataset.version | |||
| $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | |||
| console.log(data) | |||
| const duration = data.JobDuration | |||
| const jobID = data.JobID | |||
| $('#duration-'+jobID).text(duration) | |||
| }) | |||
| }) | |||
| } | |||
| $(document).ready(loadJobDuration); | |||
| // 加载任务状态 | |||
| var timeid = window.setInterval(loadJobStatus, 15000); | |||
| $(document).ready(loadJobStatus); | |||
| function loadJobStatus() { | |||
| $(".job-status").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const jobID = job.dataset.jobid | |||
| const repoPath = job.dataset.repopath | |||
| const versionname = job.dataset.version | |||
| if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| return | |||
| const status_text = $(`#${jobID}-text`).text() | |||
| if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'].includes(status_text)){ | |||
| return | |||
| } | |||
| $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | |||
| const jobID = data.JobID | |||
| const status = data.JobStatus | |||
| @@ -329,7 +312,6 @@ | |||
| } | |||
| } | |||
| function stopVersion(version_name,jobID){ | |||
| const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'/stop_version' | |||
| $.post(url,{version_name:version_name},(data)=>{ | |||
| if(data.StatusOK===0){ | |||
| @@ -450,7 +450,6 @@ td, th { | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| console.log({{.version_list_task}}) | |||
| $('.menu .item').tab() | |||
| $(document).ready(function(){ | |||
| @@ -495,14 +494,19 @@ td, th { | |||
| } | |||
| function loadJobStatus() { | |||
| $(".ui.accordion.border-according").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const versionname = job.dataset.version | |||
| if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| return | |||
| // ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'] | |||
| // if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| // || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| // || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| // return | |||
| // } | |||
| let status = $(`#${versionname}-status-span`).text() | |||
| if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'].includes(status)){ | |||
| return | |||
| } | |||
| let stopArray=["KILLED","FAILED","START_FAILED","KILLING","COMPLETED"] | |||
| $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | |||
| @@ -663,7 +667,12 @@ td, th { | |||
| html += "</span>" | |||
| html += "</td>" | |||
| html += "<td class='message seven wide'>" | |||
| html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||
| if(data.Dirs[i].IsDir){ | |||
| html += "<span class='truncate has-emoji'></span>" | |||
| }else{ | |||
| html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||
| } | |||
| html += "</td>" | |||
| html += "<td class='text right age three wide'>" | |||
| @@ -141,7 +141,6 @@ | |||
| <script> | |||
| let repolink = {{.RepoLink}} | |||
| let repoId = {{$repository}} | |||
| let url_href = window.location.pathname.split('show_model')[0] + 'create_model' | |||
| const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; | |||
| $('input[name="_csrf"]').val(csrf) | |||
| @@ -110,7 +110,36 @@ | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">模型描述</td> | |||
| <td class="ti-text-form-content" ><div id="edit-td" style="display:flex"><span id="Description" title="" class="iword-elipsis"></span><i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div></td> | |||
| <td class="ti-text-form-content" > | |||
| <div id="edit-td" style="display:flex"> | |||
| <span id="Description" title="" class="iword-elipsis"></span> | |||
| <i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">代码版本</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="CodeBranch" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">启动文件</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="BootFile" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">训练数据集</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="DatasetName" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">运行参数</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="Parameters" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">规格</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="FlavorName" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">计算节点</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="WorkServerNumber" title=""></span></td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| @@ -155,6 +184,7 @@ function changeInfo(version){ | |||
| let returnArray = [] | |||
| returnArray = transObj(versionData) | |||
| let [initObj,initModelAcc,id] = returnArray | |||
| editorCancel('','') | |||
| renderInfo(initObj,initModelAcc,id) | |||
| }) | |||
| } | |||
| @@ -175,8 +205,15 @@ function loadInfo(){ | |||
| }) | |||
| } | |||
| function transObj(data){ | |||
| let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy} = data[0] | |||
| let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy,CodeBranch,CodeCommitID,TrainTaskInfo} = data[0] | |||
| let modelAcc = JSON.parse(Accuracy) | |||
| TrainTaskInfo = JSON.parse(TrainTaskInfo) | |||
| // Parameters = JSON.parse(Parameters) | |||
| console.log("TrainTaskInfo",TrainTaskInfo) | |||
| let {Parameters} = TrainTaskInfo | |||
| Parameters = JSON.parse(Parameters) | |||
| Parameters = Parameters.parameter.length === 0 ? '--':Parameters.parameter | |||
| console.log(Parameters) | |||
| let size = tranSize(Size) | |||
| let time = transTime(CreatedUnix) | |||
| let initObj = { | |||
| @@ -186,6 +223,14 @@ function transObj(data){ | |||
| Size:size, | |||
| CreateTime:time, | |||
| Description:Description || '--', | |||
| CodeBranch:CodeBranch || '--', | |||
| CodeCommitID:CodeCommitID || '--', | |||
| BootFile:TrainTaskInfo.BootFile || '--', | |||
| DatasetName:TrainTaskInfo.DatasetName || '--', | |||
| Parameters:TrainTaskInfo.Parameters || '--', | |||
| FlavorName:TrainTaskInfo.FlavorName || '--', | |||
| WorkServerNumber:TrainTaskInfo.WorkServerNumber || '--', | |||
| Parameters:Parameters | |||
| } | |||
| let initModelAcc = { | |||
| Accuracy: modelAcc.Accuracy || '--', | |||
| @@ -221,15 +266,16 @@ function tranSize(value){ | |||
| function editorFn(context){ | |||
| let id= context.dataset.id | |||
| let text = context.dataset.desc | |||
| console.log(id,text) | |||
| $('#edit-td').replaceWith("<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;' id='edit-text'>"+text+"</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure(\"" + text + "\",\"" + id + "\")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel(\"" + text + "\",\"" + id + "\")'></i></div>"); | |||
| let textValue = text.replace(/enter;/g,'\r\n') | |||
| $('#edit-td').replaceWith(`<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;white-space: nowrap;' id='edit-text'>${textValue}</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure("${text}","${id}")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel("${text}","${id}")'></i></div>`); | |||
| } | |||
| function editorCancel(text,id){ | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${text}" class="iword-elipsis">${text}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| let objkey = text.replace(/enter;/g,'\r\n') | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${objkey}" class="iword-elipsis">${objkey}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| } | |||
| function editorSure(text,id){ | |||
| let description=$('#textarea-value').val() | |||
| let sourcetext = $('#textarea-value').val().replace(/\n/g,'enter;') | |||
| let data = { | |||
| ID:id, | |||
| Description:description | |||
| @@ -239,16 +285,18 @@ function editorSure(text,id){ | |||
| type:'PUT', | |||
| data:data | |||
| }).done((res)=>{ | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${description}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${sourcetext}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| }) | |||
| } | |||
| function renderInfo(obj,accObj,id){ | |||
| for(let key in obj){ | |||
| if(key==="Description"){ | |||
| let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;') | |||
| $(`#${key}`).text(obj[key]) | |||
| $(`#${key}`).attr("title",obj[key]) | |||
| $('#edit-pencil').attr("data-id",id) | |||
| $('#edit-pencil').attr("data-desc",obj[key]) | |||
| $('#edit-pencil').attr("data-desc",descriptionText) | |||
| } | |||
| else if(key==="Label"){ | |||
| $('#Label').empty() | |||
| @@ -263,6 +311,29 @@ function renderInfo(obj,accObj,id){ | |||
| } | |||
| $('#Label').append(html) | |||
| } | |||
| } | |||
| else if(key==="CodeCommitID"){ | |||
| let codeCommit = obj[key].slice(0,10) | |||
| let html = `<a style="margin-left:1rem" class="ui label" title="${codeCommit}">${codeCommit}</a>` | |||
| $('#CodeBranch').append(html) | |||
| } | |||
| else if(key==="Parameters"){ | |||
| console.log("obj[key",obj[key]) | |||
| if(obj[key]==='--'){ | |||
| $(`#${key}`).text(obj[key]) | |||
| }else{ | |||
| const parameterArray = obj[key].map(element => { | |||
| let labelValue = `${element.label}=${element.value}` | |||
| return labelValue | |||
| }); | |||
| const parameter = parameterArray.join('; ') | |||
| console.log(parameter) | |||
| $(`#${key}`).text(parameter) | |||
| $(`#${key}`).attr("title",parameter) | |||
| } | |||
| } | |||
| else{ | |||
| $(`#${key}`).text(obj[key]) | |||
| @@ -45,6 +45,8 @@ export default { | |||
| data() { | |||
| return { | |||
| url:'', | |||
| url_infor:'', | |||
| href_:'', | |||
| contributors_list:[], | |||
| contributors_list_page:[], | |||
| currentPage:1, | |||
| @@ -56,7 +58,7 @@ export default { | |||
| methods: { | |||
| getContributorsList(){ | |||
| this.$axios.get(this.url+'/list').then((res)=>{ | |||
| this.$axios.get(this.url+'/list?'+this.url_infor).then((res)=>{ | |||
| this.contributors_list = res.data.contributor_info | |||
| this.totalNum = this.contributors_list.length | |||
| this.contributors_list_page = this.contributors_list.slice(0,this.pageSize) | |||
| @@ -78,6 +80,10 @@ created(){ | |||
| this.url = url; | |||
| let strIndex = this.url.indexOf("contributors") | |||
| this.url_code = this.url.substr(0,strIndex) | |||
| this.href_ = window.location.href; | |||
| let index = this.href_.indexOf("?") | |||
| this.url_infor = this.href_.substring(index+1,this.href_.length) | |||
| this.getContributorsList() | |||
| }, | |||
| @@ -263,6 +263,7 @@ export default { | |||
| let cName = $("input[name='Name']").val() | |||
| let version = $("input[name='Version']").val() | |||
| let data = $("#formId").serialize() | |||
| let url_href = version === '0.0.1' ? context.url_create_newModel : context.url_create_newVersion | |||
| $("#mask").css({"display":"block","z-index":"9999"}) | |||
| $.ajax({ | |||
| url:url_href, | |||
| @@ -292,7 +293,7 @@ export default { | |||
| if(!this.loadNodeMap.get(row.cName)){ | |||
| const parent = store.states.data | |||
| const index = parent.findIndex(child => child.ID == row.ID) | |||
| parent.splice(index, 1) | |||
| this.getModelList() | |||
| }else{ | |||
| let {tree,treeNode,resolve} = this.loadNodeMap.get(row.cName) | |||
| const keys = Object.keys(store.states.lazyTreeNodeMap); | |||
| @@ -406,6 +407,8 @@ export default { | |||
| this.getModelList() | |||
| this.url = location.href.split('show_model')[0] | |||
| this.submitId.addEventListener("click", this.submit) | |||
| this.url_create_newVersion = this.url + 'create_model' | |||
| this.url_create_newModel = this.url + 'create_new_model' | |||
| }, | |||
| beforeDestroy() { // 实例销毁之前对点击事件进行解绑 | |||
| @@ -517,4 +520,4 @@ export default { | |||
| opacity: .45 !important; | |||
| } | |||
| </style> | |||
| </style> | |||
| @@ -1,6 +1,6 @@ | |||
| @import "~highlight.js/styles/github.css"; | |||
| @import "./vendor/gitGraph.css"; | |||
| // @import "~/remixicon/fonts/remixicon.css"; | |||
| @import "_svg"; | |||
| @import "_tribute"; | |||
| @import "_base"; | |||