@@ -18,7 +18,7 @@ import ( | |||
"code.gitea.io/gitea/modules/timeutil" | |||
) | |||
//todo 暂时保留之前各种云脑属性的定义 | |||
// todo 暂时保留之前各种云脑属性的定义 | |||
type CreateReq struct { | |||
JobType models.JobType `json:"job_type" binding:"Required"` | |||
DisplayJobName string `json:"display_job_name" binding:"Required"` | |||
@@ -44,6 +44,7 @@ type CreateReq struct { | |||
PoolId string `json:"pool_id"` | |||
IsContinueRequest bool `json:"is_continue"` | |||
SourceCloudbrainId int64 `json:"source_cloudbrain_id"` | |||
AppName string `json:"app_name"` | |||
ParamArray models.Parameters | |||
ComputeSource *models.ComputeSource | |||
ReqCommitID string | |||
@@ -139,6 +140,7 @@ type AITaskDetailInfo struct { | |||
EngineName string `json:"engine_name"` | |||
FailedReason string `json:"failed_reason"` | |||
UserId int64 `json:"-"` | |||
AppName string `json:"app_name"` | |||
} | |||
func (a *AITaskDetailInfo) Tr(language string) { | |||
@@ -207,6 +209,7 @@ type AITaskBriefInfo struct { | |||
AICenter string `json:"ai_center"` | |||
IsFileNotebook bool `json:"is_file_notebook"` | |||
IsFineTuneTask bool `json:"is_fine_tune_task"` | |||
APPName string `json:"app_name"` | |||
} | |||
func (a *AITaskBriefInfo) Tr(language string) { | |||
@@ -243,6 +246,7 @@ func ConvertCloudbrainToAITaskBriefInfo(task *models.Cloudbrain) *AITaskBriefInf | |||
AICenter: task.AiCenter, | |||
IsFileNotebook: task.IsFileNoteBookTask(), | |||
IsFineTuneTask: task.FineTune, | |||
APPName: task.AppName, | |||
} | |||
} | |||
@@ -73,6 +73,7 @@ const ( | |||
ActionCreateGrampusMLUTrainTask //44 | |||
ActionCreateGrampusGPUOnlineInferTask //45 | |||
ActionCreateGrampusDCUDebugTask //46 | |||
ActionCreateSuperComputeTask //47 | |||
) | |||
// Action represents user operation type and other information to | |||
@@ -425,7 +426,8 @@ func (a *Action) IsCloudbrainAction() bool { | |||
ActionCreateGrampusGCUTrainTask, | |||
ActionCreateGrampusGCUDebugTask, | |||
ActionCreateGrampusDCUDebugTask, | |||
ActionCreateGrampusMLUDebugTask: | |||
ActionCreateGrampusMLUDebugTask, | |||
ActionCreateSuperComputeTask: | |||
return true | |||
} | |||
return false | |||
@@ -48,6 +48,7 @@ const ( | |||
NPUResource = "NPU" | |||
GPUResource = "CPU/GPU" | |||
GCUResource = "GCU" | |||
CPUResource = "CPU" | |||
AllResource = "all" | |||
//notebook storage category | |||
@@ -78,6 +79,7 @@ const ( | |||
JobTypeTrain JobType = "TRAIN" | |||
JobTypeInference JobType = "INFERENCE" | |||
JobTypeOnlineInference JobType = "ONLINEINFERENCE" | |||
JobTypeSuperCompute JobType = "SUPERCOMPUTE" | |||
//notebook | |||
ModelArtsCreateQueue ModelArtsJobStatus = "CREATE_QUEUING" //免费资源创建排队中 | |||
@@ -158,12 +160,14 @@ const ( | |||
GCU = "GCU" | |||
MLU = "MLU" | |||
DCU = "DCU" | |||
CPU = "CPU" | |||
ProcessorTypeNPU = "npu.huawei.com/NPU" | |||
ProcessorTypeGPU = "nvidia.com/gpu" | |||
ProcessorTypeGCU = "enflame-tech.com/gcu" | |||
ProcessorTypeMLU = "cambricon.com/mlu" | |||
ProcessorTypeDCU = "ac.sugon.com/dcu" | |||
ProcessorTypeCPU = "hpc/cpu" | |||
) | |||
const CloudbrainTwoDefaultVersion = "/V0001" | |||
@@ -212,6 +216,7 @@ var ComputeSourceMap = map[string]*ComputeSource{ | |||
GCU: {Name: GCU, FullName: ProcessorTypeGCU}, | |||
MLU: {Name: MLU, FullName: ProcessorTypeMLU}, | |||
DCU: {Name: DCU, FullName: ProcessorTypeDCU}, | |||
CPU: {Name: CPU, FullName: ProcessorTypeCPU}, | |||
} | |||
const ( | |||
@@ -298,6 +303,7 @@ type Cloudbrain struct { | |||
FineTuneCategory int | |||
Spec *Specification `xorm:"-"` | |||
Config *CloudbrainConfig `xorm:"-"` | |||
AppName string //超算任务的应用类型 | |||
} | |||
type CloudbrainShow struct { | |||
@@ -397,7 +403,7 @@ func (task *Cloudbrain) GetAiCenter() string { | |||
} | |||
//是否为在线notebook文件任务 | |||
// 是否为在线notebook文件任务 | |||
func (task *Cloudbrain) IsFileNoteBookTask() bool { | |||
return task.JobType == string(JobTypeDebug) && task.BootFile != "" | |||
} | |||
@@ -481,8 +487,8 @@ func (task *Cloudbrain) NeedActiveStop() bool { | |||
return task.IsCreating() || (task.IsPreparing() && int64(task.CreatedUnix) < time.Now().Add(-1*setting.PREPARING_MAX_WAIT_DURATION).Unix()) | |||
} | |||
//是否允许创建多版本 | |||
//目前只有启智NPU可以 | |||
// 是否允许创建多版本 | |||
// 目前只有启智NPU可以 | |||
func (task *Cloudbrain) IsAllowedToCreateMultipleVersions() bool { | |||
if task.Type == TypeCloudBrainTwo && task.ComputeResource == NPUResource && task.JobType != string(JobTypeDebug) { | |||
return true | |||
@@ -3241,7 +3247,7 @@ func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetIn | |||
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID | |||
} else if grampusType[0] == NPU { | |||
dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/" | |||
} else if grampusType[0] == GCU || grampusType[0] == MLU || grampusType[0] == DCU { | |||
} else { | |||
if attach.Type == TypeCloudBrainOne { | |||
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID | |||
} else { | |||
@@ -13,19 +13,20 @@ const ( | |||
type TaskType string | |||
const ( | |||
TaskCreatePublicRepo TaskType = "CreatePublicRepo" | |||
TaskCreateIssue TaskType = "CreateIssue" | |||
TaskCreatePullRequest TaskType = "CreatePullRequest" | |||
TaskCommentIssue TaskType = "CommentIssue" | |||
TaskUploadAttachment TaskType = "UploadAttachment" | |||
TaskCreateNewModelTask TaskType = "CreateNewModelTask" | |||
TaskBindWechat TaskType = "BindWechat" | |||
TaskCreateCloudbrainTask TaskType = "CreateCloudbrainTask" | |||
TaskDatasetRecommended TaskType = "DatasetRecommended" | |||
TaskCreateImage TaskType = "CreateImage" | |||
TaskImageRecommend TaskType = "ImageRecommend" | |||
TaskChangeUserAvatar TaskType = "ChangeUserAvatar" | |||
TaskPushCommits TaskType = "PushCommits" | |||
TaskCreatePublicRepo TaskType = "CreatePublicRepo" | |||
TaskCreateIssue TaskType = "CreateIssue" | |||
TaskCreatePullRequest TaskType = "CreatePullRequest" | |||
TaskCommentIssue TaskType = "CommentIssue" | |||
TaskUploadAttachment TaskType = "UploadAttachment" | |||
TaskCreateNewModelTask TaskType = "CreateNewModelTask" | |||
TaskBindWechat TaskType = "BindWechat" | |||
TaskCreateCloudbrainTask TaskType = "CreateCloudbrainTask" | |||
TaskCreateSuperComputeTask TaskType = "CreateSuperComputeTask" | |||
TaskDatasetRecommended TaskType = "DatasetRecommended" | |||
TaskCreateImage TaskType = "CreateImage" | |||
TaskImageRecommend TaskType = "ImageRecommend" | |||
TaskChangeUserAvatar TaskType = "ChangeUserAvatar" | |||
TaskPushCommits TaskType = "PushCommits" | |||
) | |||
func GetTaskTypeFromAction(a ActionType) TaskType { | |||
@@ -46,6 +47,8 @@ func GetTaskTypeFromAction(a ActionType) TaskType { | |||
ActionCreateGrampusGPUOnlineInferTask, | |||
ActionCreateGrampusGPUTrainTask: | |||
return TaskCreateCloudbrainTask | |||
case ActionCreateSuperComputeTask: | |||
return TaskCreateSuperComputeTask | |||
case ActionCreateRepo: | |||
return TaskCreatePublicRepo | |||
case ActionCreatePullRequest: | |||
@@ -641,6 +641,7 @@ var ( | |||
UsageRateBeginTime string | |||
GPUImageCommonName string | |||
MultiNode string | |||
MMLSparkMaxTime int64 | |||
}{} | |||
ClearStrategy = struct { | |||
@@ -1894,6 +1895,8 @@ func GetGrampusConfig() { | |||
} | |||
Grampus.MultiNode = sec.Key("MULTI_NODE").MustString("") | |||
Grampus.MMLSparkMaxTime = sec.Key("MMLSparkMaxTime").MustInt64(8 * 3600) | |||
} | |||
func SetRadarMapConfig() { | |||
@@ -1096,6 +1096,7 @@ online_debug = Start | |||
debug_again=Restart | |||
stop=Stop | |||
delete=Delete | |||
start_use=Start use | |||
more=More | |||
gpu_type_all=All | |||
model_download=Model Download | |||
@@ -1128,6 +1129,8 @@ export_result_to_dataset = Export the results to a dataset | |||
loader_result_file = Loading results file... | |||
cloudbrain=Cloudbrain | |||
superCompute=HPC | |||
superComputeTask=HPC Task | |||
cloudbrain.task = Cloudbrain Task | |||
cloudbrain.search = Seach Task Name | |||
cloudbrain.new=New cloudbrain | |||
@@ -3182,6 +3185,7 @@ task_c2ent_mludebugjob=`created MLU type debugging task <a href="%s/grampus/trai | |||
task_c2ent_mlutrainjob=`created MLU type train task <a href="%s/grampus/train-job/%s">%s</a>` | |||
task_c2net_dcudebugjob=`created DCU type debugging task <a href="%s/grampus/notebook/%s">%s</a>` | |||
task_c2ent_onlineinferjob=`created GPU type online inference task <a href="%s/grampus/onlineinfer/%s">%s</a>` | |||
task_c2net_cpusupercomputejob=`created CPU type HPC task <a href="%s/supercompute/job/%s">%s</a>` | |||
task_nputrainjob=`created NPU training task <a href="%s/modelarts/train-job/%s">%s</a>` | |||
task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>` | |||
task_benchmark=`created profiling task <a href="%s/cloudbrain/benchmark/%s">%s</a>` | |||
@@ -3352,6 +3356,7 @@ TRAIN = TRAIN | |||
INFERENCE = INFERENCE | |||
BENCHMARK = BENCHMARK | |||
ONLINEINFERENCE = ONLINEINFERENCE | |||
SUPERCOMPUTE = HPC | |||
brain_area = Brain Area | |||
Delete_failed=Fail to delete the job, please try again later. | |||
@@ -1095,6 +1095,7 @@ online_debug = 在线推理 | |||
debug_again=再次调试 | |||
stop=停止 | |||
delete=删除 | |||
start_use=开始使用 | |||
more=更多 | |||
gpu_type_all=全部 | |||
model_download=结果下载 | |||
@@ -1127,6 +1128,8 @@ export_result_to_dataset = 导出结果至数据集 | |||
loader_result_file = 正在加载结果文件中... | |||
cloudbrain=云脑 | |||
superCompute=超算 | |||
superComputeTask=超算任务 | |||
cloudbrain.task = 云脑任务 | |||
cloudbrain.search = 搜索任务名称 | |||
cloudbrain.new=新建任务 | |||
@@ -3200,6 +3203,7 @@ task_c2ent_mludebugjob=`创建了MLU类型调试任务 <a href="%s/grampus/noteb | |||
task_c2ent_mlutrainjob=`创建了MLU类型训练任务 <a href="%s/grampus/train-job/%s">%s</a>` | |||
task_c2net_dcudebugjob=`创建了DCU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>` | |||
task_c2ent_onlineinferjob=`创建了GPU类型在线推理任务 <a href="%s/grampus/onlineinfer/%s">%s</a>` | |||
task_c2net_cpusupercomputejob=`创建了CPU类型超算任务 <a href="%s/supercompute/job/%s">%s</a>` | |||
task_nputrainjob=`创建了NPU类型训练任务 <a href="%s/modelarts/train-job/%s">%s</a>` | |||
task_inferencejob=`创建了推理任务 <a href="%s/modelarts/inference-job/%s">%s</a>` | |||
task_benchmark=`创建了评测任务 <a href="%s/cloudbrain/benchmark/%s">%s</a>` | |||
@@ -3373,6 +3377,7 @@ TRAIN = 训练任务 | |||
INFERENCE = 推理任务 | |||
BENCHMARK = 评测任务 | |||
ONLINEINFERENCE = 在线推理 | |||
SUPERCOMPUTE = 超算任务 | |||
brain_area = 脑区 | |||
Delete_failed=任务删除失败,请稍后再试。 | |||
@@ -253,7 +253,8 @@ document.onreadystatechange = function () { | |||
html += " <span style=\"color: rgba(0,0,0,0.3)\">" + record.RefName + "</span>" | |||
} | |||
} | |||
else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40" || record.OpType == "41" || record.OpType == "43"|| record.OpType == "44"|| record.OpType == "45"|| record.OpType == "46"){ | |||
else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40" || record.OpType == "41" | |||
|| record.OpType == "43"|| record.OpType == "44"|| record.OpType == "45"|| record.OpType == "46"|| record.OpType == "47"){ | |||
html += recordPrefix + actionName; | |||
const taskLink = getTaskLink(record); | |||
if (taskLink) { | |||
@@ -331,6 +332,8 @@ function getTaskLink(record){ | |||
} else { | |||
re = ''; | |||
} | |||
} else if(record.OpType == 47){ | |||
re = re + "/supercompute/job/" + record.Cloudbrain.ID; | |||
} else if(record.OpType == 45){ | |||
re = re + "/grampus/onlineinfer/" + record.Content; | |||
} | |||
@@ -498,6 +501,7 @@ var actionNameZH={ | |||
"44":"创建了MLU类型训练任务", | |||
"45":"创建了GPU类型在线推理任务", | |||
"46":"创建了DCU类型调试任务", | |||
"47":"创建了CPU类型超算任务", | |||
}; | |||
var actionNameEN={ | |||
@@ -537,6 +541,7 @@ var actionNameEN={ | |||
"44":" created MLU type training task ", | |||
"45":" created GPU type online inference task ", | |||
"46":" created DCU type debugging task ", | |||
"47":" created CPU type super compute task ", | |||
}; | |||
var repoAndOrgZH={ | |||
@@ -2039,6 +2039,7 @@ func SyncCloudbrainStatus() { | |||
if task.Duration >= setting.MaxDuration && task.JobType == string(models.JobTypeDebug) { | |||
ai_task.StopCloudbrain(task) | |||
} | |||
continue | |||
} | |||
if task.Type == models.TypeCloudBrainOne { | |||
@@ -2065,7 +2066,7 @@ func SyncCloudbrainStatus() { | |||
log.Error("task.JobType(%s) is error:%s", task.DisplayJobName, task.JobType) | |||
} | |||
} else if task.Type == models.TypeC2Net { | |||
if task.JobType == string(models.JobTypeDebug) { | |||
if task.JobType == string(models.JobTypeDebug) || task.JobType == string(models.JobTypeSuperCompute) { | |||
cloudbrainTask.SyncGrampusNotebookStatus(task) | |||
} else { | |||
result, err := grampus.GetJob(task.JobID) | |||
@@ -2110,7 +2111,7 @@ func SyncCloudbrainStatus() { | |||
log.Error("task.Type(%s) is error:%d", task.JobName, task.Type) | |||
} | |||
if task.Status != string(models.JobWaiting) { | |||
if task.Duration >= setting.MaxDuration && task.JobType == string(models.JobTypeDebug) { | |||
if (task.Duration >= setting.MaxDuration && task.JobType == string(models.JobTypeDebug)) || (task.Duration >= setting.Grampus.MMLSparkMaxTime && task.JobType == string(models.JobTypeSuperCompute)) { | |||
log.Info("begin to stop job(%s), because of the duration", task.DisplayJobName) | |||
err = cloudbrainTask.StopDebugJob(task) | |||
if err != nil { | |||
@@ -811,6 +811,7 @@ func NotebookDel(ctx *context.Context) { | |||
func TrainJobIndex(ctx *context.Context) { | |||
MustEnableModelArts(ctx) | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.HTML(200, tplModelArtsTrainJobIndex) | |||
/* | |||
repo := ctx.Repo.Repository | |||
@@ -12,6 +12,8 @@ import ( | |||
"text/template" | |||
"time" | |||
"code.gitea.io/gitea/routers/super_compute" | |||
"code.gitea.io/gitea/routers/tech" | |||
"code.gitea.io/gitea/routers/badge" | |||
@@ -1303,6 +1305,12 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainInferencForm{}), context.PointAccount(), repo.CloudBrainInferenceJobCreate) | |||
}) | |||
}, context.RepoRef()) | |||
m.Group("/supercompute", func() { | |||
m.Get("", reqRepoCloudBrainReader, super_compute.GetAPPList) | |||
m.Get("/job", reqRepoCloudBrainReader, super_compute.GetJobList) | |||
m.Get("/job/create", reqRepoCloudBrainWriter, super_compute.CreateUI) | |||
m.Get("/job/:id", reqRepoCloudBrainReader, super_compute.GetDetailUI) | |||
}) | |||
m.Group("/grampus", func() { | |||
m.Group("/notebook", func() { | |||
m.Group("/:id", func() { | |||
@@ -0,0 +1,33 @@ | |||
package super_compute | |||
import ( | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/modules/context" | |||
) | |||
const ( | |||
tplAPPList base.TplName = "repo/supercompute/index" | |||
tplJobList base.TplName = "repo/supercompute/list" | |||
tplCreateUI base.TplName = "repo/supercompute/create" | |||
tplDetail base.TplName = "repo/supercompute/detail" | |||
) | |||
func GetAPPList(ctx *context.Context) { | |||
ctx.Data["PageIsSuperCompute"] = true | |||
ctx.HTML(200, tplAPPList) | |||
} | |||
func GetJobList(ctx *context.Context) { | |||
ctx.Data["PageIsSuperCompute"] = true | |||
ctx.HTML(200, tplJobList) | |||
} | |||
func CreateUI(ctx *context.Context) { | |||
ctx.Data["PageIsSuperCompute"] = true | |||
ctx.HTML(200, tplCreateUI) | |||
} | |||
func GetDetailUI(ctx *context.Context) { | |||
ctx.Data["PageIsSuperCompute"] = true | |||
ctx.HTML(200, tplDetail) | |||
} |
@@ -1,9 +1,10 @@ | |||
package task | |||
import ( | |||
"code.gitea.io/gitea/entity" | |||
"strings" | |||
"code.gitea.io/gitea/entity" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
@@ -107,8 +108,11 @@ func GetGrampusNoteBookConfig(opts entity.AITaskConfigKey) *entity.AITaskBaseCon | |||
config.ActionType = models.ActionCreateGrampusMLUDebugTask | |||
case models.DCU: | |||
config.ActionType = models.ActionCreateGrampusDCUDebugTask | |||
case models.CPU: | |||
config.ActionType = models.ActionCreateSuperComputeTask | |||
} | |||
config.IsActionUseJobId = false | |||
config.DatasetsLimitSizeGB = setting.DebugAttachSize | |||
config.DatasetsMaxNum = setting.MaxDatasetNum | |||
@@ -419,6 +419,7 @@ func (DefaultCreationHandler) InsertCloudbrainRecord4Async(ctx *context.Creation | |||
CreatedUnix: timeutil.TimeStampNow(), | |||
UpdatedUnix: timeutil.TimeStampNow(), | |||
GpuQueue: ctx.Spec.QueueCode, | |||
AppName: req.AppName, | |||
} | |||
err := models.CreateCloudbrain(c) | |||
@@ -0,0 +1,88 @@ | |||
package task | |||
import ( | |||
"strconv" | |||
"time" | |||
"code.gitea.io/gitea/entity" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/notification" | |||
"code.gitea.io/gitea/routers/response" | |||
"code.gitea.io/gitea/services/ai_task_service/context" | |||
) | |||
type SuperComputeTaskTemplate struct { | |||
GrampusNoteBookTaskTemplate | |||
} | |||
func init() { | |||
t := &SuperComputeTaskTemplate{ | |||
GrampusNoteBookTaskTemplate: GrampusNoteBookTaskTemplate{ | |||
DefaultAITaskTemplate: DefaultAITaskTemplate{ | |||
ClusterType: entity.C2Net, | |||
JobType: models.JobTypeSuperCompute, | |||
Config: GetGrampusNoteBookConfig, | |||
}, | |||
}, | |||
} | |||
RegisterTask(models.JobTypeSuperCompute, entity.C2Net, t) | |||
} | |||
func (g SuperComputeTaskTemplate) GetImages(computeSource models.ComputeSource) ([]entity.ClusterImage, bool, *response.BizError) { | |||
c := g.GetMyCluster() | |||
if c == nil { | |||
log.Error("Get cluster failed") | |||
return nil, false, response.SYSTEM_ERROR | |||
} | |||
l, f, err := c.GetNotebookImages(entity.GetImageReq{ | |||
ComputeSource: computeSource, | |||
JobType: models.JobTypeDebug, | |||
}) | |||
if err != nil { | |||
log.Error("GetImages err.computeSource=%s err =%v", computeSource.Name, err) | |||
return nil, false, response.NewBizError(err) | |||
} | |||
return l, f, nil | |||
} | |||
func (t SuperComputeTaskTemplate) Create(ctx *context.CreationContext) (*entity.CreateTaskRes, *response.BizError) { | |||
c := &CreateOperator{} | |||
err := c.Next(t.CheckParamFormat). | |||
Next(t.CheckMultiRequest). | |||
Next(t.CheckDisplayJobName). | |||
Next(t.LoadSpec). | |||
Next(t.CheckPointBalance). | |||
Next(t.CheckDatasets). | |||
Next(t.CheckBranchExists). | |||
Next(t.CheckModel). | |||
Next(t.InsertCloudbrainRecord4Async). | |||
AsyncNextWithErrFun(t.BuildContainerData, t.CallCreationAPI, t.AfterCallCreationAPI4Async, t.NotifyCreation, t.HandleErr4Async). | |||
Operate(ctx) | |||
if err != nil { | |||
log.Error("create GrampusNoteBookTask err.%v", err) | |||
return nil, err | |||
} | |||
return &entity.CreateTaskRes{ID: ctx.NewCloudbrain.ID}, nil | |||
} | |||
func (SuperComputeTaskTemplate) NotifyCreation(ctx *context.CreationContext) *response.BizError { | |||
req := ctx.Request | |||
var actionType = models.ActionCreateSuperComputeTask | |||
task, err := models.GetCloudbrainByCloudbrainID(ctx.NewCloudbrain.ID) | |||
if err != nil { | |||
log.Error("GetCloudbrainByJobID failed: %v", err.Error()) | |||
return response.NewBizError(err) | |||
} | |||
stringId := strconv.FormatInt(task.ID, 10) | |||
notification.NotifyOtherTask(ctx.User, ctx.Repository, stringId, req.DisplayJobName, actionType) | |||
return nil | |||
} | |||
func (g SuperComputeTaskTemplate) GetDisplayJobName(userName string) string { | |||
t := time.Now() | |||
millisecondStr := strconv.FormatInt((t.UnixNano()%1e6/1e3)%1000, 10) | |||
return "mmlspark-" + t.Format("20060102150405") + millisecondStr | |||
} |
@@ -1,6 +1,11 @@ | |||
package task | |||
import ( | |||
"errors" | |||
"time" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
"code.gitea.io/gitea/entity" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/convert" | |||
@@ -16,9 +21,7 @@ import ( | |||
"code.gitea.io/gitea/services/ai_task_service/container_builder" | |||
"code.gitea.io/gitea/services/ai_task_service/context" | |||
"code.gitea.io/gitea/services/cloudbrain/resource" | |||
"errors" | |||
"strconv" | |||
"time" | |||
) | |||
var taskMap = map[string]AITaskTemplate{} | |||
@@ -62,6 +65,7 @@ type AITaskTemplate interface { | |||
GetConfig(opts entity.AITaskConfigKey) *entity.AITaskBaseConfig | |||
GetNodeInfo(cloudbrainId int64) ([]entity.AITaskNodeInfo, *response.BizError) | |||
GetAllowedWorkerNum(userId int64, computeSource *models.ComputeSource) ([]int, *response.BizError) | |||
GetDisplayJobName(userName string) string | |||
} | |||
type GetConfigFunc func(entity.AITaskConfigKey) *entity.AITaskBaseConfig | |||
@@ -519,3 +523,6 @@ func isInNodes(nodes []int, num int) bool { | |||
return false | |||
} | |||
func (g DefaultAITaskTemplate) GetDisplayJobName(userName string) string { | |||
return cloudbrainService.GetDisplayJobName(userName) | |||
} |
@@ -7,7 +7,6 @@ import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/routers/response" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" | |||
"code.gitea.io/gitea/services/reward/point/account" | |||
) | |||
@@ -45,13 +44,16 @@ func GetAITaskCreationInfo(req entity.GetAITaskCreationInfoReq) (*entity.Creatio | |||
} | |||
//积分开关 | |||
result.PaySwitch = setting.CloudBrainPaySwitch | |||
//生成任务名称 | |||
result.DisplayJobName = cloudbrainService.GetDisplayJobName(req.User.Name) | |||
t, err := GetAITaskTemplate(req.JobType, req.ClusterType) | |||
if err != nil { | |||
log.Error("param error") | |||
return nil, err | |||
} | |||
//生成任务名称 | |||
result.DisplayJobName = t.GetDisplayJobName(req.User.Name) | |||
// 查询镜像列表 | |||
if images, canUseAll, err := t.GetImages(*req.ComputeSource); err == nil { | |||
result.Images = images | |||
@@ -133,6 +133,7 @@ func buildAITaskInfo(task *models.Cloudbrain, creator *models.User, config *enti | |||
CreatorName: creator.GetDisplayName(), | |||
EngineName: task.EngineName, | |||
UserId: task.UserID, | |||
AppName: task.AppName, | |||
}, nil | |||
} | |||
@@ -10,7 +10,7 @@ import ( | |||
"github.com/elliotchance/orderedmap" | |||
) | |||
var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40, 41, 42, 43, 44, 45, 46} | |||
var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40, 41, 42, 43, 44, 45, 46, 47} | |||
type ClientsManager struct { | |||
Clients *orderedmap.OrderedMap | |||
@@ -89,7 +89,7 @@ | |||
<div class="row"> | |||
<!-- 任务名 --> | |||
{{$JobID := '0'}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "SUPERCOMPUTE" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{$JobID = .Cloudbrain.ID}} | |||
{{else}} | |||
{{$JobID = .JobID}} | |||
@@ -103,6 +103,13 @@ | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "SUPERCOMPUTE"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/supercompute/job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" | |||
@@ -148,7 +155,7 @@ | |||
<div class="two wide column text center nowrap" | |||
style="width: 6% !important;"> | |||
<span class="job-status" id="{{$JobID}}" | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE" "SUPERCOMPUTE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}/modelarts/inference-job{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}"> | |||
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;" | |||
@@ -270,6 +277,19 @@ | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
{{if eq .JobType "SUPERCOMPUTE"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
<a id="ai-debug-infer-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "RUNNING"}} blue {{else}} disabled {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.start_use"}} | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
<!-- 停止任务 --> | |||
<div class="ui compact buttons"> | |||
@@ -284,7 +304,7 @@ | |||
</a> | |||
</form> | |||
{{else}} | |||
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{if eq .JobType "DEBUG" "SUPERCOMPUTE" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
@@ -329,7 +349,7 @@ | |||
</form> | |||
{{else}} | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}}/cloudbrain{{else if eq .JobType "DEBUG" "ONLINEINFERENCE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?isadminpage=true' | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}}/cloudbrain{{else if eq .JobType "DEBUG" "ONLINEINFERENCE" "SUPERCOMPUTE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?isadminpage=true' | |||
method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Cloudbrain.ID}}" style="display:none" name="id" /> | |||
@@ -38,6 +38,7 @@ | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=MODELSAFETY&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MODELSAFETY">MODELSAFETY</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4ECOSET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="SNN4ECOSET">SNN4ECOSET</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SIM2BRAIN_SNN&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="SIM2BRAIN_SNN">SIM2BRAIN_SNN</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SUPERCOMPUTE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="SUPERCOMPUTE">SUPERCOMPUTE</a> | |||
</div> | |||
</div> | |||
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;"> | |||
@@ -50,6 +51,7 @@ | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=GCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="GCU">GCU</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=MLU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MLU">MLU</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=DCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="DCU">DCU</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=CPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="CPU">CPU</a> | |||
</div> | |||
</div> | |||
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;"> | |||
@@ -91,7 +93,7 @@ | |||
for (var i = 0, iLen = data.length; i < iLen; i++) { | |||
var dataI = data[i]; | |||
var aiCenterCode = dataI.AiCenterCode; | |||
var aiCenterName = dataI.AiCenterName; | |||
var aiCenterName = dataI.AiCenterName || dataI.AiCenterCode; | |||
var itemClone = itemEl.clone(); | |||
var oHref = itemClone.attr('href'); | |||
var oId = itemClone.attr('id'); | |||
@@ -48,7 +48,8 @@ | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BENCHMARK&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.BENCHMARK"}}</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=ONLINEINFERENCE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="ONLINEINFERENCE">{{.i18n.Tr "cloudbrain.ONLINEINFERENCE"}}</a> | |||
<!-- <a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4IMAGENET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.SNN4IMAGENET"}}</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.BRAINSCORE"}}</a> --> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="BENCHMARK">{{.i18n.Tr "cloudbrain.BRAINSCORE"}}</a> --> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SUPERCOMPUTE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="SUPERCOMPUTE">{{.i18n.Tr "repo.superComputeTask"}}</a> | |||
</div> | |||
</div> | |||
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;"> | |||
@@ -61,6 +62,7 @@ | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=GCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="GCU">GCU</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=MLU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MLU">MLU</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=DCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="DCU">DCU</a> | |||
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=CPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="CPU">CPU</a> | |||
</div> | |||
</div> | |||
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;"> | |||
@@ -105,7 +107,7 @@ | |||
for (var i = 0, iLen = data.length; i < iLen; i++) { | |||
var dataI = data[i]; | |||
var aiCenterCode = dataI.AiCenterCode; | |||
var aiCenterName = dataI.AiCenterName; | |||
var aiCenterName = dataI.AiCenterName || dataI.AiCenterCode; | |||
var itemClone = itemEl.clone(); | |||
var oHref = itemClone.attr('href'); | |||
var oId = itemClone.attr('id'); | |||
@@ -201,7 +201,15 @@ | |||
</span> | |||
</a> | |||
{{end}} | |||
<!-- {{if .IsSigned}} | |||
{{if .Permission.CanRead $.UnitTypeCloudBrain}} | |||
<a class="{{if .PageIsSuperCompute}}active{{end}} item" href="{{.RepoLink}}/supercompute"> | |||
<span> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path d="M14 18V20L16 21V22H8L7.99639 21.0036L10 20V18H2.9918C2.44405 18 2 17.5511 2 16.9925V4.00748C2 3.45107 2.45531 3 2.9918 3H21.0082C21.556 3 22 3.44892 22 4.00748V16.9925C22 17.5489 21.5447 18 21.0082 18H14ZM4 5V14H20V5H4Z"></path></svg> | |||
{{.i18n.Tr "repo.superCompute"}} | |||
</span> | |||
</a> | |||
{{end}} | |||
<!-- {{if .IsSigned}} | |||
<a class="{{if .PageIsBlockChain}}active{{end}} item " href="{{.RepoLink}}/blockchain"> | |||
{{svg "octicon-law" 16}} | |||
{{.i18n.Tr "repo.balance"}} | |||
@@ -0,0 +1,8 @@ | |||
{{template "base/head" .}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-super-create.css?v={{MD5 AppVer}}" /> | |||
<div class="repository release dataset-list view"> | |||
{{template "repo/header" .}} | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-super-create.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,8 @@ | |||
{{template "base/head" .}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-super-detail.css?v={{MD5 AppVer}}" /> | |||
<div class="repository release dataset-list view"> | |||
{{template "repo/header" .}} | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-super-detail.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,8 @@ | |||
{{template "base/head" .}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-super-apps.css?v={{MD5 AppVer}}" /> | |||
<div class="repository release dataset-list view"> | |||
{{template "repo/header" .}} | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-super-apps.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,8 @@ | |||
{{template "base/head" .}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-cloudbrain-super-list.css?v={{MD5 AppVer}}" /> | |||
<div class="repository release dataset-list view"> | |||
{{template "repo/header" .}} | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script src="{{StaticUrlPrefix}}/js/vp-cloudbrain-super-list.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -7,6 +7,7 @@ | |||
data-debug-again="{{$.i18n.Tr "repo.debug_again"}}" data-debug-task="{{$.i18n.Tr "cloudbrain.DEBUG"}}" | |||
data-train-task="{{$.i18n.Tr "cloudbrain.TRAIN"}}" data-inference-task="{{$.i18n.Tr "cloudbrain.INFERENCE"}}" | |||
data-benchmark-task="{{$.i18n.Tr "cloudbrain.BENCHMARK"}}" data-inferonline-task="{{$.i18n.Tr "cloudbrain.ONLINEINFERENCE"}}" | |||
data-supercompute-task="{{$.i18n.Tr "repo.superComputeTask"}}" | |||
data-all-cluster="{{.i18n.Tr "cloudbrain.all_resource_cluster"}}" | |||
data-all-aiCenter="{{.i18n.Tr "cloudbrain.all_ai_center"}}" | |||
data-cluster-c2net="{{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}" | |||
@@ -71,7 +72,7 @@ | |||
<div class="row"> | |||
<!-- 任务名 --> | |||
{{$JobID := '0'}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{if eq .JobType "DEBUG" "TRAIN" "SUPERCOMPUTE" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{$JobID = .Cloudbrain.ID}} | |||
{{else}} | |||
{{$JobID = .JobID}} | |||
@@ -85,6 +86,13 @@ | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if eq .JobType "SUPERCOMPUTE"}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/supercompute/job/{{$JobID}}" | |||
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px"> | |||
<span class="fitted" | |||
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
{{else if (eq .JobType "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN")}} | |||
<a class="title" | |||
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}" | |||
@@ -130,7 +138,7 @@ | |||
<div class="two wide column text center nowrap" | |||
style="width: 8% !important;"> | |||
<span class="job-status" id="{{$JobID}}" | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG" "ONLINEINFERENCE" "SUPERCOMPUTE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}' | |||
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" | |||
data-cloudbrainid="{{.Cloudbrain.ID}}" | |||
data-bootfile="{{.BootFile}}"> | |||
@@ -232,6 +240,19 @@ | |||
</form> | |||
</div> | |||
{{end}} | |||
{{if eq .JobType "SUPERCOMPUTE"}} | |||
<div class="ui compact buttons"> | |||
<form id="debugAgainForm-{{$JobID}}"> | |||
{{$.CsrfTokenHtml}} | |||
<a id="ai-debug-infer-{{$JobID}}" | |||
class='ui basic ai_debug {{if eq .Status "RUNNING"}} blue {{else}} disabled {{end}}button' | |||
data-jobid="{{$JobID}}" | |||
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'> | |||
{{$.i18n.Tr "repo.start_use"}} | |||
</a> | |||
</form> | |||
</div> | |||
{{end}} | |||
<!-- 停止任务 --> | |||
<div class="ui compact buttons"> | |||
{{if eq .JobType "MODELSAFETY"}} | |||
@@ -245,7 +266,7 @@ | |||
</a> | |||
</form> | |||
{{else}} | |||
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
{{if eq .JobType "DEBUG" "SUPERCOMPUTE" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET" "SIM2BRAIN_SNN" "ONLINEINFERENCE"}} | |||
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;"> | |||
{{$.CsrfTokenHtml}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" | |||
@@ -298,7 +319,7 @@ | |||
</form> | |||
{{else}} | |||
<form class="ui compact buttons" id="delForm-{{$JobID}}" | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}}/cloudbrain{{else if eq .JobType "DEBUG" "ONLINEINFERENCE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true' | |||
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET") (eq .JobType "SIM2BRAIN_SNN")}}/cloudbrain{{else if eq .JobType "DEBUG" "ONLINEINFERENCE" "SUPERCOMPUTE"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true' | |||
method="post"> | |||
{{$.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Cloudbrain.ID}}" style="display:none" name="id" /> | |||
@@ -151,7 +151,13 @@ | |||
{{$.i18n.Tr "action.task_c2net_dcudebugjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}} | |||
{{else}} | |||
{{$.i18n.Tr "action.task_c2net_dcudebugjob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span> | |||
{{end}} | |||
{{end}} | |||
{{else if eq .GetOpType 47}} | |||
{{if .Cloudbrain}} | |||
{{$.i18n.Tr "action.task_c2net_cpusupercomputejob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}} | |||
{{else}} | |||
{{$.i18n.Tr "action.task_c2net_cpusupercomputejob" "" "" "" | Str2html}}<span style="">{{.RefName}}{{$.i18n.Tr "repo.issues.deleted_milestone"}}</span> | |||
{{end}} | |||
{{else if eq .GetOpType 44}} | |||
{{if .Cloudbrain}} | |||
{{$.i18n.Tr "action.task_c2ent_mlutrainjob" .GetRepoLink (Printf "%d" .Cloudbrain.ID) .RefName | Str2html}} | |||
@@ -213,6 +219,8 @@ | |||
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span> | |||
{{else if eq .GetOpType 46}} | |||
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span> | |||
{{else if eq .GetOpType 47}} | |||
<span class="text grey"><i class="ri-voice-recognition-line icon big"></i></span> | |||
{{else if eq .GetOpType 27}} | |||
<span class="text grey"><i class="ri-character-recognition-line icon big"></i></span> | |||
{{else if eq .GetOpType 28}} | |||
@@ -551,6 +551,8 @@ function userSearchControll() { | |||
jobType = $(".cloudbrain_debug").data("inference-task"); | |||
} else if (params.get("jobType") === "ONLINEINFERENCE") { | |||
jobType = $(".cloudbrain_debug").data("inferonline-task"); | |||
} else if (params.get("jobType") === "SUPERCOMPUTE") { | |||
jobType = $(".cloudbrain_debug").data("supercompute-task"); | |||
} else { | |||
jobType = $(".cloudbrain_debug").data("benchmark-task"); | |||
} | |||
@@ -10,6 +10,7 @@ export const getAiTaskPrepareInfo = (params) => { | |||
job_type: params.jobType, | |||
compute_source: params.computeSource, | |||
cluster_type: params.clusterType, | |||
app_name: params.appName, | |||
}, | |||
}); | |||
} | |||
@@ -4,9 +4,10 @@ | |||
<span :class="required ? 'required' : ''">{{ $t('cloudbrainObj.taskName') }}</span> | |||
</div> | |||
<div class="content" :class="errStatus ? 'error' : ''"> | |||
<el-input class="field-input" v-model="currentValue" @input="handleInput" @change="handleInputChange" maxlength="36" | |||
:placeholder="$t('cloudbrainObj.taskName')" :autofocus="autofocus" :disabled="disabled"></el-input> | |||
<div class="tips">{{ $t('cloudbrainObj.taskNameTips') }}</div> | |||
<el-input class="field-input" v-model="currentValue" @input="handleInput" @change="handleInputChange" :maxlength="type == 'supercompute' ? 26 : 36" | |||
:placeholder="$t('cloudbrainObj.taskName')" :autofocus="autofocus"></el-input> | |||
<div v-if="type === 'supercompute'" class="tips">{{ $t('cloudbrainObj.taskNameTips1') }}</div> | |||
<div v-else class="tips">{{ $t('cloudbrainObj.taskNameTips') }}</div> | |||
</div> | |||
</div> | |||
</template> | |||
@@ -21,8 +22,8 @@ export default { | |||
userName: { type: String, required: true }, | |||
autofocus: { type: Boolean, default: true, }, | |||
generate: { type: Boolean, default: false, }, | |||
disabled: { type: Boolean, default: false }, | |||
required: { type: Boolean, default: true }, | |||
type: { type: String, default: '' }, | |||
}, | |||
data() { | |||
return { | |||
@@ -42,7 +43,12 @@ export default { | |||
methods: { | |||
check() { | |||
const reg = /^[a-z0-9][a-z0-9\-_]{1,34}[a-z0-9\-]$/; | |||
this.errStatus = !reg.test(this.currentValue); | |||
const reg1 = /^[a-z][a-z0-9\-]{4,25}$/; | |||
if (this.type == 'supercompute') { | |||
this.errStatus = !reg1.test(this.currentValue); | |||
} else { | |||
this.errStatus = !reg.test(this.currentValue); | |||
} | |||
if (!this.required && this.currentValue == '') { | |||
this.errStatus = false; | |||
} | |||
@@ -118,6 +118,9 @@ export default { | |||
case 'taskName': | |||
result = i18n.t('cloudbrainObj.taskName'); | |||
break; | |||
case 'appName': | |||
result = i18n.t('cloudbrainObj.appName'); | |||
break; | |||
case 'spec': | |||
result = i18n.t('cloudbrainObj.resourceSpec'); | |||
break; | |||
@@ -211,6 +214,9 @@ export default { | |||
case 'taskName': | |||
result = task.display_job_name; | |||
break; | |||
case 'appName': | |||
result = task.app_name; | |||
break; | |||
case 'imagev1': | |||
result = `<span class="ui poping up clipboard" | |||
id="clipboard-${SparkMD5.hash(task.image_url || task.image_name)}" | |||
@@ -6,12 +6,12 @@ export const POINT_ACTIONS = [ | |||
{ k: 'CreatePublicRepo', v: i18n.t('createPublicProject') }, { k: 'CreateIssue', v: i18n.t('dailyPutforwardTasks') }, { k: 'CreatePullRequest', v: i18n.t('dailyPR') }, { k: 'CommentIssue', v: i18n.t('comment') }, { k: 'UploadAttachment', v: i18n.t('uploadDatasetFile') }, { k: 'CreateNewModelTask', v: i18n.t('importNewModel') }, { k: 'BindWechat', v: i18n.t('completeWechatCodeScanningVerification') }, | |||
{ k: 'CreateCloudbrainTask', v: i18n.t('dailyRunCloudbrainTasks') }, { k: 'DatasetRecommended', v: i18n.t('datasetRecommendedByThePlatform') }, { k: 'CreateImage', v: i18n.t('submitNewPublicImage') }, { k: 'ImageRecommend', v: i18n.t('imageRecommendedByThePlatform') }, { k: 'ChangeUserAvatar', v: i18n.t('firstChangeofAvatar') }, { k: 'PushCommits', v: i18n.t('dailyCommit') }, | |||
]; | |||
export const JOB_TYPE = [{ k: 'DEBUG', v: i18n.t('debugTask') }, { k: 'TRAIN', v: i18n.t('trainTask') }, { k: 'INFERENCE', v: i18n.t('inferenceTask') }, { k: 'BENCHMARK', v: i18n.t('benchmarkTask') },{ k: 'ONLINEINFERENCE', v: i18n.t('onlineinfer') }]; | |||
export const JOB_TYPE = [{ k: 'DEBUG', v: i18n.t('debugTask') }, { k: 'TRAIN', v: i18n.t('trainTask') }, { k: 'INFERENCE', v: i18n.t('inferenceTask') }, { k: 'BENCHMARK', v: i18n.t('benchmarkTask') },{ k: 'ONLINEINFERENCE', v: i18n.t('onlineinfer') }, { k: 'SUPERCOMPUTE', v: i18n.t('superComputeTask') }]; | |||
// 资源管理 | |||
export const CLUSTERS = [{ k: 'OpenI', v: i18n.t('resourcesManagement.OpenI') }, { k: 'C2Net', v: i18n.t('resourcesManagement.C2Net') }]; | |||
export const AI_CENTER = [{ k: 'OpenIOne', v: i18n.t('resourcesManagement.OpenIOne') }, { k: 'OpenITwo', v: i18n.t('resourcesManagement.OpenITwo') }, { k: 'OpenIChengdu', v: i18n.t('resourcesManagement.OpenIChengdu') }, { k: 'pclcci', v: i18n.t('resourcesManagement.pclcci') }, { k: 'hefei', v: i18n.t('resourcesManagement.hefeiCenter') }, { k: 'xuchang', v: i18n.t('resourcesManagement.xuchangCenter') }]; | |||
export const COMPUTER_RESOURCES = [{ k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'GCU', v: 'GCU' }, { k: 'MLU', v: 'MLU' }, { k: 'DCU', v: 'DCU' }]; | |||
export const COMPUTER_RESOURCES = [{ k: 'CPU', v: 'CPU' }, { k: 'GPU', v: 'GPU' }, { k: 'NPU', v: 'NPU' }, { k: 'GCU', v: 'GCU' }, { k: 'MLU', v: 'MLU' }, { k: 'DCU', v: 'DCU' }]; | |||
export const ACC_CARD_TYPE = [{ k: 'T4', v: 'T4' }, { k: 'A100', v: 'A100' }, { k: 'V100', v: 'V100' }, { k: 'ASCEND910', v: 'Ascend 910' }, { k: 'MLU270', v: 'MLU270' }, { k: 'MLU290', v: 'MLU290' }, { k: 'RTX3080', v: 'RTX3080' }, { k: 'ENFLAME-T20', v: 'ENFLAME-T20' }, { k: 'DCU', v: 'DCU' }]; | |||
export const SPECIFICATION_STATUS = [{ k: '1', v: i18n.t('resourcesManagement.willOnShelf') }, { k: '2', v: i18n.t('resourcesManagement.onShelf') }, { k: '3', v: i18n.t('resourcesManagement.offShelf') }]; | |||
@@ -41,6 +41,7 @@ const en = { | |||
inferenceTask: 'Inference Task', | |||
benchmarkTask: 'Benchmark Task', | |||
onlineinfer: "Online Inference", | |||
superComputeTask: "HPC Task", | |||
createPublicProject: 'Create Public Projects', | |||
dailyPutforwardTasks: 'Daily Put Forward Tasks', | |||
dailyPR: 'Daily PR', | |||
@@ -511,7 +512,7 @@ const en = { | |||
openi: 'OpenI Resource Cluster', | |||
c2net: 'China Computing NET(Beta)', | |||
create: 'New ', | |||
createTask: 'New cloudbrain', | |||
createTask: 'Create Task', | |||
cluster: 'Resource cluster', | |||
computeResource: 'Computing resources', | |||
sameTaskTips1: 'You have created an <span>equivalent task</span> that is waiting or running, please wait for the task to finish before creating it.', | |||
@@ -529,8 +530,13 @@ const en = { | |||
taskPrepareTips: 'The task is currently being prepared. Drink a glass of water and come back to take a look~', | |||
waitCountStart: 'Your current queue position is ', | |||
waitCountEnd: '', | |||
task: ' Task', | |||
taskList: 'Task List', | |||
taskName: 'Task name', | |||
appName: 'App name', | |||
appList: 'App List', | |||
taskNameTips: 'Name must start with a lowercase letter or number,can include lowercase letter,number,_ and -,can not end with _, and can be up to 36 characters long.', | |||
taskNameTips1: 'Name must start with a lowercase letter,can include lowercase letter,number,and -, and between 5 and 26 characters.', | |||
taskDescr: 'Description', | |||
taskDescrPlaceholder: 'The description should not exceed 255 characters', | |||
codeBranch: 'Code branch', | |||
@@ -568,6 +574,7 @@ const en = { | |||
stop: 'Stop', | |||
modify: 'Modify', | |||
delete: 'Delete', | |||
startUse: 'Start use', | |||
more: 'More', | |||
commitImage: 'Submit Image', | |||
downloadModel: 'Download', | |||
@@ -601,6 +608,7 @@ const en = { | |||
debugTaskEmptyTip3: 'Instructions for use: You can refer to the OpenI AI collaboration platform<a href="{url}"> Help Center </a>.', | |||
onlineInferTaskEmptyTitle: 'Online Inference task has not been created', | |||
onlineInferEmptyTip2: 'Dataset: Cloud Brain 1 provides CPU/GPU,Cloud Brain 2 provides Ascend NPU.And dataset also needs to be uploaded to the corresponding environment;', | |||
superTaskEmptyTitle: 'Super compute task has not been created', | |||
deleteConfirmTips: 'Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered.', | |||
deletingTips: 'Task deletion in progress, please wait', | |||
tabTitDebug: 'Debug Task', | |||
@@ -644,6 +652,9 @@ const en = { | |||
}, | |||
superComputeObj: { | |||
mmlSparkDescr: `The full name of MMLSpark is Microsoft Machine Learning for Apache Spark, which supports users to run self-made container images and grants them root privileges within the container. Users can directly use Microsoft's MMLSpark provided by the platform.\nNote: MMLSpark is a Spark version provided by Microsoft for machine learning environments( <a target="_blank" href="https://github.com/Azure/mmlspark">https://github.com/Azure/mmlspark</a> )Regarding mmlspark, please refer to the following paper: <a target="_blank" href="https://arxiv.org/pdf/1810.08744.pdf">https://arxiv.org/pdf/1810.08744.pdf</a>`, | |||
} | |||
} | |||
export default en; |
@@ -40,6 +40,7 @@ const zh = { | |||
inferenceTask: "推理任务", | |||
benchmarkTask: "评测任务", | |||
onlineinfer: "在线推理", | |||
superComputeTask: "超算任务", | |||
createPublicProject: "创建公开项目", | |||
dailyPutforwardTasks: "每日提出任务", | |||
dailyPR: "每日提出PR", | |||
@@ -545,8 +546,13 @@ const zh = { | |||
taskPrepareTips: '任务正在准备中,喝杯水回来再看看~', | |||
waitCountStart: '您当前排队位置是第', | |||
waitCountEnd: '位', | |||
task: '任务', | |||
taskList: '任务列表', | |||
taskName: '任务名称', | |||
appName: '应用名称', | |||
appList: '应用列表', | |||
taskNameTips: '只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。', | |||
taskNameTips1: '只能以小写字母开头,包含数字、小写字母和短横线(-),长度为5~26个字符。', | |||
taskDescr: '任务描述', | |||
taskDescrPlaceholder: '描述字数不超过255个字符', | |||
codeBranch: '代码分支', | |||
@@ -584,6 +590,7 @@ const zh = { | |||
stop: '停止', | |||
modify: '修改', | |||
delete: '删除', | |||
startUse: '开始使用', | |||
more: '更多', | |||
commitImage: '提交镜像', | |||
downloadModel: '模型下载', | |||
@@ -617,6 +624,7 @@ const zh = { | |||
debugTaskEmptyTip3: '使用说明:可以参考启智AI协作平台 <a href="{url}" target="_blank">帮助中心</a>。', | |||
onlineInferTaskEmptyTitle: '未创建过在线推理任务', | |||
onlineInferEmptyTip2: '数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,在线推理使用的数据集也需要上传到对应的环境;', | |||
superTaskEmptyTitle: '未创建过超算任务', | |||
deleteConfirmTips: '您确认删除该任务么?此任务一旦删除不可恢复。', | |||
deletingTips: '任务删除中,请稍后', | |||
tabTitDebug: '调试任务', | |||
@@ -661,6 +669,10 @@ const zh = { | |||
}, | |||
superComputeObj: { | |||
mmlSparkDescr: `MMLSpark全称为Microsoft Machine Learning for Apache Spark,支持用户运行自制容器镜像,且赋予了用户容器内root权限。用户可直接使用平台提供的微软的MMLSpark。\n注:MMLSpark是微软提供针对机器学习环境的Spark版本(<a target="_blank" href="https://github.com/Azure/mmlspark">https://github.com/Azure/mmlspark</a>),关于mmlspark可参考论文:<a target="_blank" href="https://arxiv.org/pdf/1810.08744.pdf">https://arxiv.org/pdf/1810.08744.pdf</a>`, | |||
} | |||
} | |||
export default zh; |
@@ -27,14 +27,14 @@ | |||
<div class="row-r" style="flex:1">{{ $t('resourcesManagement.resQueue') }}</div> | |||
</div> | |||
<div class="table-content"> | |||
<div class="row" v-for="item in tableData1"> | |||
<div class="row" v-for="(item, index) in tableData1" :key="index"> | |||
<div class="row-l" style="width:600px;">{{ item.SpecStr }}</div> | |||
<div class="row-r" style="flex:1"> | |||
<div class="btn-c"> | |||
<button @click="selectAll(item.queues)">{{ $t('selectAll') }}</button> | |||
<button @click="clearSelectAll(item.queues)">{{ $t('selectNone') }}</button> | |||
</div> | |||
<div class="" v-for="_item in item.queues"> | |||
<div class="" v-for="_item in item.queues" :key="_item.ID"> | |||
<el-checkbox :value="_item.checked" @change="selectChange(_item.ID)"> | |||
<span v-html="_item.QueueStr + _item.PriceStr + _item.StatusStr"></span> | |||
</el-checkbox> | |||
@@ -50,14 +50,14 @@ | |||
<div class="row-r" style="flex:1">{{ $t('resourcesManagement.resourceSpecification') }}</div> | |||
</div> | |||
<div class="table-content"> | |||
<div class="row" v-for="item in tableData2"> | |||
<div class="row" v-for="(item, index) in tableData2" :key="index"> | |||
<div class="row-l" style="width:400px;">{{ item.QueueStr }}</div> | |||
<div class="row-r" style="flex:1"> | |||
<div class="btn-c"> | |||
<button @click="selectAll(item.specs)">{{ $t('selectAll') }}</button> | |||
<button @click="clearSelectAll(item.specs)">{{ $t('selectNone') }}</button> | |||
</div> | |||
<div class="" v-for="_item in item.specs"> | |||
<div class="" v-for="_item in item.specs" :key="_item.ID"> | |||
<el-checkbox :value="_item.checked" @change="selectChange(_item.ID)"> | |||
<span v-html="_item.SpecStr + _item.PriceStr + _item.StatusStr"></span> | |||
</el-checkbox> | |||
@@ -83,10 +83,10 @@ | |||
<div class="row-r" style="flex:1">{{ $t('resourcesManagement.resQueue') }}</div> | |||
</div> | |||
<div class="table-content"> | |||
<div class="row" v-for="item in tableDataShow"> | |||
<div class="row" v-for="(item, index) in tableDataShow" :key="index"> | |||
<div class="row-l" style="width:400px;">{{ item.SpecStr }}</div> | |||
<div class="row-r" style="flex:1"> | |||
<div class="" v-for="_item in item.queues"> | |||
<div class="" v-for="(_item, _index) in item.queues" :key="_index"> | |||
<span v-html="_item.QueueStr + _item.PriceStr + _item.StatusStr"></span> | |||
</div> | |||
</div> | |||
@@ -397,7 +397,7 @@ export default { | |||
} | |||
.dlg-content { | |||
margin: -30px 0 0 0; | |||
margin: 0px 0 0 0; | |||
display: flex; | |||
font-size: 12px; | |||
@@ -0,0 +1,186 @@ | |||
<template> | |||
<div> | |||
<div class="ui container"> | |||
<div class="header"> | |||
<div class="tab-c"> | |||
<a class="tab-item" :href="`/${repoOwnerName}/${repoName}/${item.url}`" :key="item.key" | |||
:class="item.type == curTab ? 'focus' : ''" v-for="item in tabs"> | |||
<span>{{ item.label }}</span> | |||
</a> | |||
</div> | |||
<div class="right-c"></div> | |||
</div> | |||
<div class="list"> | |||
<div class="item-c" v-for="(item, index) in apps" :key="index"> | |||
<el-tooltip class="item-tool-tips" effect="light" placement="bottom"> | |||
<a class="item" :href="`/${repoOwnerName}/${repoName}/supercompute/job/create?type=${item.type}`"> | |||
<div class="logo"> | |||
<img :src="item.logo" alt="" /> | |||
</div> | |||
<div class="name"> {{ item.name }}</div> | |||
</a> | |||
<div slot="content" class="item-tool-tip-content" v-html="item.descr"></div> | |||
</el-tooltip> | |||
</div> | |||
</div> | |||
</div> | |||
<LoadingMask :loading="maskLoading" :content="maskLoadingContent"></LoadingMask> | |||
</div> | |||
</template> | |||
<script> | |||
import LoadingMask from '~/components/cloudbrain/LoadingMask.vue'; | |||
import { TABS } from '../configs'; | |||
export default { | |||
data() { | |||
return { | |||
curTab: 'app', | |||
tabs: [...TABS], | |||
repoOwnerName: location.pathname.split('/')[1], | |||
repoName: location.pathname.split('/')[2], | |||
apps: [{ | |||
type: 'MMLSpark', | |||
name: 'MMLSpark', | |||
logo: '/img/supercompute/mmlspark.jpg', | |||
descr: this.$t('superComputeObj.mmlSparkDescr'), | |||
}], | |||
maskLoading: false, | |||
maskLoadingContent: '', | |||
}; | |||
}, | |||
components: { | |||
LoadingMask | |||
}, | |||
methods: {}, | |||
beforeMount() { }, | |||
mounted() { }, | |||
beforeDestroy() { }, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
@import '~/components/cloudbrain/cloudbrain.less'; | |||
.header { | |||
margin-bottom: 26px; | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
.tab-c { | |||
display: flex; | |||
align-items: center; | |||
.tab-item { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
font-size: 13px; | |||
color: rgba(0, 0, 0, .87); | |||
border: 1px solid rgba(34, 36, 38, .15); | |||
margin-left: -1px; | |||
height: 38px; | |||
padding: 0 12px; | |||
border-left: none; | |||
&.focus { | |||
color: #0087f5; | |||
border-color: #0087f5; | |||
border-left: 1px solid #0087f5; | |||
} | |||
&:first-child { | |||
border-radius: 0.28571429rem 0 0 0.28571429rem; | |||
border-left: 1px solid rgba(34, 36, 38, .15); | |||
&.focus { | |||
border-color: #0087f5; | |||
} | |||
} | |||
&:last-child { | |||
border-radius: 0 0.28571429rem 0.28571429rem 0; | |||
} | |||
&:hover:not(.focus) { | |||
background: rgba(0, 0, 0, .03); | |||
} | |||
} | |||
} | |||
.right-c { | |||
display: flex; | |||
align-items: center; | |||
} | |||
} | |||
.list { | |||
display: flex; | |||
flex-wrap: wrap; | |||
.item-c { | |||
width: 288px; | |||
height: 221px; | |||
display: flex; | |||
.item { | |||
flex: 1; | |||
margin: 10px; | |||
border-radius: 4px; | |||
cursor: pointer; | |||
box-shadow: 0px 4px 4px 0px rgba(232, 232, 232, 0.6); | |||
border: 1px solid #e8e8e8 !important; | |||
padding: 16px; | |||
.logo { | |||
height: 140px; | |||
box-shadow: 0px 1px 1px 0px rgba(232, 232, 232, 0.6); | |||
img { | |||
height: 100%; | |||
width: 100%; | |||
object-fit: cover; | |||
} | |||
} | |||
.name { | |||
text-align: center; | |||
font-size: 16px; | |||
font-weight: bold; | |||
margin-top: 12px; | |||
color: #0366D6; | |||
} | |||
} | |||
} | |||
} | |||
.item-tool-tips { | |||
.el-tooltip__popper .popper__arrow { | |||
/* 上方箭头 */ | |||
border-top-color: #fff !important; | |||
/* 下方箭头 */ | |||
border-bottom-color: #fff !important; | |||
} | |||
.el-tooltip__popper .popper__arrow:after { | |||
border-top-color: #fff !important; | |||
border-bottom-color: #fff !important; | |||
} | |||
/* tooltip主体部分 */ | |||
.el-tooltip__popper { | |||
padding: 0 !important; | |||
border-radius: 4px !important; | |||
border-color: #e6e6e6 !important; | |||
box-shadow: 0px 0px 7px 0px rgba(42, 42, 42, 0.2) !important; | |||
} | |||
} | |||
.item-tool-tip-content { | |||
width: 402px; | |||
word-wrap: break-word; | |||
white-space: pre-wrap; | |||
} | |||
</style> |
@@ -0,0 +1,17 @@ | |||
import Vue from 'vue'; | |||
import ElementUI from 'element-ui'; | |||
import 'element-ui/lib/theme-chalk/index.css'; | |||
import localeEn from 'element-ui/lib/locale/lang/en'; | |||
import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||
import { i18n, lang } from '~/langs'; | |||
import App from './index.vue'; | |||
Vue.use(ElementUI, { | |||
locale: lang === 'zh-CN' ? localeZh : localeEn, | |||
size: 'small', | |||
}); | |||
new Vue({ | |||
i18n, | |||
render: (h) => h(App), | |||
}).$mount('#__vue-root'); |
@@ -0,0 +1,94 @@ | |||
import { i18n } from '~/langs'; | |||
export const TABS = [{ | |||
type: 'app', | |||
url: 'supercompute', | |||
label: i18n.t('cloudbrainObj.appList'), | |||
}, { | |||
type: 'task', | |||
url: 'supercompute/job', | |||
label: i18n.t('cloudbrainObj.taskList'), | |||
}]; | |||
export const ListPageConfigs = { | |||
page: { | |||
clusterType: 'C2Net', | |||
computerResouce: 'CPU', | |||
appName: 'MMLSpark', | |||
jobType: 'SUPERCOMPUTE', | |||
jobTypeName: i18n.t('superComputeTask'), | |||
columns: ['taskName', 'status', 'appName', 'createTime', 'runDuration', 'clusterAndComputeResource', 'creator'], | |||
operations: ['start', 'stop', 'delete'], | |||
emptyTitle: i18n.t('cloudbrainObj.superTaskEmptyTitle'), | |||
emptyTip0: true, | |||
emptyTip1: '', | |||
emptyTip2: '', | |||
emptyTip3: i18n.t('cloudbrainObj.debugTaskEmptyTip3', { url: 'https://openi.pcl.ac.cn/docs/index.html#/supercompute/mmlspark' }), | |||
} | |||
}; | |||
export const CreatePageConfigs = { | |||
'MMLSpark': { | |||
appListUrl: 'supercompute', | |||
taskListUrl: 'supercompute/job', | |||
taskType: 'SUPERCOMPUTE', | |||
taskTypeName: i18n.t('superComputeTask'), | |||
clusterType: 'C2Net', | |||
computerResouce: 'CPU', | |||
appName: 'MMLSpark', | |||
hideCluster: true, | |||
hideComputerResource: true, | |||
tips2: i18n.t('cloudbrainObj.pathTips3', { | |||
code: '/code', | |||
dataset: '/dataset', | |||
model: '/pretrainmodel', | |||
}), | |||
form: { | |||
taskName: { required: true, }, | |||
taskDescr: { required: false, }, | |||
branchName: {}, | |||
model: { required: false, multiple: true }, | |||
imagev2: { required: true }, | |||
dataset: { required: false }, | |||
spec: { required: true }, | |||
}, | |||
} | |||
}; | |||
export const DetailPageConfigs = { | |||
'MMLSpark': { | |||
listUrl: 'supercompute/job', | |||
summary: [], | |||
operations: [], | |||
tabs: [{ | |||
name: 'configInfo', | |||
fields: [ | |||
'taskName', 'appName', | |||
'status', 'imagev2', | |||
'creator', 'spec', | |||
'branch', 'aiCenter', | |||
'computerRes', 'modelName', | |||
'createTime', 'modelVersion', | |||
'startTime', 'modelFiles', | |||
'endTime', '', | |||
'duration', '', | |||
'descr', '', | |||
'failedReason', | |||
'dataset', | |||
'modelList', | |||
] | |||
}], | |||
} | |||
}; | |||
export const getAiJobLink = (taskInfo) => { | |||
return `supercompute/job/${taskInfo.id}`; | |||
}; | |||
export const getCreatePageConfigs = (appName) => { | |||
return CreatePageConfigs[appName] || CreatePageConfigs['MMLSpark']; | |||
}; | |||
export const getDetailPageConfigs = (appName) => { | |||
return DetailPageConfigs[appName]; | |||
}; |
@@ -0,0 +1,406 @@ | |||
<template> | |||
<div> | |||
<div class="ui container" v-if="errorMsgBoxShow"> | |||
<div class="err-msg-box"> | |||
<p>{{ errorMsg }}</p> | |||
</div> | |||
</div> | |||
<div class="ui container"> | |||
<div class="head-path"> | |||
<a class="section" :href="`/${repoOwnerName}/${repoName}/supercompute`">{{ $t('cloudbrainObj.appList') }}</a> | |||
<span class="divider">/</span> | |||
<span class="section active">{{ $t('cloudbrainObj.create') }}{{ $t('superComputeTask') }}</span> | |||
</div> | |||
<div class="form-container"> | |||
<div class="form-head"> | |||
<h4>{{ $t('cloudbrainObj.create') }}{{ pageCfg.appName }}{{ $t('cloudbrainObj.task') }}</h4> | |||
</div> | |||
<div class="ui container" v-if="alreadyMsgBoxShow"> | |||
<div class="err-msg-box-already"> | |||
<div class="msg-content"> | |||
<i class="ri-information-line"></i> | |||
<div class="msg-content-tip"> | |||
<div class="line-1" v-html="$t('cloudbrainObj.sameTaskTips1')"></div> | |||
<div class="line-2" v-html="$t('cloudbrainObj.sameTaskTips2')"></div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="form-body"> | |||
<div class="form-body-content"> | |||
<div class="main-title">{{ $t('cloudbrainObj.basicInfo') }}:</div> | |||
<FormTop ref="formTopRef" :repoOwnerName="repoOwnerName" :repoName="repoName" :configs="pageCfg" | |||
:queueNum="queueNum"></FormTop> | |||
<TaskName ref="taskNameRef" v-if="formCfg.taskName" v-model="state.taskName" autofocus type="supercompute" | |||
:required="formCfg.taskName.required" :userName="repoOwnerName"> | |||
</TaskName> | |||
<TaskDescr ref="taskDescrRef" v-if="formCfg.taskDescr" v-model="state.taskDescr" | |||
:required="formCfg.taskDescr.required"></TaskDescr> | |||
</div> | |||
<div class="line"></div> | |||
<div class="form-body-content"> | |||
<div class="main-title params-setting">{{ $t('cloudbrainObj.paramsSetting') }}:</div> | |||
<BranchName ref="branchNameRef" v-if="formCfg.branchName" v-model="state.branchName" | |||
:required="formCfg.branchName.required" :branches="branchList"> | |||
</BranchName> | |||
<ModelSelect ref="modelRef" v-if="formCfg.model" v-model="state.model" :required="formCfg.model.required" | |||
:multiple="formCfg.model.multiple" :repoOwnerName="repoOwnerName" :repoName="repoName"></ModelSelect> | |||
<ImageSelectV2 ref="imagev2Ref" v-if="formCfg.imagev2" v-model="state.image" :images="imageList" | |||
:required="formCfg.imagev2.required"> | |||
</ImageSelectV2> | |||
<DatasetSelect ref="datasetRef" v-if="formCfg.dataset" v-model="state.dataset" | |||
:required="formCfg.dataset.required" :type="formCfg.dataset.type != undefined ? formCfg.dataset.type : -1" | |||
:repoOwnerName="repoOwnerName" :repoName="repoName" :exceedSize="datasetSize"></DatasetSelect> | |||
<SpecSelect ref="specRef" v-if="formCfg.spec" v-model="state.spec" :required="formCfg.spec.required" | |||
:configs="specConfigs" :workServerNum="state.workServerNum"></SpecSelect> | |||
<div class="form-row"> | |||
<div class="title"></div> | |||
<div class="content"> | |||
<el-button type="primary" :disabled="maskLoading || alreadyMsgBoxShow || noSpecFlag" size="default" | |||
class="submit-btn" @click="submit">{{ $t('cloudbrainObj.createTask') }}</el-button> | |||
<el-button class="cancel-btn" size="default" @click="cancel">{{ $t('cancel') }}</el-button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<LoadingMask :loading="maskLoading" :content="maskLoadingContent"></LoadingMask> | |||
</div> | |||
</template> | |||
<script> | |||
import FormTop from '~/components/cloudbrain/FormTop.vue'; | |||
import TaskName from '~/components/cloudbrain/TaskName.vue'; | |||
import TaskDescr from '~/components/cloudbrain/TaskDescr.vue'; | |||
import BranchName from '~/components/cloudbrain/BranchName.vue'; | |||
import ModelSelect from '~/components/cloudbrain/ModelSelect.vue'; | |||
import ImageSelectV2 from '~/components/cloudbrain/ImageSelectV2.vue'; | |||
import DatasetSelect from '~/components/cloudbrain/DatasetSelect.vue'; | |||
import SpecSelect from '~/components/cloudbrain/SpecSelect.vue'; | |||
import LoadingMask from '~/components/cloudbrain/LoadingMask.vue'; | |||
import { getCreatePageConfigs } from '../configs'; | |||
import { getUrlSearchParams } from '~/utils'; | |||
import { getAiTaskPrepareInfo, createAiTask } from '~/apis/modules/cloudbrain'; | |||
export default { | |||
data() { | |||
return { | |||
pageCfg: {}, | |||
formCfg: {}, | |||
cancelUrl: '', | |||
successUrl: '', | |||
repoOwnerName: location.pathname.split('/')[1], | |||
repoName: location.pathname.split('/')[2], | |||
state: { | |||
taskName: '', | |||
taskDescr: '', | |||
branchName: '', | |||
model: [], | |||
image_url: '', | |||
image: {}, | |||
dataset: [], | |||
spec: '', | |||
}, | |||
branchList: [], | |||
imageList: [], | |||
specConfigs: { | |||
specs: [], | |||
blance: 0, | |||
showPoint: false, | |||
}, | |||
queueNum: 1, | |||
errorMsgBoxShow: false, | |||
errorMsg: '', | |||
alreadyMsgBoxShow: false, | |||
maskLoading: false, | |||
maskLoadingContent: '', | |||
datasetSize: 0, | |||
noSpecFlag: false, | |||
}; | |||
}, | |||
components: { | |||
FormTop, TaskName, TaskDescr, BranchName, ImageSelectV2, ModelSelect, DatasetSelect, SpecSelect, | |||
LoadingMask | |||
}, | |||
methods: { | |||
submit() { | |||
if (this.maskLoading) return; | |||
let canSubmit = true; | |||
for (let key in this.formCfg) { | |||
if (this.$refs[key + 'Ref']) { | |||
if (!this.$refs[key + 'Ref'].check()) { | |||
canSubmit = false; | |||
} | |||
} | |||
} | |||
if (!canSubmit) return; | |||
const subObj = { | |||
repoOwnerName: this.repoOwnerName, | |||
repoName: this.repoName, | |||
job_type: this.pageCfg.taskType, | |||
cluster: this.pageCfg.clusterType, | |||
compute_source: this.pageCfg.computerResouce, | |||
app_name: this.pageCfg.appName, | |||
}; | |||
for (let key in this.formCfg) { | |||
switch (key) { | |||
case 'taskName': | |||
subObj['display_job_name'] = this.state.taskName; | |||
break; | |||
case 'taskDescr': | |||
subObj['description'] = this.state.taskDescr; | |||
break; | |||
case 'branchName': | |||
subObj['branch_name'] = this.state.branchName; | |||
break; | |||
case 'model': | |||
const modelInfo = this.state.model[0] || {}; | |||
const pretrain_model_ckpt_name = this.state.model.map(item => item.FileName).join(';'); | |||
subObj['pretrain_model_id'] = modelInfo._modelID || ''; | |||
subObj['pretrain_model_name'] = modelInfo._modelName || ''; | |||
subObj['pretrain_model_version'] = modelInfo._modelVersion || ''; | |||
subObj['pretrain_model_ckpt_name'] = pretrain_model_ckpt_name || ''; | |||
subObj['pretrain_model_url'] = modelInfo._preTrainModelUrl || ''; | |||
break; | |||
case 'imagev2': | |||
subObj['image_id'] = this.state.image.image_id; | |||
subObj['image_name'] = this.state.image.image_name; | |||
break; | |||
case 'dataset': | |||
subObj['dataset_uuid_str'] = this.state.dataset.map(item => item.id).join(';'); | |||
break; | |||
case 'spec': | |||
subObj['spec_id'] = Number(this.state.spec); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
// console.log('subObj', subObj); | |||
// return; | |||
this.maskLoadingContent = this.$t('cloudbrainObj.taskPrepareTips'); | |||
this.maskLoading = true; | |||
this.errorMsg = ''; | |||
this.errorMsgBoxShow = false; | |||
createAiTask(subObj).then(res => { | |||
const data = res.data; | |||
if (data.code == 0) { | |||
this.goTaskList(); | |||
} else { | |||
this.maskLoading = false; | |||
this.errorMsg = data.msg; | |||
this.errorMsgBoxShow = true; | |||
} | |||
}).catch(err => { | |||
this.maskLoading = false; | |||
console.log(err); | |||
}); | |||
}, | |||
cancel() { | |||
if (this.cancelUrl) { | |||
window.location.href = this.cancelUrl; | |||
} else { | |||
window.history.back(); | |||
} | |||
}, | |||
goTaskList() { | |||
window.location.href = this.successUrl; | |||
} | |||
}, | |||
beforeMount() { | |||
const urlParams = getUrlSearchParams(); | |||
const appName = urlParams.type; | |||
const configs = getCreatePageConfigs(appName); | |||
this.pageCfg = configs; | |||
this.formCfg = configs.form; | |||
this.cancelUrl = `/${this.repoOwnerName}/${this.repoName}/${configs.appListUrl}`; | |||
this.successUrl = `/${this.repoOwnerName}/${this.repoName}/${configs.taskListUrl}`; | |||
if (urlParams.backurl) { | |||
this.cancelUrl = urlParams.backurl; | |||
} | |||
if (!configs.taskType || !configs.clusterType || !configs.computerResouce) { | |||
console.log(`page configs error.`); | |||
this.cancel(); | |||
return; | |||
} | |||
getAiTaskPrepareInfo({ | |||
repoOwnerName: this.repoOwnerName, | |||
repoName: this.repoName, | |||
jobType: configs.taskType, | |||
clusterType: configs.clusterType, | |||
computeSource: configs.computerResouce, | |||
appName: configs.appName, | |||
}).then(res => { | |||
res = res.data; | |||
if (res.code == 0) { | |||
const data = res.data; | |||
this.branchList = data.branches || []; | |||
this.imageList = data.images || []; | |||
this.alreadyMsgBoxShow = data.not_stop_task_count > 0; | |||
this.specConfigs.showPoint = data.pay_switch; | |||
this.specConfigs.blance = data.point_account ? data.point_account.balance : 0; | |||
this.specConfigs.specs = data.specs || []; | |||
if (!this.specConfigs.specs.length) { | |||
this.noSpecFlag = true | |||
} | |||
this.queueNum = data.wait_count || 1; | |||
this.state.branchName = data.default_branch; | |||
this.state.taskName = data.display_job_name; | |||
this.state.spec = this.specConfigs.specs.length ? this.specConfigs.specs[0].id.toString() : ''; | |||
this.state.image = this.imageList.length ? { | |||
image_id: this.imageList[0].image_id, | |||
image_name: this.imageList[0].image_name, | |||
} : {}; | |||
if (data.config && data.config.dataset_max_size) { | |||
this.datasetSize = data.config.dataset_max_size; | |||
} | |||
} else { | |||
} | |||
}).catch(err => { | |||
console.log(err); | |||
}); | |||
}, | |||
mounted() { }, | |||
beforeDestroy() { }, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
@import '~/components/cloudbrain/cloudbrain.less'; | |||
.err-msg-box { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
background-color: #fff6f6; | |||
color: #9f3a38; | |||
box-shadow: 0 0 0 1px #e0b4b4 inset, 0 0 0 0 transparent; | |||
margin: 1em 0; | |||
padding: 1em 1.5em; | |||
border-radius: 0.28571429rem; | |||
transition: opacity .1s ease, color .1s ease, background .1s ease, box-shadow .1s ease, -webkit-box-shadow .1s ease; | |||
>p { | |||
opacity: .85; | |||
} | |||
} | |||
.err-msg-box-already { | |||
margin: 1em 0; | |||
padding: 1em 1.5em; | |||
background-color: rgba(242, 113, 28, 0.05); | |||
border: 1px solid rgba(242, 113, 28, 1); | |||
border-radius: 5px; | |||
.msg-content { | |||
display: flex; | |||
align-items: center; | |||
i { | |||
font-size: 35px; | |||
color: rgba(242, 113, 28, 1); | |||
} | |||
.msg-content-tip { | |||
text-align: left; | |||
margin-left: 1rem; | |||
.line-1 { | |||
font-weight: 600; | |||
line-height: 2; | |||
span { | |||
color: rgba(242, 113, 28, 1); | |||
} | |||
} | |||
.line-2 { | |||
color: #939393 | |||
} | |||
} | |||
} | |||
} | |||
.head-path { | |||
margin-top: -0.14285714em; | |||
margin-bottom: 1rem; | |||
.section { | |||
display: inline-block; | |||
margin: 0; | |||
padding: 0; | |||
color: #4183c4; | |||
line-height: 1.4285em; | |||
font-size: 1rem; | |||
font-weight: 700; | |||
cursor: pointer; | |||
&.active { | |||
color: rgba(0, 0, 0, .87); | |||
cursor: default; | |||
} | |||
&:hover { | |||
&:not(.active) { | |||
color: #1e70bf; | |||
} | |||
} | |||
} | |||
.divider { | |||
display: inline-block; | |||
opacity: .7; | |||
margin: 0 0.21428571rem 0; | |||
font-size: .92857143em; | |||
color: rgba(0, 0, 0, .4); | |||
vertical-align: baseline; | |||
} | |||
} | |||
.form-container { | |||
.form-head { | |||
background: #f0f0f0; | |||
border-radius: 0.28571429rem 0.28571429rem 0 0; | |||
padding: 0.78571429rem 1rem; | |||
margin: 0 -1px; | |||
box-shadow: none; | |||
border: 1px solid #d4d4d5; | |||
} | |||
.form-body { | |||
min-height: 400px; | |||
border: 1px solid #d4d4d5; | |||
margin: -1px -1px; | |||
padding: 3em; | |||
background-color: #FFF; | |||
.form-body-content { | |||
max-width: 1200px; | |||
margin: 0 auto; | |||
padding-right: 120px; | |||
.main-title { | |||
color: #101010; | |||
font-size: 16px; | |||
padding-left: 5rem; | |||
font-weight: 700; | |||
line-height: 1.28571429em; | |||
margin: 16px 0; | |||
} | |||
} | |||
.line { | |||
border-top: 1px solid rgba(34, 36, 38, .15); | |||
border-bottom: 1px solid rgba(255, 255, 255, .1); | |||
margin: 1rem 0 2rem; | |||
} | |||
} | |||
} | |||
/deep/ .form-row .content { | |||
width: 65%; | |||
} | |||
</style> |
@@ -0,0 +1,17 @@ | |||
import Vue from 'vue'; | |||
import ElementUI from 'element-ui'; | |||
import 'element-ui/lib/theme-chalk/index.css'; | |||
import localeEn from 'element-ui/lib/locale/lang/en'; | |||
import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||
import { i18n, lang } from '~/langs'; | |||
import App from './index.vue'; | |||
Vue.use(ElementUI, { | |||
locale: lang === 'zh-CN' ? localeZh : localeEn, | |||
size: 'small', | |||
}); | |||
new Vue({ | |||
i18n, | |||
render: (h) => h(App), | |||
}).$mount('#__vue-root'); |
@@ -0,0 +1,332 @@ | |||
<template> | |||
<div style="min-height:400px;"> | |||
<div v-if="notFound"> | |||
<NotFound></NotFound> | |||
</div> | |||
<div v-else> | |||
<div v-if="!loading" class="ui container"> | |||
<div class="head-path"> | |||
<a class="section" :href="`/${repoOwnerName}/${repoName}/${pageCfg.listUrl}`">{{ $t('cloudbrainObj.taskList') | |||
}}</a> | |||
<span class="divider">/</span> | |||
<span class="section active">{{ mainData[0] ? mainData[0].task.display_job_name : '' }}</span> | |||
</div> | |||
<div class="body-content"> | |||
<el-collapse class="collapse" accordion v-model="collapseValue" @change="taskChange"> | |||
<el-collapse-item class="collapse-item" v-for="(item, index) in mainData" :key="index" | |||
:name="index.toString()"> | |||
<template slot="title"> | |||
<div class="title" @click.stop.prevent=""> | |||
<div class="title-l"> | |||
<span class="task-create-time">{{ item.task.createTimeStr }}</span> | |||
<span class="task-status"> | |||
<span>{{ $t('status') }}:</span><i :class="item.task.status"></i><span>{{ item.task.status }}</span> | |||
</span> | |||
<span class="task-duration"> | |||
<span>{{ $t('cloudbrainObj.runDuration') }}:</span><span>{{ item.task.formatted_duration }}</span> | |||
</span> | |||
<span class="task-refresh"> | |||
<el-tooltip placement="top" :content="$t('cloudbrainObj.refresh')"> | |||
<i class="el-icon-refresh-right" @click.stop.prevent="refresh(item)"></i> | |||
</el-tooltip> | |||
</span> | |||
</div> | |||
<div class="title-r"></div> | |||
</div> | |||
</template> | |||
<div class="content"> | |||
<el-tabs v-model="item.activeName" @tab-click="tabChange(item)"> | |||
<el-tab-pane v-if="tabNameList.indexOf('configInfo') >= 0" | |||
:label="$t('cloudbrainObj.configurationInfo')" :name="`configInfo-` + item.task.id"> | |||
<ConfigInfo :ref="`configInfo-` + item.task.id + '-Ref'" :data="item" | |||
:configs="tabConfigs['configInfo']"> | |||
</ConfigInfo> | |||
</el-tab-pane> | |||
</el-tabs> | |||
</div> | |||
</el-collapse-item> | |||
</el-collapse> | |||
</div> | |||
</div> | |||
</div> | |||
<LoadingMask :loading="maskLoading" :content="maskLoadingContent"></LoadingMask> | |||
</div> | |||
</template> | |||
<script> | |||
import NotFound from '~/components/NotFound.vue'; | |||
import LoadingMask from '~/components/cloudbrain/LoadingMask.vue'; | |||
import ConfigInfo from '~/components/cloudbrain/details/ConfigInfo.vue'; | |||
import { CloudBrainTools } from '~/pages/cloudbrain/tools'; | |||
import { CLUSTERS } from '~/const'; | |||
import { timeSinceUnix, getListValueWithKey } from '~/utils'; | |||
import { getDetailPageConfigs, getAiJobLink } from '../configs'; | |||
import { getAiTask } from '~/apis/modules/cloudbrain'; | |||
import { formatDate } from 'element-ui/lib/utils/date-util'; | |||
const cloudBrainTools = new CloudBrainTools(); | |||
export default { | |||
data() { | |||
return { | |||
notFound: false, | |||
pageCfg: {}, | |||
tabNameList: [], | |||
tabConfigs: {}, | |||
operationList: [], | |||
repoOwnerName: location.pathname.split('/')[1], | |||
repoName: location.pathname.split('/')[2], | |||
state: {}, | |||
collapseValue: '0', | |||
mainData: [], | |||
loading: false, | |||
errorMsgBoxShow: false, | |||
errorMsg: '', | |||
maskLoading: false, | |||
maskLoadingContent: '', | |||
}; | |||
}, | |||
components: { NotFound, LoadingMask, ConfigInfo }, | |||
methods: { | |||
taskChange(taskIndex) { | |||
const item = this.mainData[Number(taskIndex)]; | |||
item.activeName = 'configInfo-' + item.task.id; | |||
}, | |||
tabChange(item) { | |||
this.$nextTick(() => { | |||
this.refresh(item); | |||
}); | |||
}, | |||
refresh(item) { | |||
const activeTab = item.activeName; | |||
const tabContent = this.$refs[activeTab + '-Ref']; | |||
if (activeTab.indexOf('configInfo-') > -1) { | |||
const task = item.task; | |||
const taskId = task.id; | |||
getAiTask({ | |||
repoOwnerName: task.repoOwnerName, | |||
repoName: task.repoName, | |||
id: taskId, | |||
}).then(res => { | |||
res = res.data; | |||
if (res.code == 0) { | |||
Object.assign(task, res.data.task); | |||
delete res.data.task; | |||
delete res.data.early_version_list; | |||
Object.assign(item, res.data); | |||
Object.assign(task, res.data); | |||
task.createdFromNow = timeSinceUnix(task.created_unix, Date.now() / 1000); | |||
task.createTimeStr = formatDate(new Date(task.created_unix * 1000), 'yyyy-MM-dd HH:mm:ss'); | |||
cloudBrainTools.checkOperation(task); | |||
} | |||
}).catch(err => { | |||
console.log(err); | |||
}); | |||
} else { | |||
tabContent && tabContent[0] && tabContent[0].refresh && tabContent[0].refresh(); | |||
} | |||
} | |||
}, | |||
beforeMount() { | |||
const taskId = window.location.pathname.split('/').pop(); | |||
this.loading = true; | |||
getAiTask({ | |||
repoOwnerName: this.repoOwnerName, | |||
repoName: this.repoName, | |||
id: taskId, | |||
}).then(res => { | |||
this.loading = false; | |||
res = res.data; | |||
if (res.code == 0 && res.data) { | |||
const earlyVersionList = (res.data.early_version_list || []).map(item => { | |||
return Object.assign({}, res.data, { task: item }); | |||
}); | |||
const data = [res.data, ...earlyVersionList]; | |||
let appName = ''; | |||
data.forEach(item => { | |||
const task = item.task; | |||
appName = task.app_name; | |||
task.computeSourceShow = task.compute_source == 'GPU' ? 'CPU/GPU' : task.compute_source; | |||
item.activeName = 'configInfo-' + task.id; | |||
task.clusterName = getListValueWithKey(CLUSTERS, task.cluster); | |||
task.repoOwnerName = this.repoOwnerName; | |||
task.repoName = this.repoName; | |||
task.jobLink = `/${this.repoOwnerName}/${this.repoName}/${getAiJobLink(task)}`; | |||
task.createdFromNow = timeSinceUnix(task.created_unix, Date.now() / 1000); | |||
task.createTimeStr = formatDate(new Date(task.created_unix * 1000), 'yyyy-MM-dd HH:mm:ss'); | |||
cloudBrainTools.checkOperation(task); | |||
}); | |||
const configs = getDetailPageConfigs(appName) || {}; | |||
this.pageCfg = configs; | |||
const tabs = this.pageCfg.tabs || []; | |||
const tabsName = tabs.map(item => item.name); | |||
const tabConfigs = {}; | |||
tabs.forEach(item => { | |||
tabConfigs[item.name] = item; | |||
}); | |||
this.tabNameList = tabsName; | |||
this.tabConfigs = tabConfigs; | |||
this.operationList = this.pageCfg.operations || []; | |||
this.mainData = data; | |||
cloudBrainTools.initRefreshData(this.mainData); | |||
} else { | |||
this.notFound = true; | |||
} | |||
}).catch(err => { | |||
this.loading = false; | |||
this.notFound = true; | |||
console.log(err); | |||
}); | |||
}, | |||
mounted() { }, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
.head-path { | |||
margin-top: -0.14285714em; | |||
margin-bottom: 1rem; | |||
.section { | |||
display: inline-block; | |||
margin: 0; | |||
padding: 0; | |||
color: #4183c4; | |||
line-height: 1.4285em; | |||
font-size: 1rem; | |||
font-weight: 700; | |||
cursor: pointer; | |||
&.active { | |||
color: rgba(0, 0, 0, .87); | |||
cursor: default; | |||
} | |||
&:hover { | |||
&:not(.active) { | |||
color: #1e70bf; | |||
} | |||
} | |||
} | |||
.divider { | |||
display: inline-block; | |||
opacity: .7; | |||
margin: 0 0.21428571rem 0; | |||
font-size: .92857143em; | |||
color: rgba(0, 0, 0, .4); | |||
vertical-align: baseline; | |||
} | |||
} | |||
.body-content { | |||
.collapse-item { | |||
border: 1px solid #dfe1e6; | |||
margin-top: -1px; | |||
/deep/ div[role="tab"] { | |||
div[role="button"] { | |||
height: 40px; | |||
box-sizing: border-box; | |||
padding: 8px 16px; | |||
color: #252b3a; | |||
background-color: #f2f5fc; | |||
line-height: 1.5; | |||
cursor: default; | |||
position: relative; | |||
.title { | |||
height: 100%; | |||
width: 100%; | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
.title-l { | |||
display: flex; | |||
align-items: center; | |||
cursor: default; | |||
font-size: 12px; | |||
padding-left: 18px; | |||
.task-create-time { | |||
margin-right: 12px; | |||
} | |||
.task-status { | |||
display: flex; | |||
align-items: center; | |||
margin-right: 12px; | |||
i { | |||
margin-right: 4px; | |||
} | |||
} | |||
.task-duration { | |||
display: flex; | |||
align-items: center; | |||
margin-right: 6px; | |||
} | |||
.task-refresh { | |||
display: flex; | |||
align-items: center; | |||
i { | |||
font-size: 14px; | |||
font-weight: 600; | |||
color: #3291F8; | |||
cursor: pointer; | |||
} | |||
} | |||
} | |||
.title-r { | |||
display: flex; | |||
align-items: center; | |||
.ops-btn { | |||
margin-right: 10px; | |||
padding-right: 11px; | |||
font-size: 13px; | |||
border-right: 1px solid #dfe1e6; | |||
line-height: 14px; | |||
&:last-child { | |||
border-right: none; | |||
padding-right: 0; | |||
margin-right: 0; | |||
} | |||
&.btn-disabled { | |||
cursor: not-allowed; | |||
opacity: 0.45 !important; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
.el-icon-arrow-right { | |||
position: absolute; | |||
margin-top: -2px; | |||
font-size: 13px; | |||
&::before { | |||
content: "\e791"; | |||
cursor: pointer; | |||
} | |||
} | |||
} | |||
/deep/ div.el-collapse-item__wrap[role="tabpanel"] { | |||
padding: 15px 35px 5px; | |||
.el-collapse-item__content { | |||
padding-bottom: 0; | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,17 @@ | |||
import Vue from 'vue'; | |||
import ElementUI from 'element-ui'; | |||
import 'element-ui/lib/theme-chalk/index.css'; | |||
import localeEn from 'element-ui/lib/locale/lang/en'; | |||
import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||
import { i18n, lang } from '~/langs'; | |||
import App from './index.vue'; | |||
Vue.use(ElementUI, { | |||
locale: lang === 'zh-CN' ? localeZh : localeEn, | |||
size: 'small', | |||
}); | |||
new Vue({ | |||
i18n, | |||
render: (h) => h(App), | |||
}).$mount('#__vue-root'); |
@@ -0,0 +1,559 @@ | |||
<template> | |||
<div> | |||
<div class="ui container"> | |||
<div class="header"> | |||
<div class="tab-c"> | |||
<a class="tab-item" :href="`/${repoOwnerName}/${repoName}/${item.url}`" :key="item.key" | |||
:class="item.type == curTab ? 'focus' : ''" v-for="item in tabs"> | |||
<span>{{ item.label }}</span> | |||
</a> | |||
</div> | |||
<div class="right-c"></div> | |||
</div> | |||
<div v-if="tableData.length > 0"> | |||
<div class="list-body table-container"> | |||
<el-table :data="tableData" style="min-width:100%" v-loading="loading" stripe> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('taskName') >= 0" :label="$t('cloudbrainObj.taskName')" | |||
align="left" header-align="left" min-width="250"> | |||
<template slot-scope="scope"> | |||
<a class="dispaly-job-name" :href="scope.row.task.jobLink"> | |||
{{ scope.row.task.display_job_name }} | |||
</a> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('status') >= 0" prop="Status" :label="$t('status')" | |||
align="left" header-align="left" min-width="120"> | |||
<template slot-scope="scope"> | |||
<div class="status-wrap"> | |||
<i :class="scope.row.task.status"></i> | |||
<span>{{ scope.row.task.status }}</span> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('appName') >= 0" prop="job_type" | |||
:label="$t('cloudbrainObj.appName')" align="center" header-align="center" min-width="120"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.app_name }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('createTime') >= 0" prop="created_unix" | |||
:label="$t('cloudbrainObj.createTime')" align="center" header-align="center" min-width="120"> | |||
<template slot-scope="scope"> | |||
<el-tooltip effect="dark" :content="dateFormat(scope.row.task.created_unix)" placement="top-start"> | |||
<span>{{ scope.row.task.createdFromNow }}</span> | |||
</el-tooltip> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('runDuration') >= 0" prop="formatted_duration" | |||
:label="$t('cloudbrainObj.runDuration')" align="center" header-align="center" min-width="120"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.formatted_duration }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('clusterAndComputeResource') >= 0" | |||
:label="$t('cloudbrainObj.clusterAndComputeResource')" align="center" header-align="center" min-width="150"> | |||
<template slot-scope="scope"> | |||
<span>{{ scope.row.task.clusterName }} {{ scope.row.task.computeSourceShow }}</span> | |||
</template> | |||
</el-table-column> | |||
<el-table-column v-if="pageCfg.page.columns.indexOf('creator') >= 0" prop="remark" | |||
:label="$t('modelManage.creator')" align="left" min-width="80" header-align="center"> | |||
<template slot-scope="scope"> | |||
<div class="creator-wrap"> | |||
<a :href="'/' + scope.row.creator.name" :title="scope.row.creator.full_name"> | |||
<img :src="scope.row.creator.rel_avatar_link"> | |||
</a> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column prop="remark" :label="$t('operation')" align="left" min-width="300" header-align="center"> | |||
<template slot-scope="scope"> | |||
<div class="op-wrap"> | |||
<a href="javascript:;" | |||
v-if="pageCfg.page.operations.indexOf('start') >= 0 && scope.row.can_modify && scope.row.task.canDebug" | |||
@click="opDebug(scope.row)" | |||
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.startUse') | |||
}}</a> | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('stop') >= 0" @click="opStop(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canStop ? '' : 'disabled'">{{ $t('cloudbrainObj.stop') | |||
}}</a> | |||
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('delete') >= 0" | |||
@click="opDelete(scope.row)" | |||
:class="scope.row.can_delete && scope.row.task.canDelete ? '' : 'disabled'">{{ | |||
$t('cloudbrainObj.delete') }}</a> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
</el-table> | |||
</div> | |||
<div class="list-foot"> | |||
<el-pagination ref="paginationRef" background @current-change="currentChange" @size-change="sizeChange" | |||
:current-page.sync="page" :page-sizes="pageSizes" :page-size.sync="pageSize" | |||
layout="total, sizes, prev, pager, next, jumper" :total="total"> | |||
</el-pagination> | |||
</div> | |||
<div v-if="false" class="foot-tips" v-html="$t('cloudbrainObj.maxTaskTips')"></div> | |||
</div> | |||
<div class="empty-page" v-if="!loading && tableData.length == 0"> | |||
<div class="empty-icon"></div> | |||
<div class="empty-title">{{ pageCfg.page.emptyTitle }}</div> | |||
<div class="empty-content"> | |||
<div v-if="pageCfg.page.emptyTip0 && isRepoEmpty" | |||
v-html="$t('cloudbrainObj.debugTaskEmptyTip0', { url: `/${repoOwnerName}/${repoName}` })"></div> | |||
<div v-if="pageCfg.page.emptyTip1" v-html="pageCfg.page.emptyTip1"></div> | |||
<div v-if="pageCfg.page.emptyTip2" v-html="pageCfg.page.emptyTip2"></div> | |||
<div v-if="pageCfg.page.emptyTip3" v-html="pageCfg.page.emptyTip3"></div> | |||
</div> | |||
</div> | |||
</div> | |||
<LoadingMask :loading="maskLoading" :content="maskLoadingContent"></LoadingMask> | |||
<el-dialog class="task-already-dlg" :visible.sync="taskAlreadyDialogShow" :lock-scroll="false" :show-close="false"> | |||
<div class="err-msg-box-already"> | |||
<div class="msg-content"> | |||
<i class="ri-information-line"></i> | |||
<div class="msg-content-tip"> | |||
<div class="line-1" v-html="$t('cloudbrainObj.sameTaskTips1')"></div> | |||
<div class="line-2" v-html="$t('cloudbrainObj.sameTaskTips2')"></div> | |||
</div> | |||
</div> | |||
</div> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<script> | |||
import LoadingMask from '~/components/cloudbrain/LoadingMask.vue'; | |||
import { ListPageConfigs, getAiJobLink } from '../configs'; | |||
import { TABS } from '../configs'; | |||
import { CloudBrainTools } from '~/pages/cloudbrain/tools'; | |||
import { CLUSTERS } from '~/const'; | |||
import { timeSinceUnix, getListValueWithKey } from '~/utils'; | |||
import { getAiTaskList, getAiTaskDebugUrl, stopAiTask, deleteAiTask } from '~/apis/modules/cloudbrain'; | |||
import relativeTime from 'dayjs/plugin/relativeTime'; | |||
import localizedFormat from 'dayjs/plugin/localizedFormat'; | |||
import 'dayjs/locale/zh-cn'; | |||
import 'dayjs/locale/en'; | |||
import dayjs from 'dayjs'; | |||
import { lang } from '~/langs'; | |||
dayjs.locale(lang == 'zh-CN' ? 'zh-cn' : 'en'); | |||
dayjs.extend(relativeTime); | |||
dayjs.extend(localizedFormat); | |||
const cloudBrainTools = new CloudBrainTools(); | |||
export default { | |||
data() { | |||
return { | |||
curTab: 'task', | |||
tabs: [...TABS], | |||
repoOwnerName: location.pathname.split('/')[1], | |||
repoName: location.pathname.split('/')[2], | |||
isRepoEmpty: false, | |||
sort: '', | |||
pageCfg: { ...ListPageConfigs }, | |||
tableData: [], | |||
page: 1, | |||
pageSizes: [10], | |||
pageSize: 10, | |||
total: 0, | |||
canCreateTask: false, | |||
loading: false, | |||
errorMsgBoxShow: false, | |||
errorMsg: '', | |||
maskLoading: false, | |||
maskLoadingContent: '', | |||
operating: false, | |||
taskAlreadyDialogShow: false, | |||
}; | |||
}, | |||
components: { LoadingMask }, | |||
methods: { | |||
getTableData() { | |||
this.loading = true; | |||
getAiTaskList({ | |||
repoOwnerName: this.repoOwnerName, | |||
repoName: this.repoName, | |||
page: this.page, | |||
page_size: this.pageSize, | |||
job_type: this.pageCfg.page.jobType, | |||
compute_source: this.sort, | |||
}).then(res => { | |||
this.loading = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
const data = res.data; | |||
this.canCreateTask = data.can_create_task; | |||
this.isRepoEmpty = data.is_repo_empty; | |||
this.total = data.total; | |||
data.tasks.forEach(item => { | |||
const obj = Object.assign({}, item); | |||
delete obj.task; | |||
const task = item.task; | |||
Object.assign(task, obj); | |||
task.computeSourceShow = task.compute_source == 'GPU' ? 'CPU/GPU' : task.compute_source; | |||
task.clusterName = getListValueWithKey(CLUSTERS, task.cluster); | |||
task.repoOwnerName = this.repoOwnerName; | |||
task.repoName = this.repoName; | |||
task.jobLink = `/${this.repoOwnerName}/${this.repoName}/${getAiJobLink(task)}`; | |||
task.createdFromNow = this.calcFromNow(task.created_unix); | |||
cloudBrainTools.checkOperation(task); | |||
}); | |||
this.tableData = data.tasks || []; | |||
cloudBrainTools.initRefreshData(this.tableData); | |||
} | |||
}).catch(err => { | |||
this.loading = false; | |||
console.log(err); | |||
}); | |||
}, | |||
changeSort() { | |||
this.page = 1; | |||
this.getTableData(); | |||
}, | |||
currentChange(page) { | |||
this.page = page; | |||
this.getTableData(); | |||
}, | |||
sizeChange(pageSize) { | |||
this.page = 1; | |||
this.pageSize = pageSize; | |||
this.getTableData(); | |||
}, | |||
calcFromNow(unix) { | |||
return timeSinceUnix(unix, Date.now() / 1000); | |||
}, | |||
dateFormat(unix) { | |||
return lang == 'zh-CN' ? dayjs(unix * 1000).format('YYYY年MM月DD日 HH时mm分ss秒') : | |||
dayjs(unix * 1000).format('ddd, D MMM YYYY HH:mm:ss [CST]'); | |||
}, | |||
// operations | |||
opDebug(row) { | |||
if (this.operating) return; | |||
this.operating = true; | |||
getAiTaskDebugUrl({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
if (res.data && res.data.url) { | |||
window.open(res.data.url) | |||
} | |||
} else { | |||
this.$message({ | |||
type: 'error', | |||
message: res.msg, | |||
}); | |||
} | |||
}).catch(err => { | |||
this.operating = false; | |||
console.log(err); | |||
}); | |||
}, | |||
opStop(row) { | |||
if (this.operating) return; | |||
this.operating = true; | |||
stopAiTask({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
res = res.data; | |||
if (res.code == 0) { | |||
const data = res.data; | |||
Object.assign(row.task, data); | |||
row.task.createdFromNow = this.calcFromNow(row.task.created_unix); | |||
cloudBrainTools.checkOperation(row.task); | |||
} else { | |||
this.$message({ | |||
type: 'error', | |||
message: res.msg | |||
}); | |||
} | |||
}).catch(err => { | |||
this.operating = false; | |||
}); | |||
}, | |||
opDelete(row) { | |||
if (this.operating) return; | |||
this.$confirm(this.$t('cloudbrainObj.deleteConfirmTips'), this.$t('tips'), { | |||
confirmButtonText: this.$t('confirm'), | |||
cancelButtonText: this.$t('cancel'), | |||
type: 'warning' | |||
}).then(() => { | |||
this.operating = true; | |||
this.maskLoading = true; | |||
this.maskLoadingContent = this.$t('cloudbrainObj.deletingTips'); | |||
deleteAiTask({ | |||
repoOwnerName: row.task.repoOwnerName, | |||
repoName: row.task.repoName, | |||
id: row.task.id, | |||
}).then(res => { | |||
this.operating = false; | |||
this.maskLoading = false; | |||
if (this.total % this.pageSize == 1 && this.page > 1) { | |||
this.page -= 1; | |||
} | |||
this.getTableData(); | |||
}).catch(err => { | |||
this.maskLoading = false; | |||
this.operating = false; | |||
this.$message({ | |||
type: 'error', | |||
message: this.$t('operationFailed'), | |||
}); | |||
}); | |||
}).catch(() => { | |||
this.$message({ | |||
type: 'info', | |||
message: this.$t('cancelOperate'), | |||
}); | |||
}); | |||
}, | |||
}, | |||
beforeMount() { | |||
// const urlParams = getUrlSearchParams(); | |||
// const configs = getListPageConfigs(location.href) || {}; | |||
// this.pageCfg = configs; | |||
this.getTableData(); | |||
}, | |||
mounted() { }, | |||
beforeDestroy() { }, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
@import '~/components/cloudbrain/cloudbrain.less'; | |||
.container { | |||
min-height: 350px; | |||
} | |||
.header { | |||
margin-bottom: 26px; | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
.tab-c { | |||
display: flex; | |||
align-items: center; | |||
.tab-item { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
font-size: 13px; | |||
color: rgba(0, 0, 0, .87); | |||
border: 1px solid rgba(34, 36, 38, .15); | |||
margin-left: -1px; | |||
height: 38px; | |||
padding: 0 12px; | |||
border-left: none; | |||
&.focus { | |||
color: #0087f5; | |||
border-color: #0087f5; | |||
border-left: 1px solid #0087f5; | |||
} | |||
&:first-child { | |||
border-radius: 0.28571429rem 0 0 0.28571429rem; | |||
border-left: 1px solid rgba(34, 36, 38, .15); | |||
&.focus { | |||
border-color: #0087f5; | |||
} | |||
} | |||
&:last-child { | |||
border-radius: 0 0.28571429rem 0.28571429rem 0; | |||
} | |||
&:hover:not(.focus) { | |||
background: rgba(0, 0, 0, .03); | |||
} | |||
} | |||
} | |||
.right-c { | |||
display: flex; | |||
align-items: center; | |||
} | |||
} | |||
.table-container { | |||
/deep/ .el-table__body { | |||
td { | |||
height: 64px; | |||
} | |||
} | |||
.dispaly-job-name { | |||
font-size: 14px; | |||
// padding-left: 10px; | |||
font-weight: bold; | |||
} | |||
.status-wrap { | |||
display: flex; | |||
align-items: center; | |||
i { | |||
margin-right: 4px; | |||
} | |||
} | |||
.creator-wrap { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
img { | |||
height: 28px; | |||
width: 28px; | |||
border-radius: 100%; | |||
} | |||
} | |||
.op-wrap { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
a { | |||
margin: 0 10px; | |||
font-size: 14px; | |||
color: #1678c2; | |||
&.disabled { | |||
color: rgba(0, 0, 0, .87); | |||
} | |||
} | |||
.el-dropdown { | |||
margin: 0 10px; | |||
color: rgba(0, 0, 0, .87); | |||
cursor: pointer; | |||
} | |||
} | |||
} | |||
.list-foot { | |||
text-align: center; | |||
margin-top: 12px; | |||
} | |||
.foot-tips { | |||
margin-top: 2rem; | |||
color: #888888; | |||
font-size: 14px; | |||
/deep/ span { | |||
color: #f2711c; | |||
} | |||
} | |||
/deep/ .el-dropdown-menu__item { | |||
a { | |||
color: #1678c2; | |||
} | |||
&.is-disabled { | |||
color: rgba(0, 0, 0, .87); | |||
pointer-events: none; | |||
opacity: 0.45 !important; | |||
a { | |||
color: rgba(0, 0, 0, .87); | |||
pointer-events: none; | |||
opacity: 0.45 !important; | |||
} | |||
} | |||
} | |||
.empty-page { | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
.empty-icon { | |||
height: 100px; | |||
width: 100px; | |||
background: url(/img/empty-box.svg) center center no-repeat; | |||
margin: 2rem 0 1rem; | |||
scale: 0.8; | |||
} | |||
.empty-title { | |||
text-align: center; | |||
color: #3f3f40; | |||
font-size: 18px; | |||
margin-bottom: 1rem; | |||
} | |||
.empty-content { | |||
margin: 2rem 0 0; | |||
div { | |||
font-size: 14px; | |||
color: #a6a6a6; | |||
line-height: 22px; | |||
margin-bottom: 4px; | |||
} | |||
} | |||
} | |||
.task-already-dlg { | |||
margin-top: 15vh; | |||
/deep/.el-dialog__header { | |||
display: none; | |||
} | |||
/deep/.el-dialog__body { | |||
padding: 0px 0px; | |||
} | |||
} | |||
.err-msg-box-already { | |||
padding: 1em 1.5em; | |||
background-color: rgba(242, 113, 28, 0.05); | |||
border: 2px solid rgba(242, 113, 28, 1); | |||
border-radius: 5px; | |||
.msg-content { | |||
display: flex; | |||
align-items: center; | |||
i { | |||
font-size: 35px; | |||
color: rgba(242, 113, 28, 1); | |||
} | |||
.msg-content-tip { | |||
text-align: left; | |||
margin-left: 1rem; | |||
.line-1 { | |||
font-weight: 600; | |||
line-height: 2; | |||
span { | |||
color: rgba(242, 113, 28, 1); | |||
} | |||
} | |||
.line-2 { | |||
color: #939393 | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,17 @@ | |||
import Vue from 'vue'; | |||
import ElementUI from 'element-ui'; | |||
import 'element-ui/lib/theme-chalk/index.css'; | |||
import localeEn from 'element-ui/lib/locale/lang/en'; | |||
import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||
import { i18n, lang } from '~/langs'; | |||
import App from './index.vue'; | |||
Vue.use(ElementUI, { | |||
locale: lang === 'zh-CN' ? localeZh : localeEn, | |||
size: 'small', | |||
}); | |||
new Vue({ | |||
i18n, | |||
render: (h) => h(App), | |||
}).$mount('#__vue-root'); |
@@ -34,10 +34,11 @@ export const transFileSize = (srcSize) => { | |||
export const renderSpecStr = (spec, showPoint) => { | |||
if (!spec) return ''; | |||
var ngpu = `${spec.ComputeResource}: ${spec.AccCardsNum + '*' + getListValueWithKey(ACC_CARD_TYPE, spec.AccCardType)}`; | |||
var gpuMemStr = spec.GPUMemGiB != 0 ? `${i18n.t('resourcesManagement.gpuMem')}: ${spec.GPUMemGiB}GB, ` : ''; | |||
var gpuMemStr = spec.GPUMemGiB != 0 ? `, ${i18n.t('resourcesManagement.gpuMem')}: ${spec.GPUMemGiB}GB, ` : ''; | |||
var memStr = spec.MemGiB != 0 ? `, ${i18n.t('resourcesManagement.mem')}: ${spec.MemGiB}GB` : ''; | |||
var sharedMemStr = spec.ShareMemGiB != 0 ? `, ${i18n.t('resourcesManagement.shareMem')}: ${spec.ShareMemGiB}GB` : ''; | |||
var pointStr = showPoint ? `, ${spec.UnitPrice == 0 ? i18n.t('resourcesManagement.free') : spec.UnitPrice + i18n.t('resourcesManagement.point_hr')}` : ''; | |||
var specStr = `${ngpu}, CPU: ${spec.CpuCores}, ${gpuMemStr}${i18n.t('resourcesManagement.mem')}: ${spec.MemGiB}GB${sharedMemStr}${pointStr}`; | |||
var specStr = `${ngpu}, CPU: ${spec.CpuCores}${gpuMemStr}${memStr}${sharedMemStr}${pointStr}`; | |||
return specStr; | |||
}; | |||
@@ -50,10 +51,11 @@ export const renderSpecObject = (spec, showPoint) => { | |||
}; | |||
} | |||
var ngpu = `${spec.compute_resource}: ${spec.acc_cards_num + '*' + getListValueWithKey(ACC_CARD_TYPE, spec.acc_card_type)}`; | |||
var gpuMemStr = spec.gpu_mem_gi_b != 0 ? `${i18n.t('resourcesManagement.gpuMem')}: ${spec.gpu_mem_gi_b}GB, ` : ''; | |||
var gpuMemStr = spec.gpu_mem_gi_b != 0 ? `, ${i18n.t('resourcesManagement.gpuMem')}: ${spec.gpu_mem_gi_b}GB` : ''; | |||
var memStr = spec.mem_gi_b != 0 ? `, ${i18n.t('resourcesManagement.mem')}: ${spec.mem_gi_b}GB` : ''; | |||
var sharedMemStr = spec.share_mem_gi_b != 0 ? `, ${i18n.t('resourcesManagement.shareMem')}: ${spec.share_mem_gi_b}GB` : ''; | |||
var pointStr = showPoint ? `${spec.unit_price == 0 ? i18n.t('resourcesManagement.free') : spec.unit_price + i18n.t('resourcesManagement.point_hr')}` : ''; | |||
var specStr = `${ngpu}, CPU: ${spec.cpu_cores}, ${gpuMemStr}${i18n.t('resourcesManagement.mem')}: ${spec.mem_gi_b}GB${sharedMemStr}`; | |||
var specStr = `${ngpu}, CPU: ${spec.cpu_cores}${gpuMemStr}${memStr}${sharedMemStr}`; | |||
return { | |||
...spec, | |||
id: spec.id.toString(), | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》