@@ -88,6 +88,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:"-"` | |||
@@ -102,7 +105,7 @@ type Cloudbrain struct { | |||
IsLatestVersion string //是否是最新版本,1是,0否 | |||
CommitID string //提交的仓库代码id | |||
PreVersionName string //父版本名称 | |||
ComputeResource string //计算资源,例如npu | |||
ComputeResource string `xorm:"-"` //计算资源,例如npu | |||
EngineID int64 //引擎id | |||
TrainUrl string //输出的obs路径 | |||
@@ -353,7 +353,7 @@ func GetMilestonesByRepoID(repoID int64, state api.StateType, listOptions ListOp | |||
} | |||
miles := make([]*Milestone, 0, listOptions.PageSize) | |||
return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) | |||
return miles, sess.Desc("id").Find(&miles) | |||
} | |||
// GetMilestones returns a list of milestones of given repository and status. | |||
@@ -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,142 @@ 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, | |||
}) | |||
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 | |||
} | |||
@@ -277,7 +277,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
DatasetName: attach.Name, | |||
CommitID: req.CommitID, | |||
IsLatestVersion: req.IsLatestVersion, | |||
ComputeResource: NPUResource, | |||
//ComputeResource: NPUResource, | |||
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 | |||
@@ -12,6 +12,7 @@ import ( | |||
"time" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/minio/minio-go" | |||
) | |||
@@ -153,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 | |||
} |
@@ -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 | |||
@@ -1127,6 +1131,7 @@ issues.filter_label_exclude = `Use <code>alt</code> + <code>click/enter</code> t | |||
issues.filter_label_no_select = All labels | |||
issues.filter_milestone = Milestone | |||
issues.filter_milestone_no_select = All milestones | |||
issues.filter_milestone_no_add = Not add milestones | |||
issues.filter_assignee = Assignee | |||
issues.filter_assginee_no_select = All assignees | |||
issues.filter_type = Type | |||
@@ -784,8 +784,10 @@ cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 | |||
model_manager = 模型 | |||
model_noright=无权限操作 | |||
model_rename=模型名称重复,请修改模型名称 | |||
debug=调试 | |||
debug_again=再次调试 | |||
stop=停止 | |||
delete=删除 | |||
model_download=模型下载 | |||
@@ -1140,6 +1142,7 @@ issues.filter_label_exclude=`使用 <code>alt</code> + <code>鼠标左键 / 回 | |||
issues.filter_label_no_select=所有标签 | |||
issues.filter_milestone=里程碑筛选 | |||
issues.filter_milestone_no_select=所有里程碑 | |||
issues.filter_milestone_no_add=未添加里程碑 | |||
issues.filter_assignee=指派人筛选 | |||
issues.filter_assginee_no_select=所有指派成员 | |||
issues.filter_type=类型筛选 | |||
@@ -1,8 +1,6 @@ | |||
package routers | |||
import ( | |||
"net/http" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
@@ -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,9 +236,10 @@ 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) | |||
@@ -247,6 +248,72 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
} | |||
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 | |||
} | |||
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) { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
@@ -351,32 +418,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 +511,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) | |||
@@ -562,7 +650,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 { | |||
@@ -572,10 +660,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") | |||
@@ -357,7 +357,8 @@ func Issues(ctx *context.Context) { | |||
var err error | |||
// Get milestones. | |||
ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateAll, models.ListOptions{}) | |||
ctx.Data["OpenMilestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateOpen, models.ListOptions{}) | |||
ctx.Data["ClosedMilestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateClosed, models.ListOptions{}) | |||
if err != nil { | |||
ctx.ServerError("GetAllRepoMilestones", err) | |||
return | |||
@@ -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") | |||
@@ -73,21 +74,19 @@ func DebugJobIndex(ctx *context.Context) { | |||
} | |||
for i, task := range ciTasks { | |||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
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) | |||
} else if task.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||
ciTasks[i].Cloudbrain.ComputeResource = modelarts.NPUResource | |||
} | |||
} | |||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
pager.SetDefaultParams(ctx) | |||
//pager.SetDefaultParams(ctx) | |||
pager.AddParam(ctx, "debugListType", "ListType") | |||
ctx.Data["Page"] = pager | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.Data["Tasks"] = ciTasks | |||
@@ -232,38 +231,91 @@ 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 | |||
} | |||
} 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 | |||
} | |||
task.Status = res.CurrentStatus | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
ctx.ServerError("UpdateJob failed", err) | |||
return | |||
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 +326,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 | |||
@@ -323,6 +375,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 = modelarts.NPUResource | |||
} | |||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
@@ -968,6 +968,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
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", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainRestart) | |||
m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) | |||
m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | |||
m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDownloadModel) | |||
@@ -977,6 +978,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) | |||
@@ -1002,7 +1004,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Group("/:jobid", func() { | |||
m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) | |||
m.Get("/debug", reqRepoCloudBrainWriter, repo.NotebookDebug) | |||
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookStop) | |||
m.Post("/:action", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookManage) | |||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel) | |||
}) | |||
m.Get("/create", reqRepoCloudBrainWriter, repo.NotebookNew) | |||
@@ -202,14 +202,20 @@ | |||
<div class="rect5"></div> | |||
</div> | |||
</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' | |||
@@ -499,7 +526,68 @@ | |||
.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('blue').addClass('disabled').text("再次调试").css("margin","0") | |||
$('#model-image-'+JobID).removeClass('blue').addClass('disabled') | |||
$('#stop-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
} | |||
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 +596,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 +610,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 +641,7 @@ | |||
}); | |||
}; | |||
$(document).ready(function(){ | |||
dropdownValue = dropdownValue==="CPU%2FGPU"? 'CPU/GPU' : dropdownValue | |||
$('.default.text').text(dropdownValue) | |||
$('.ui.dropdown') | |||
.dropdown({ | |||
@@ -564,6 +652,12 @@ | |||
location.href = `${url}/debugjob?debugListType=${value}` | |||
} | |||
}) | |||
$('.message .close') | |||
.on('click', function() { | |||
$(this) | |||
.closest('.message') | |||
.transition('fade') | |||
}) | |||
}) | |||
@@ -601,7 +695,6 @@ | |||
// 显示弹窗,弹出相应的信息 | |||
function showmask() { | |||
var image_tag = !$('#image_tag').val() | |||
console.log("image_tag",image_tag) | |||
if(image_tag){ | |||
return | |||
} | |||
@@ -149,6 +149,12 @@ | |||
{{.i18n.Tr "repo.model_manager"}} | |||
</a> | |||
{{end}} | |||
{{if .Permission.CanRead $.UnitTypeModelManage}} | |||
<a class="{{if .isModelManage}}active{{end}} item" href="{{.RepoLink}}/modelmanage/show_model"> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M3.741 1.408l18.462 10.154a.5.5 0 0 1 0 .876L3.741 22.592A.5.5 0 0 1 3 22.154V1.846a.5.5 0 0 1 .741-.438zM5 13v6.617L18.85 12 5 4.383V11h5v2H5z"/></svg> | |||
{{.i18n.Tr "repo.model_manager"}} | |||
</a> | |||
{{end}} | |||
{{if .Permission.CanRead $.UnitTypeCloudBrain}} | |||
<a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
<span> | |||
@@ -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"> | |||
@@ -1,3 +1,11 @@ | |||
<style> | |||
.repository .filter.menu.labels .svg{ | |||
margin-right: 2px !important; | |||
} | |||
.ovfl{ | |||
overflow-y:hidden !important; | |||
} | |||
</style> | |||
{{template "base/head" .}} | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
@@ -57,16 +65,41 @@ | |||
</div> | |||
<!-- Milestone --> | |||
<div class="ui {{if not .Milestones}}disabled{{end}} dropdown jump item"> | |||
<div class="ui {{if and (not .OpenMilestones) (not .ClosedMilestones)}}disabled{{end}} dropdown jump item"> | |||
<span class="text"> | |||
{{.i18n.Tr "repo.issues.filter_milestone"}} | |||
<i class="dropdown icon"></i> | |||
</span> | |||
<div class="menu"> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}">{{.i18n.Tr "repo.issues.filter_milestone_no_select"}}</a> | |||
{{range .Milestones}} | |||
<a class="{{if eq $.MilestoneID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.ID}}&assignee={{$.AssigneeID}}">{{.Name}}</a> | |||
{{end}} | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone=-1&assignee={{$.AssigneeID}}">{{.i18n.Tr "repo.issues.filter_milestone_no_add"}}</a> | |||
{{if .OpenMilestones}} | |||
<div class="divider" ></div> | |||
<div class="header ovfl" > | |||
{{svg "octicon-milestone" 12 }} | |||
{{.i18n.Tr "repo.issues.new.open_milestone"}} | |||
</div> | |||
{{range .OpenMilestones}} | |||
<a class="{{if eq $.MilestoneID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.ID}}&assignee={{$.AssigneeID}}"> | |||
{{.Name}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
{{if .ClosedMilestones}} | |||
<div class="divider"></div> | |||
<div class="header ovfl" > | |||
{{svg "octicon-milestone" 12}} | |||
{{.i18n.Tr "repo.issues.new.closed_milestone"}} | |||
</div> | |||
{{range .ClosedMilestones}} | |||
<a class="{{if eq $.MilestoneID .ID}}active selected{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.ID}}&assignee={{$.AssigneeID}}"> | |||
{{.Name}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
</div> | |||
@@ -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() | |||
}, | |||
@@ -52,7 +52,7 @@ export default { | |||
previewTemplate += | |||
' <span data-dz-name data-dz-thumbnail></span>'; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-size" data-dz-size></div>\n '; | |||
previewTemplate += ' <div class="dz-size" data-dz-size style="white-space: nowrap"></div>\n '; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-progress ui active progress">'; | |||
previewTemplate += | |||
@@ -53,7 +53,7 @@ export default { | |||
previewTemplate += | |||
' <span data-dz-name data-dz-thumbnail></span>'; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-size" data-dz-size></div>\n '; | |||
previewTemplate += ' <div class="dz-size" data-dz-size style="white-space: nowrap"></div>\n '; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-progress ui active progress">'; | |||
previewTemplate += | |||