diff --git a/models/ai_model_manage.go b/models/ai_model_manage.go index a88da8fe5..d9adda2dc 100644 --- a/models/ai_model_manage.go +++ b/models/ai_model_manage.go @@ -88,7 +88,7 @@ type AiModelQueryOptions struct { } func (a *AiModelConvert) IsGpuTrainTask() bool { - if a.SrcEngine == 0 || a.SrcEngine == 1 { + if a.SrcEngine == 0 || a.SrcEngine == 1 || a.SrcEngine == 4 || a.SrcEngine == 6 { return true } return false diff --git a/models/cloudbrain.go b/models/cloudbrain.go index 6135dac40..989d0905b 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -1070,6 +1070,12 @@ type CreateInferenceJobParams struct { InfConfig InfConfig `json:"config"` WorkspaceID string `json:"workspace_id"` } +type CreateInfUserImageParams struct { + JobName string `json:"job_name"` + Description string `json:"job_desc"` + Config InfUserImageConfig `json:"config"` + WorkspaceID string `json:"workspace_id"` +} type InfConfig struct { WorkServerNum int `json:"worker_server_num"` @@ -1084,6 +1090,21 @@ type InfConfig struct { PoolID string `json:"pool_id"` } +type InfUserImageConfig struct { + WorkServerNum int `json:"worker_server_num"` + AppUrl string `json:"app_url"` //训练作业的代码目录 + BootFileUrl string `json:"boot_file_url"` //训练作业的代码启动文件,需要在代码目录下 + Parameter []Parameter `json:"parameter"` + DataUrl string `json:"data_url"` //训练作业需要的数据集OBS路径URL + EngineID int64 `json:"engine_id"` + LogUrl string `json:"log_url"` + CreateVersion bool `json:"create_version"` + Flavor Flavor `json:"flavor"` + PoolID string `json:"pool_id"` + UserImageUrl string `json:"user_image_url"` + UserCommand string `json:"user_command"` +} + type CreateTrainJobVersionParams struct { Description string `json:"job_desc"` Config TrainJobVersionConfig `json:"config"` @@ -2015,11 +2036,6 @@ func GetModelSafetyTestTask() ([]*Cloudbrain, error) { return cloudbrains, err } -func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) { - count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ? and type = ?", jobType, userID, TypeCloudBrainOne).Count(new(Cloudbrain)) - return int(count), err -} - func GetCloudbrainRunCountByRepoID(repoID int64) (int, error) { count, err := x.In("status", JobWaiting, JobRunning, ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsDeleting, ModelArtsRestarting, ModelArtsTrainJobInit, @@ -2028,13 +2044,8 @@ func GetCloudbrainRunCountByRepoID(repoID int64) (int, error) { return int(count), err } -func GetBenchmarkCountByUserID(userID int64) (int, error) { - count, err := x.In("status", JobWaiting, JobRunning).And("(job_type = ? or job_type = ? or job_type = ?) and user_id = ? and type = ?", string(JobTypeBenchmark), string(JobTypeModelSafety), string(JobTypeBrainScore), string(JobTypeSnn4imagenet), userID, TypeCloudBrainOne).Count(new(Cloudbrain)) - return int(count), err -} - func GetModelSafetyCountByUserID(userID int64) (int, error) { - count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ?", string(JobTypeModelSafety), userID).Count(new(Cloudbrain)) + count, err := x.In("status", JobWaiting, JobRunning, ModelArtsTrainJobInit, ModelArtsTrainJobImageCreating, ModelArtsTrainJobSubmitTrying, ModelArtsTrainJobScaling, ModelArtsTrainJobCheckInit, ModelArtsTrainJobCheckRunning, ModelArtsTrainJobCheckRunningCompleted).And("job_type = ? and user_id = ?", string(JobTypeModelSafety), userID).Count(new(Cloudbrain)) return int(count), err } @@ -2048,40 +2059,14 @@ func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTy } return sess.Count(new(Cloudbrain)) } - -func GetCloudbrainNotebookCountByUserID(userID int64) (int, error) { - count, err := x.In("status", ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting). - And("job_type = ? and user_id = ? and type in (?,?)", JobTypeDebug, userID, TypeCloudBrainTwo, TypeCDCenter).Count(new(Cloudbrain)) - return int(count), err -} - -func GetCloudbrainTrainJobCountByUserID(userID int64) (int, error) { - count, err := x.In("status", ModelArtsTrainJobInit, ModelArtsTrainJobImageCreating, ModelArtsTrainJobSubmitTrying, ModelArtsTrainJobWaiting, ModelArtsTrainJobRunning, ModelArtsTrainJobScaling, ModelArtsTrainJobCheckInit, ModelArtsTrainJobCheckRunning, ModelArtsTrainJobCheckRunningCompleted). - And("job_type = ? and user_id = ? and type = ?", JobTypeTrain, userID, TypeCloudBrainTwo).Count(new(Cloudbrain)) - return int(count), err -} - -func GetCloudbrainInferenceJobCountByUserID(userID int64) (int, error) { - count, err := x.In("status", ModelArtsTrainJobInit, ModelArtsTrainJobImageCreating, ModelArtsTrainJobSubmitTrying, ModelArtsTrainJobWaiting, ModelArtsTrainJobRunning, ModelArtsTrainJobScaling, ModelArtsTrainJobCheckInit, ModelArtsTrainJobCheckRunning, ModelArtsTrainJobCheckRunningCompleted). - And("job_type = ? and user_id = ? and type = ?", JobTypeInference, userID, TypeCloudBrainTwo).Count(new(Cloudbrain)) +func GetNotFinalStatusTaskCount(userID int64, notFinalStatus []string, jobTypes []JobType, cloudbrainTypes []int, computeResource string) (int, error) { + count, err := x.In("status", notFinalStatus). + In("job_type", jobTypes). + In("type", cloudbrainTypes). + And("user_id = ? and compute_resource = ?", userID, computeResource).Count(new(Cloudbrain)) return int(count), err } -func GetGrampusCountByUserID(userID int64, jobType, computeResource string) (int, error) { - count, err := x.In("status", GrampusStatusWaiting, GrampusStatusRunning).And("job_type = ? and user_id = ? and type = ?", jobType, userID, TypeC2Net).And("compute_resource = ?", computeResource).Count(new(Cloudbrain)) - return int(count), err -} - -func UpdateInferenceJob(job *Cloudbrain) error { - return updateInferenceJob(x, job) -} - -func updateInferenceJob(e Engine, job *Cloudbrain) error { - var sess *xorm.Session - sess = e.Where("job_id = ?", job.JobID) - _, err := sess.Cols("status", "train_job_duration", "duration", "start_time", "end_time", "created_unix").Update(job) - return err -} func RestartCloudbrain(old *Cloudbrain, new *Cloudbrain) (err error) { sess := x.NewSession() defer sess.Close() @@ -2296,9 +2281,9 @@ func CloudbrainAllStatic(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, er } sess.Limit(opts.PageSize, start) } - sess.OrderBy("cloudbrain.created_unix DESC") + // sess.OrderBy("cloudbrain.created_unix DESC") cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) - if err := sess.Table(&Cloudbrain{}).Unscoped().Where(cond). + if err := sess.Cols("status", "type", "job_type", "train_job_duration", "duration", "compute_resource", "created_unix", "start_time", "end_time", "work_server_number").Table(&Cloudbrain{}).Unscoped().Where(cond). Find(&cloudbrains); err != nil { return nil, 0, fmt.Errorf("Find: %v", err) } @@ -2411,97 +2396,6 @@ var ( CloudbrainSpecialGpuInfosMap map[string]*GpuInfo ) -func InitCloudbrainOneResourceSpecMap() { - if CloudbrainDebugResourceSpecsMap == nil || len(CloudbrainDebugResourceSpecsMap) == 0 { - t := ResourceSpecs{} - json.Unmarshal([]byte(setting.ResourceSpecs), &t) - CloudbrainDebugResourceSpecsMap = make(map[int]*ResourceSpec, len(t.ResourceSpec)) - for _, spec := range t.ResourceSpec { - CloudbrainDebugResourceSpecsMap[spec.Id] = spec - } - } - if CloudbrainTrainResourceSpecsMap == nil || len(CloudbrainTrainResourceSpecsMap) == 0 { - t := ResourceSpecs{} - json.Unmarshal([]byte(setting.TrainResourceSpecs), &t) - CloudbrainTrainResourceSpecsMap = make(map[int]*ResourceSpec, len(t.ResourceSpec)) - for _, spec := range t.ResourceSpec { - CloudbrainTrainResourceSpecsMap[spec.Id] = spec - } - } - if CloudbrainInferenceResourceSpecsMap == nil || len(CloudbrainInferenceResourceSpecsMap) == 0 { - t := ResourceSpecs{} - json.Unmarshal([]byte(setting.InferenceResourceSpecs), &t) - CloudbrainInferenceResourceSpecsMap = make(map[int]*ResourceSpec, len(t.ResourceSpec)) - for _, spec := range t.ResourceSpec { - CloudbrainInferenceResourceSpecsMap[spec.Id] = spec - } - } - if CloudbrainBenchmarkResourceSpecsMap == nil || len(CloudbrainBenchmarkResourceSpecsMap) == 0 { - t := ResourceSpecs{} - json.Unmarshal([]byte(setting.BenchmarkResourceSpecs), &t) - CloudbrainBenchmarkResourceSpecsMap = make(map[int]*ResourceSpec, len(t.ResourceSpec)) - for _, spec := range t.ResourceSpec { - CloudbrainBenchmarkResourceSpecsMap[spec.Id] = spec - } - } - if CloudbrainSpecialResourceSpecsMap == nil || len(CloudbrainSpecialResourceSpecsMap) == 0 { - t := SpecialPools{} - json.Unmarshal([]byte(setting.SpecialPools), &t) - for _, pool := range t.Pools { - CloudbrainSpecialResourceSpecsMap = make(map[int]*ResourceSpec, len(pool.ResourceSpec)) - for _, spec := range pool.ResourceSpec { - CloudbrainSpecialResourceSpecsMap[spec.Id] = spec - } - } - } - SpecsMapInitFlag = true -} - -func InitCloudbrainOneGpuInfoMap() { - if CloudbrainDebugGpuInfosMap == nil || len(CloudbrainDebugGpuInfosMap) == 0 { - t := GpuInfos{} - json.Unmarshal([]byte(setting.GpuTypes), &t) - CloudbrainDebugGpuInfosMap = make(map[string]*GpuInfo, len(t.GpuInfo)) - for _, GpuInfo := range t.GpuInfo { - CloudbrainDebugGpuInfosMap[GpuInfo.Queue] = GpuInfo - } - } - if CloudbrainTrainGpuInfosMap == nil || len(CloudbrainTrainGpuInfosMap) == 0 { - t := GpuInfos{} - json.Unmarshal([]byte(setting.TrainGpuTypes), &t) - CloudbrainTrainGpuInfosMap = make(map[string]*GpuInfo, len(t.GpuInfo)) - for _, GpuInfo := range t.GpuInfo { - CloudbrainTrainGpuInfosMap[GpuInfo.Queue] = GpuInfo - } - } - if CloudbrainInferenceGpuInfosMap == nil || len(CloudbrainInferenceGpuInfosMap) == 0 { - t := GpuInfos{} - json.Unmarshal([]byte(setting.InferenceGpuTypes), &t) - CloudbrainInferenceGpuInfosMap = make(map[string]*GpuInfo, len(t.GpuInfo)) - for _, GpuInfo := range t.GpuInfo { - CloudbrainInferenceGpuInfosMap[GpuInfo.Queue] = GpuInfo - } - } - if CloudbrainBenchmarkGpuInfosMap == nil || len(CloudbrainBenchmarkGpuInfosMap) == 0 { - t := GpuInfos{} - json.Unmarshal([]byte(setting.BenchmarkGpuTypes), &t) - CloudbrainBenchmarkGpuInfosMap = make(map[string]*GpuInfo, len(t.GpuInfo)) - for _, GpuInfo := range t.GpuInfo { - CloudbrainBenchmarkGpuInfosMap[GpuInfo.Queue] = GpuInfo - } - } - if CloudbrainSpecialGpuInfosMap == nil || len(CloudbrainSpecialGpuInfosMap) == 0 { - t := SpecialPools{} - json.Unmarshal([]byte(setting.SpecialPools), &t) - for _, pool := range t.Pools { - CloudbrainSpecialGpuInfosMap = make(map[string]*GpuInfo, len(pool.Pool)) - for _, GpuInfo := range pool.Pool { - CloudbrainSpecialGpuInfosMap[GpuInfo.Queue] = GpuInfo - } - } - } - GpuInfosMapInitFlag = true -} func GetNewestJobsByAiCenter() ([]int64, error) { ids := make([]int64, 0) return ids, x. diff --git a/models/cloudbrain_spec.go b/models/cloudbrain_spec.go index c32e4b0fd..49a4d603e 100644 --- a/models/cloudbrain_spec.go +++ b/models/cloudbrain_spec.go @@ -9,7 +9,7 @@ type CloudbrainSpec struct { SpecId int64 `xorm:"index"` SourceSpecId string AccCardsNum int - AccCardType string + AccCardType string `xorm:"index"` CpuCores int MemGiB float32 GPUMemGiB float32 @@ -19,7 +19,7 @@ type CloudbrainSpec struct { QueueId int64 QueueCode string Cluster string - AiCenterCode string + AiCenterCode string `xorm:"index"` AiCenterName string IsExclusive bool ExclusiveOrg string diff --git a/models/cloudbrain_static.go b/models/cloudbrain_static.go index 48df111a0..19e55fb6d 100644 --- a/models/cloudbrain_static.go +++ b/models/cloudbrain_static.go @@ -1,6 +1,7 @@ package models import ( + "fmt" "strconv" "time" @@ -38,6 +39,60 @@ type TaskDetail struct { Spec *Specification `json:"Spec"` } +type CloudbrainDurationStatistic struct { + ID int64 `xorm:"pk autoincr"` + Cluster string + AiCenterCode string + AiCenterName string + ComputeResource string + AccCardType string + + DateTime string + DayTime string + HourTime int + CardsUseDuration int + CardsTotalDuration int + CardsTotalNum int + + DeletedUnix timeutil.TimeStamp `xorm:"deleted"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` +} +type DurationStatisticOptions struct { + BeginTime time.Time + EndTime time.Time + AiCenterCode string +} + +type DurationRateStatistic struct { + AiCenterTotalDurationStat map[string]int `json:"aiCenterTotalDurationStat"` + AiCenterUsageDurationStat map[string]int `json:"aiCenterUsageDurationStat"` + UsageRate map[string]float64 `json:"UsageRate"` +} +type ResourceDetail struct { + QueueCode string + Cluster string `xorm:"notnull"` + AiCenterCode string + AiCenterName string + ComputeResource string + AccCardType string + CardsTotalNum int + IsAutomaticSync bool +} + +type DateUsageStatistic struct { + Date string `json:"date"` + UsageDuration int `json:"usageDuration"` + TotalDuration int `json:"totalDuration"` + UsageRate float64 `json:"usageRate"` +} + +type HourTimeStatistic struct { + HourTimeUsageDuration map[string]int `json:"hourTimeUsageDuration"` + HourTimeTotalDuration map[string]int `json:"hourTimeTotalDuration"` + HourTimeUsageRate map[string]float64 `json:"hourTimeUsageRate"` +} + func GetTodayCreatorCount(beginTime time.Time, endTime time.Time) (int64, error) { countSql := "SELECT count(distinct user_id) FROM " + "public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + @@ -199,3 +254,121 @@ func GetRunHourPeriodCount(dateBeginTime string, dateEndTime string) (map[string } return dateHourMap, nil } + +func GetCloudbrainRunning() ([]*CloudbrainInfo, error) { + sess := x.NewSession() + defer sess.Close() + var cond = builder.NewCond() + cond = cond.And( + builder.Eq{"cloudbrain.status": string(JobRunning)}, + ) + sess.OrderBy("cloudbrain.created_unix ASC") + cloudbrains := make([]*CloudbrainInfo, 0, 10) + if err := sess.Table(&Cloudbrain{}).Where(cond). + Find(&cloudbrains); err != nil { + log.Info("find error.") + } + return cloudbrains, nil +} + +func GetCloudbrainByTime(beginTime int64, endTime int64) ([]*CloudbrainInfo, error) { + sess := x.NewSession() + defer sess.Close() + var cond = builder.NewCond() + cond = cond.And( + builder.And(builder.Gte{"cloudbrain.end_time": beginTime}, builder.Lte{"cloudbrain.end_time": endTime}), + ) + cond = cond.Or( + builder.Eq{"cloudbrain.status": string(JobRunning)}, + ) + sess.OrderBy("cloudbrain.created_unix ASC") + cloudbrains := make([]*CloudbrainInfo, 0, 10) + if err := sess.Table(&Cloudbrain{}).Unscoped().Where(cond). + Find(&cloudbrains); err != nil { + log.Info("find error.") + } + return cloudbrains, nil +} + +func GetSpecByAiCenterCodeAndType(aiCenterCode string, accCardType string) ([]*CloudbrainSpec, error) { + sess := x.NewSession() + defer sess.Close() + var cond = builder.NewCond() + cond = cond.And( + builder.And(builder.Eq{"cloudbrain_spec.ai_center_code": aiCenterCode}, builder.Eq{"cloudbrain_spec.acc_card_type": accCardType}), + ) + cloudbrainSpecs := make([]*CloudbrainSpec, 0, 10) + if err := sess.Table(&CloudbrainSpec{}).Where(cond). + Find(&cloudbrainSpecs); err != nil { + log.Info("find error.") + } + return cloudbrainSpecs, nil +} + +func InsertCloudbrainDurationStatistic(cloudbrainDurationStatistic *CloudbrainDurationStatistic) (int64, error) { + return xStatistic.Insert(cloudbrainDurationStatistic) +} + +func DeleteCloudbrainDurationStatisticHour(date string, hour int, aiCenterCode string, accCardType string) error { + sess := xStatistic.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return fmt.Errorf("Begin: %v", err) + } + + if _, err := sess.Where("day_time = ? AND hour_time = ? AND ai_center_code = ? AND acc_card_type = ?", date, hour, aiCenterCode, accCardType).Delete(&CloudbrainDurationStatistic{}); err != nil { + return fmt.Errorf("Delete: %v", err) + } + + if err := sess.Commit(); err != nil { + sess.Close() + return fmt.Errorf("Commit: %v", err) + } + + sess.Close() + return nil +} + +func GetCanUseCardInfo() ([]*ResourceQueue, error) { + sess := x.NewSession() + defer sess.Close() + sess.OrderBy("resource_queue.id ASC") + ResourceQueues := make([]*ResourceQueue, 0, 10) + if err := sess.Table(&ResourceQueue{}).Find(&ResourceQueues); err != nil { + log.Info("find error.") + } + return ResourceQueues, nil +} + +func GetCardDurationStatistics(opts *DurationStatisticOptions) ([]*CloudbrainDurationStatistic, error) { + sess := xStatistic.NewSession() + defer sess.Close() + var cond = builder.NewCond() + if opts.BeginTime.Unix() > 0 && opts.EndTime.Unix() > 0 { + cond = cond.And( + builder.And(builder.Gte{"cloudbrain_duration_statistic.created_unix": opts.BeginTime.Unix()}, builder.Lte{"cloudbrain_duration_statistic.created_unix": opts.EndTime.Unix()}), + ) + } + if opts.AiCenterCode != "" { + cond = cond.And( + builder.Eq{"cloudbrain_duration_statistic.ai_center_code": opts.AiCenterCode}, + ) + } + CloudbrainDurationStatistics := make([]*CloudbrainDurationStatistic, 0, 10) + if err := sess.Table(&CloudbrainDurationStatistic{}).Where(cond). + Find(&CloudbrainDurationStatistics); err != nil { + log.Info("find error.") + } + return CloudbrainDurationStatistics, nil +} + +func GetDurationRecordBeginTime() ([]*CloudbrainDurationStatistic, error) { + sess := xStatistic.NewSession() + defer sess.Close() + sess.OrderBy("cloudbrain_duration_statistic.id ASC limit 1") + CloudbrainDurationStatistics := make([]*CloudbrainDurationStatistic, 0) + if err := sess.Table(&CloudbrainDurationStatistic{}).Find(&CloudbrainDurationStatistics); err != nil { + log.Info("find error.") + } + return CloudbrainDurationStatistics, nil +} diff --git a/models/models.go b/models/models.go index ff64bfad2..b2b7a6472 100755 --- a/models/models.go +++ b/models/models.go @@ -183,6 +183,7 @@ func init() { new(UserMetrics), new(UserAnalysisPara), new(Invitation), + new(CloudbrainDurationStatistic), ) gonicNames := []string{"SSL", "UID"} diff --git a/modules/aisafety/resty.go b/modules/aisafety/resty.go index be6468529..ce1fa736e 100644 --- a/modules/aisafety/resty.go +++ b/modules/aisafety/resty.go @@ -10,6 +10,7 @@ import ( "strings" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" "github.com/go-resty/resty/v2" ) @@ -71,8 +72,8 @@ func checkSetting() { } func loginCloudbrain() error { - HOST = "http://221.122.70.196:8081/atp-api" - KEY = "1" + HOST = setting.ModelSafetyTest.HOST + KEY = setting.ModelSafetyTest.KEY return nil } diff --git a/modules/cron/tasks_basic.go b/modules/cron/tasks_basic.go index 8dbc8d1ed..aac4f87c3 100755 --- a/modules/cron/tasks_basic.go +++ b/modules/cron/tasks_basic.go @@ -266,6 +266,17 @@ func registerSyncModelArtsTempJobs() { }) } +func registerHandleCloudbrainDurationStatistic() { + RegisterTaskFatal("handle_cloudbrain_duration_statistic", &BaseConfig{ + Enabled: true, + RunAtStart: false, + Schedule: "1 0 * * * ?", + }, func(ctx context.Context, _ *models.User, _ Config) error { + repo.CloudbrainDurationStatisticHour() + return nil + }) +} + func initBasicTasks() { registerUpdateMirrorTask() registerRepoHealthCheck() @@ -293,4 +304,5 @@ func initBasicTasks() { registerCloudbrainPointDeductTask() registerHandleModelSafetyTask() + registerHandleCloudbrainDurationStatistic() } diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go index 06521993e..567f6d620 100755 --- a/modules/modelarts/modelarts.go +++ b/modules/modelarts/modelarts.go @@ -143,6 +143,8 @@ type GenerateInferenceJobReq struct { Spec *models.Specification DatasetName string JobType string + UserImageUrl string + UserCommand string } type VersionInfo struct { @@ -682,26 +684,51 @@ func GetOutputPathByCount(TotalVersionCount int) (VersionOutputPath string) { func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (err error) { createTime := timeutil.TimeStampNow() - jobResult, err := createInferenceJob(models.CreateInferenceJobParams{ - JobName: req.JobName, - Description: req.Description, - InfConfig: models.InfConfig{ - WorkServerNum: req.WorkServerNumber, - AppUrl: req.CodeObsPath, - BootFileUrl: req.BootFileUrl, - DataUrl: req.DataUrl, - EngineID: req.EngineID, - // TrainUrl: req.TrainUrl, - LogUrl: req.LogUrl, - PoolID: req.PoolID, - CreateVersion: true, - Flavor: models.Flavor{ - Code: req.Spec.SourceSpecId, + var jobResult *models.CreateTrainJobResult + var createErr error + if req.EngineID < 0 { + jobResult, createErr = createInferenceJobUserImage(models.CreateInfUserImageParams{ + JobName: req.JobName, + Description: req.Description, + Config: models.InfUserImageConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + // TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + CreateVersion: true, + Flavor: models.Flavor{ + Code: req.Spec.SourceSpecId, + }, + Parameter: req.Parameters, + UserImageUrl: req.UserImageUrl, + UserCommand: req.UserCommand, }, - Parameter: req.Parameters, - }, - }) - if err != nil { + }) + } else { + jobResult, createErr = createInferenceJob(models.CreateInferenceJobParams{ + JobName: req.JobName, + Description: req.Description, + InfConfig: models.InfConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + EngineID: req.EngineID, + // TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + CreateVersion: true, + Flavor: models.Flavor{ + Code: req.Spec.SourceSpecId, + }, + Parameter: req.Parameters, + }, + }) + } + if createErr != nil { log.Error("createInferenceJob failed: %v", err.Error()) if strings.HasPrefix(err.Error(), UnknownErrorPrefix) { log.Info("(%s)unknown error, set temp status", req.DisplayJobName) diff --git a/modules/modelarts/resty.go b/modules/modelarts/resty.go index fd1c467f3..c38300606 100755 --- a/modules/modelarts/resty.go +++ b/modules/modelarts/resty.go @@ -1197,6 +1197,66 @@ sendjob: return &result, nil } +func createInferenceJobUserImage(createJobParams models.CreateInfUserImageParams) (*models.CreateTrainJobResult, error) { + checkSetting() + client := getRestyClient() + var result models.CreateTrainJobResult + + retry := 0 + +sendjob: + res, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetAuthToken(TOKEN). + SetBody(createJobParams). + SetResult(&result). + Post(HOST + "/v1/" + setting.ProjectID + urlTrainJob) + + if err != nil { + return nil, fmt.Errorf("resty create train-job: %s", err) + } + + req, _ := json.Marshal(createJobParams) + log.Info("%s", req) + + if res.StatusCode() == http.StatusUnauthorized && retry < 1 { + retry++ + _ = getToken() + goto sendjob + } + + if res.StatusCode() != http.StatusOK { + var temp models.ErrorResult + if err = json.Unmarshal([]byte(res.String()), &temp); err != nil { + log.Error("json.Unmarshal failed(%s): %v", res.String(), err.Error()) + return &result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) + } + log.Error("createInferenceJobUserImage failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + bootFileErrorMsg := "Invalid OBS path '" + createJobParams.Config.BootFileUrl + "'." + dataSetErrorMsg := "Invalid OBS path '" + createJobParams.Config.DataUrl + "'." + if temp.ErrorMsg == bootFileErrorMsg { + log.Error("启动文件错误!createInferenceJobUserImage failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + return &result, fmt.Errorf("启动文件错误!") + } + if temp.ErrorMsg == dataSetErrorMsg { + log.Error("数据集错误!createInferenceJobUserImage failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + return &result, fmt.Errorf("数据集错误!") + } + if res.StatusCode() == http.StatusBadGateway { + return &result, fmt.Errorf(UnknownErrorPrefix+"createInferenceJobUserImage failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + } else { + return &result, fmt.Errorf("createInferenceJobUserImage failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + } + } + + if !result.IsSuccess { + log.Error("createInferenceJobUserImage failed(%s): %s", result.ErrorCode, result.ErrorMsg) + return &result, fmt.Errorf("createInferenceJobUserImage failed(%s): %s", result.ErrorCode, result.ErrorMsg) + } + + return &result, nil +} + func createNotebook2(createJobParams models.CreateNotebook2Params) (*models.CreateNotebookResult, error) { checkSetting() client := getRestyClient() diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 2f468c850..052cdd3c5 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -597,6 +597,7 @@ var ( }{} C2NetInfos *C2NetSqInfos + C2NetMapInfo map[string]*C2NetSequenceInfo //elk config ElkUrl string @@ -701,8 +702,12 @@ var ( GPU_PYTORCH_IMAGE string GpuQueue string GPU_TENSORFLOW_IMAGE string + GPU_PADDLE_IMAGE string + GPU_MXNET_IMAGE string NPU_MINDSPORE_16_IMAGE string PytorchOnnxBootFile string + PaddleOnnxBootFile string + MXnetOnnxBootFile string PytorchTrTBootFile string MindsporeBootFile string TensorFlowNpuBootFile string @@ -725,6 +730,9 @@ var ( GPUBaseDataSetUUID string GPUCombatDataSetName string GPUCombatDataSetUUID string + + HOST string + KEY string }{} ModelApp = struct { @@ -1572,6 +1580,8 @@ func getModelSafetyConfig() { ModelSafetyTest.NPUBaseDataSetUUID = sec.Key("NPUBaseDataSetUUID").MustString("") ModelSafetyTest.NPUCombatDataSetName = sec.Key("NPUCombatDataSetName").MustString("") ModelSafetyTest.NPUCombatDataSetUUID = sec.Key("NPUCombatDataSetUUID").MustString("") + ModelSafetyTest.HOST = sec.Key("HOST").MustString("") + ModelSafetyTest.KEY = sec.Key("KEY").MustString("") } func getModelConvertConfig() { @@ -1591,6 +1601,10 @@ func getModelConvertConfig() { ModelConvert.NPU_PoolID = sec.Key("NPU_PoolID").MustString("pool7908321a") ModelConvert.NPU_MINDSPORE_IMAGE_ID = sec.Key("NPU_MINDSPORE_IMAGE_ID").MustInt(121) ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35) + ModelConvert.GPU_PADDLE_IMAGE = sec.Key("GPU_PADDLE_IMAGE").MustString("dockerhub.pcl.ac.cn:5000/user-images/openi:paddle2.3.0_gpu_cuda11.2_cudnn8") + ModelConvert.GPU_MXNET_IMAGE = sec.Key("GPU_MXNET_IMAGE").MustString("dockerhub.pcl.ac.cn:5000/user-images/openi:mxnet191cu_cuda102_py37") + ModelConvert.PaddleOnnxBootFile = sec.Key("PaddleOnnxBootFile").MustString("convert_paddle.py") + ModelConvert.MXnetOnnxBootFile = sec.Key("MXnetOnnxBootFile").MustString("convert_mxnet.py") } func getModelAppConfig() { @@ -1627,6 +1641,10 @@ func getGrampusConfig() { if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { log.Error("Unmarshal(C2NetSequence) failed:%v", err) } + C2NetMapInfo=make(map[string]*C2NetSequenceInfo) + for _,value :=range C2NetInfos.C2NetSqInfo{ + C2NetMapInfo[value.Name]=value + } } Grampus.SyncScriptProject = sec.Key("SYNC_SCRIPT_PROJECT").MustString("script_for_grampus") diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 324930544..f9ed861fa 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -265,8 +265,8 @@ page_dev_yunlao_desc3=China computing power network (C²NET) phase I can realize page_dev_yunlao_desc4=Developers can freely select the corresponding computing resources according to the use needs, and can test the adaptability, performance, stability, etc. of the model in different hardware environments. page_dev_yunlao_desc5=If your model requires more computing resources, you can also apply for it separately. page_dev_yunlao_apply=Apply Separately -c2net_title=China Computing Network -c2net_desc=The artificial intelligence computing power network promotion alliance has access to 11 intelligent computing centers, with a total scale of 1924p. +c2net_title=China Computing NET(C²NET) +c2net_desc=Extensive access to intelligent computing centers, supercomputing centers and big data centers across the country to provide users with free computing resources. c2net_center=Center search=Search search_repo=Repository @@ -289,6 +289,7 @@ provide_resoure = Computing resources of CPU/GPU/NPU are provided freely for var activity = Activity no_events = There are no events related or_t = or +powerdby=Powered_by Pengcheng CloudBrain、China Computing NET(C²NET)、 [explore] repos = Repositories @@ -1216,7 +1217,8 @@ cloudbrain.benchmark.evaluate_train=Train Script cloudbrain.benchmark.evaluate_test=Test Script cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"Target detection","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"Target re-identification","second":[{"id":1,"value":"Vehicle re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"Image-based person re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"Multi-target tracking","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]} cloudbrain.morethanonejob=You already have a running or waiting task, create it after that task is over. - +cloudbrain.morethanonejob1=You have created a similar task that is waiting or running, please wait for the task to finish before creating it. +cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in Personal Center > Cloud Brain Tasks . modelarts.infer_job_model = Model modelarts.infer_job_model_file = Model File @@ -1226,6 +1228,9 @@ modelarts.infer_job.select_model = Select Model modelarts.infer_job.boot_file_helper=The startup file is the entry file for your program execution and must end in.py.Such as inference.py, main.py, example/inference.py, case/main.py. modelarts.infer_job.tooltip = The model has been deleted and cannot be viewed. modelarts.download_log=Download log file +modelarts.log_file = Log file +modelarts.fullscreen_log_file = View in full screen +modelarts.exit_full_screen = Exit fullscreen modelarts.no_node_right = The value of 'Amount of Compute Node' is wrong, you have no right to use the current value of 'Amount of Compute Node'. @@ -3178,7 +3183,7 @@ foot.help = help foot.copyright= Copyright: New Generation Artificial Intelligence Open Source Open Platform (OpenI) Platform_Tutorial = Tutorial foot.advice_feedback = Feedback - +resource_description = Resource Note [cloudbrain] all_resource_cluster=All Cluster all_ai_center=All Computing NET @@ -3217,7 +3222,7 @@ view_sample = View sample inference_output_path_rule = The inference output path is stored in the run parameter result_url. model_file_path_rule=The model file location is stored in the run parameter ckpt_url model_file_postfix_rule = The supported format of the model file is [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt] -model_convert_postfix_rule = The supported format of the model file is [.pth, .pkl, .onnx, .mindir, .ckpt, .pb] +model_convert_postfix_rule = The supported format of the model file is [.pth, .pkl, .onnx, .mindir, .ckpt, .pb, .pdmodel, .pdiparams, .params, .json] delete_task = Delete task task_delete_confirm = Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered. operate_confirm = confirm diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index fd5596a2e..766bd3b85 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -267,8 +267,8 @@ page_dev_yunlao_desc3=中国算力网(C²NET)一期可实现不同人工智 page_dev_yunlao_desc4=开发者可以根据使用需求,自由选择相应计算资源,可以测试模型在不同硬件环境下的适配能力、性能、稳定性等。 page_dev_yunlao_desc5=如果您的模型需要更多的计算资源,也可以单独申请。 page_dev_yunlao_apply=单独申请 -c2net_title=智算网络 -c2net_desc=人工智能算力网络推进联盟已接入11家智算中心,算力总规模1924P +c2net_title=中国算力网(C²NET) +c2net_desc=广泛接入全国各地智算中心、超算中心与大数据中心等,为用户提供免费算力资源 c2net_center=中心 search=搜索 search_repo=项目 @@ -292,6 +292,7 @@ create_pro = 创建项目 activity = 活动 no_events = 还没有与您相关的活动 or_t = 或 +powerdby=Powered_by 鹏城实验室云脑、中国算力网(C²NET)、 [explore] @@ -1230,6 +1231,8 @@ cloudbrain.benchmark.evaluate_test=测试程序 cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"目标检测","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"目标重识别","second":[{"id":1,"value":"车辆重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"基于图像的行人重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"多目标跟踪","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]} cloudbrain.benchmark.model.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"目标检测","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"目标重识别","second":[{"id":1,"value":"车辆重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"基于图像的行人重识别","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"多目标跟踪","second":[{"id":1,"value":"无","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]} cloudbrain.morethanonejob=您已经创建了一个正在等待或运行中的同类任务,请等待任务结束再创建。 +cloudbrain.morethanonejob1=您已经有 同类任务 正在等待或运行中,请等待任务结束再创建; +cloudbrain.morethanonejob2=可以在 “个人中心 > 云脑任务” 查看您所有的云脑任务。 modelarts.infer_job_model = 模型名称 modelarts.infer_job_model_file = 模型文件 @@ -1239,6 +1242,9 @@ modelarts.infer_job.select_model = 选择模型 modelarts.infer_job.boot_file_helper=启动文件是您程序执行的入口文件,必须是以.py结尾的文件。比如inference.py、main.py、example/inference.py、case/main.py。 modelarts.infer_job.tooltip = 该模型已删除,无法查看。 modelarts.download_log=下载日志文件 +modelarts.log_file=日志文件 +modelarts.fullscreen_log_file=全屏查看 +modelarts.exit_full_screen=退出全屏 modelarts.no_node_right = 计算节点数的值配置错误,您没有权限使用当前配置的计算节点数。 @@ -3195,6 +3201,7 @@ foot.help=帮助 foot.copyright= 版权所有:新一代人工智能开源开放平台(OpenI) Platform_Tutorial=新手指引 foot.advice_feedback = 意见反馈 +resource_description = 资源说明 [cloudbrain] all_resource_cluster=全部集群 @@ -3235,7 +3242,7 @@ view_sample = 查看样例 inference_output_path_rule = 推理输出路径存储在运行参数 result_url 中。 model_file_path_rule = 模型文件位置存储在运行参数 ckpt_url 中。 model_file_postfix_rule = 模型文件支持的格式为 [ckpt, pb, h5, json, pkl, pth, t7, pdparams, onnx, pbtxt, keras, mlmodel, cfg, pt] -model_convert_postfix_rule = 模型文件支持的格式为 [.pth, .pkl, .onnx, .mindir, .ckpt, .pb] +model_convert_postfix_rule = 模型文件支持的格式为 [.pth, .pkl, .onnx, .mindir, .ckpt, .pb, .pdmodel, .pdiparams, .params, .json] delete_task = 删除任务 task_delete_confirm = 你确认删除该任务么?此任务一旦删除不可恢复。 operate_confirm = 确定操作 diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8e1d725ed..c464f252c 100755 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -599,6 +599,11 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/hours_data", repo.GetCloudbrainsCreateHoursData) m.Get("/waitting_top_data", repo.GetWaittingTop) m.Get("/running_top_data", repo.GetRunningTop) + + m.Get("/overview_resource", repo.GetCloudbrainResourceOverview) + m.Get("/resource_usage_statistic", repo.GetDurationRateStatistic) + m.Get("/resource_usage_rate_detail", repo.GetCloudbrainResourceUsageDetail) + m.Get("/apitest_for_statistic", repo.CloudbrainDurationStatisticForTest) }) }, operationReq) diff --git a/routers/api/v1/repo/cloudbrain.go b/routers/api/v1/repo/cloudbrain.go index ba46ab58c..a8b9bcbac 100755 --- a/routers/api/v1/repo/cloudbrain.go +++ b/routers/api/v1/repo/cloudbrain.go @@ -572,7 +572,13 @@ func CloudbrainGetLog(ctx *context.APIContext) { startLine = 0 } } + } else { + if startLine > 0 { + startLine += 1 + endLine += 1 + } } + result = getLogFromModelDir(job.JobName, startLine, endLine, resultPath) if result == nil { log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"]) @@ -719,10 +725,10 @@ func getLogFromModelDir(jobName string, startLine int, endLine int, resultPath s line, error := r.ReadString('\n') if error == io.EOF { if i >= startLine { - fileEndLine = i re = re + line count++ } + fileEndLine = i + 1 log.Info("read file completed.") break } @@ -732,13 +738,12 @@ func getLogFromModelDir(jobName string, startLine int, endLine int, resultPath s } if error == nil { if i >= startLine { - fileEndLine = i + fileEndLine = i + 1 re = re + line count++ } } } - fileEndLine = fileEndLine + 1 } else { log.Info("error:" + err.Error()) } diff --git a/routers/api/v1/repo/cloudbrain_dashboard.go b/routers/api/v1/repo/cloudbrain_dashboard.go index 935006476..fdc8d64bb 100755 --- a/routers/api/v1/repo/cloudbrain_dashboard.go +++ b/routers/api/v1/repo/cloudbrain_dashboard.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "net/url" + "strconv" "strings" "time" @@ -120,9 +121,6 @@ func GetOverviewDuration(ctx *context.Context) { recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix now := time.Now() endTime := now - page := 1 - pagesize := 1000 - count := pagesize worker_server_num := 1 cardNum := 1 durationAllSum := int64(0) @@ -138,54 +136,46 @@ func GetOverviewDuration(ctx *context.Context) { c2NetDuration := int64(0) cDCenterDuration := int64(0) - for count == pagesize && count != 0 { - cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{ - ListOptions: models.ListOptions{ - Page: page, - PageSize: pagesize, - }, - Type: models.TypeCloudBrainAll, - BeginTimeUnix: int64(recordBeginTime), - EndTimeUnix: endTime.Unix(), - }) - if err != nil { - ctx.ServerError("Get cloudbrains failed:", err) - return - } - models.LoadSpecs4CloudbrainInfo(cloudbrains) - - for _, cloudbrain := range cloudbrains { - if cloudbrain.Cloudbrain.WorkServerNumber >= 1 { - worker_server_num = cloudbrain.Cloudbrain.WorkServerNumber - } else { - worker_server_num = 1 - } - if cloudbrain.Cloudbrain.Spec == nil { - cardNum = 1 - } else { - cardNum = cloudbrain.Cloudbrain.Spec.AccCardsNum - } - duration := cloudbrain.Duration - durationSum := cloudbrain.Duration * int64(worker_server_num) * int64(cardNum) - if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne { - cloudBrainOneDuration += duration - cloudBrainOneCardDuSum += durationSum - } else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo { - cloudBrainTwoDuration += duration - cloudBrainTwoCardDuSum += durationSum - } else if cloudbrain.Cloudbrain.Type == models.TypeC2Net { - c2NetDuration += duration - c2NetCardDuSum += durationSum - } else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter { - cDCenterDuration += duration - cDNetCardDuSum += durationSum - } + cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{ + Type: models.TypeCloudBrainAll, + BeginTimeUnix: int64(recordBeginTime), + EndTimeUnix: endTime.Unix(), + }) + if err != nil { + ctx.ServerError("Get cloudbrains failed:", err) + return + } + models.LoadSpecs4CloudbrainInfo(cloudbrains) - durationAllSum += duration - cardDuSum += durationSum - count = len(cloudbrains) - page += 1 + for _, cloudbrain := range cloudbrains { + if cloudbrain.Cloudbrain.WorkServerNumber >= 1 { + worker_server_num = cloudbrain.Cloudbrain.WorkServerNumber + } else { + worker_server_num = 1 } + if cloudbrain.Cloudbrain.Spec == nil { + cardNum = 1 + } else { + cardNum = cloudbrain.Cloudbrain.Spec.AccCardsNum + } + duration := cloudbrain.Duration + durationSum := cloudbrain.Duration * int64(worker_server_num) * int64(cardNum) + if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne { + cloudBrainOneDuration += duration + cloudBrainOneCardDuSum += durationSum + } else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo { + cloudBrainTwoDuration += duration + cloudBrainTwoCardDuSum += durationSum + } else if cloudbrain.Cloudbrain.Type == models.TypeC2Net { + c2NetDuration += duration + c2NetCardDuSum += durationSum + } else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter { + cDCenterDuration += duration + cDNetCardDuSum += durationSum + } + + durationAllSum += duration + cardDuSum += durationSum } ctx.JSON(http.StatusOK, map[string]interface{}{ "cloudBrainOneCardDuSum": cloudBrainOneCardDuSum, @@ -532,6 +522,21 @@ func getPageDateCloudbrainInfo(dateCloudbrainInfo []DateCloudbrainInfo, page int } +func getPageDateCloudbrainDuration(dateUsageStatistic []models.DateUsageStatistic, page int, pagesize int) []models.DateUsageStatistic { + begin := (page - 1) * pagesize + end := (page) * pagesize + + if begin > len(dateUsageStatistic)-1 { + return nil + } + if end > len(dateUsageStatistic)-1 { + return dateUsageStatistic[begin:] + } else { + return dateUsageStatistic[begin:end] + } + +} + func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) { queryType := ctx.QueryTrim("type") beginTimeStr := ctx.QueryTrim("beginTime") @@ -545,7 +550,7 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) { recordBeginTime := time.Unix(int64(recordCloudbrain[0].Cloudbrain.CreatedUnix), 0) beginTime, endTime, err := getCloudbrainTimePeroid(ctx, recordBeginTime) if err != nil { - log.Error("Parameter is wrong", err) + log.Error("getCloudbrainTimePeroid error:", err) ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong")) return } @@ -1403,3 +1408,424 @@ func getCloudbrainTimePeroid(ctx *context.Context, recordBeginTime time.Time) (t return beginTime, endTime, nil } + +func GetCloudbrainResourceOverview(ctx *context.Context) { + recordCloudbrainDuration, err := models.GetDurationRecordBeginTime() + if err != nil { + log.Error("Can not get GetDurationRecordBeginTime", err) + return + } + recordBeginTime := recordCloudbrainDuration[0].CreatedUnix + recordUpdateTime := time.Now().Unix() + resourceQueues, err := models.GetCanUseCardInfo() + if err != nil { + log.Info("GetCanUseCardInfo err: %v", err) + return + } + OpenIResourceDetail := []models.ResourceDetail{} + C2NetResourceDetail := []models.ResourceDetail{} + for _, resourceQueue := range resourceQueues { + if resourceQueue.Cluster == models.OpenICluster { + var resourceDetail models.ResourceDetail + resourceDetail.QueueCode = resourceQueue.QueueCode + resourceDetail.Cluster = resourceQueue.Cluster + resourceDetail.AiCenterCode = resourceQueue.AiCenterCode + resourceDetail.AiCenterName = resourceQueue.AiCenterName + "/" + resourceQueue.AiCenterCode + resourceDetail.ComputeResource = resourceQueue.ComputeResource + resourceDetail.AccCardType = resourceQueue.AccCardType + "(" + resourceQueue.ComputeResource + ")" + resourceDetail.CardsTotalNum = resourceQueue.CardsTotalNum + resourceDetail.IsAutomaticSync = resourceQueue.IsAutomaticSync + OpenIResourceDetail = append(OpenIResourceDetail, resourceDetail) + } + if resourceQueue.Cluster == models.C2NetCluster { + var resourceDetail models.ResourceDetail + resourceDetail.QueueCode = resourceQueue.QueueCode + resourceDetail.Cluster = resourceQueue.Cluster + resourceDetail.AiCenterCode = resourceQueue.AiCenterCode + resourceDetail.AiCenterName = resourceQueue.AiCenterName + "/" + resourceQueue.AiCenterCode + resourceDetail.ComputeResource = resourceQueue.ComputeResource + resourceDetail.AccCardType = resourceQueue.AccCardType + "(" + resourceQueue.ComputeResource + ")" + resourceDetail.CardsTotalNum = resourceQueue.CardsTotalNum + resourceDetail.IsAutomaticSync = resourceQueue.IsAutomaticSync + C2NetResourceDetail = append(C2NetResourceDetail, resourceDetail) + } + } + openIResourceNum := make(map[string]map[string]int) + + for _, openIResourceDetail := range OpenIResourceDetail { + if _, ok := openIResourceNum[openIResourceDetail.AiCenterName]; !ok { + openIResourceNum[openIResourceDetail.AiCenterName] = make(map[string]int) + } + if _, ok := openIResourceNum[openIResourceDetail.AiCenterName][openIResourceDetail.AccCardType]; !ok { + openIResourceNum[openIResourceDetail.AiCenterName][openIResourceDetail.AccCardType] = openIResourceDetail.CardsTotalNum + } else { + openIResourceNum[openIResourceDetail.AiCenterName][openIResourceDetail.AccCardType] += openIResourceDetail.CardsTotalNum + } + } + + c2NetResourceNum := make(map[string]map[string]int) + for _, c2NetResourceDetail := range C2NetResourceDetail { + if _, ok := c2NetResourceNum[c2NetResourceDetail.AiCenterName]; !ok { + c2NetResourceNum[c2NetResourceDetail.AiCenterName] = make(map[string]int) + } + if _, ok := c2NetResourceNum[c2NetResourceDetail.AiCenterName][c2NetResourceDetail.AccCardType]; !ok { + c2NetResourceNum[c2NetResourceDetail.AiCenterName][c2NetResourceDetail.AccCardType] = c2NetResourceDetail.CardsTotalNum + } else { + c2NetResourceNum[c2NetResourceDetail.AiCenterName][c2NetResourceDetail.AccCardType] += c2NetResourceDetail.CardsTotalNum + } + + } + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "openI": openIResourceNum, + "c2Net": c2NetResourceNum, + "recordUpdateTime": recordUpdateTime, + "recordBeginTime": recordBeginTime, + }) +} + +func GetCloudbrainResourceUsageDetail(ctx *context.Context) { + aiCenterCode := ctx.QueryTrim("aiCenterCode") + if aiCenterCode == "" { + aiCenterCode = models.AICenterOfCloudBrainOne + } + beginTime, endTime := getBeginAndEndTime(ctx) + dayCloudbrainDuration, count, err := getDayCloudbrainDuration(beginTime, endTime, aiCenterCode) + if err != nil { + log.Error("Can not query dayCloudbrainDuration.", err) + return + } + hourCloudbrainDuration, err := getHourCloudbrainDuration(beginTime, endTime, aiCenterCode) + if err != nil { + log.Error("Can not query hourCloudbrainDuration.", err) + return + } + page := ctx.QueryInt("page") + if page <= 0 { + page = 1 + } + pagesize := ctx.QueryInt("pagesize") + if pagesize <= 0 { + pagesize = 36500 + } + pageDateCloudbrainDuration := getPageDateCloudbrainDuration(dayCloudbrainDuration, page, pagesize) + ctx.JSON(http.StatusOK, map[string]interface{}{ + "totalCount": count, + "pageDateCloudbrainDuration": pageDateCloudbrainDuration, + "hourCloudbrainDuration": hourCloudbrainDuration, + }) +} + +func GetDurationRateStatistic(ctx *context.Context) { + beginTime, endTime := getBeginAndEndTime(ctx) + OpenIDurationRate, C2NetDurationRate, totalUsageRate := getDurationStatistic(beginTime, endTime) + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "openIDurationRate": OpenIDurationRate, + "c2NetDurationRate": C2NetDurationRate, + "totalUsageRate": totalUsageRate, + }) + +} + +func CloudbrainDurationStatisticForTest(ctx *context.Context) { + repo.CloudbrainDurationStatisticHour() + ctx.JSON(http.StatusOK, map[string]interface{}{ + "message": 0, + }) +} + +func getBeginAndEndTime(ctx *context.Context) (time.Time, time.Time) { + queryType := ctx.QueryTrim("type") + now := time.Now() + beginTimeStr := ctx.QueryTrim("beginTime") + endTimeStr := ctx.QueryTrim("endTime") + + var beginTime time.Time + var endTime time.Time + var err error + if queryType != "" { + if queryType == "all" { + recordCloudbrainDuration, err := models.GetDurationRecordBeginTime() + if err != nil { + log.Error("Can not get GetDurationRecordBeginTime", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) + return beginTime, endTime + } + brainRecordBeginTime := recordCloudbrainDuration[0].CreatedUnix.AsTime() + beginTime = brainRecordBeginTime + endTime = now + } else if queryType == "today" { + beginTime = now.AddDate(0, 0, 0) + beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) + endTime = now + + } else if queryType == "yesterday" { + beginTime = now.AddDate(0, 0, -1) + beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) + endTime = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) + } else if queryType == "last_7day" { + beginTime = now.AddDate(0, 0, -6) + beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) + endTime = now + } else if queryType == "last_30day" { + beginTime = now.AddDate(0, 0, -29) + beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) + endTime = now + } else if queryType == "current_month" { + endTime = now + beginTime = time.Date(endTime.Year(), endTime.Month(), 1, 0, 0, 0, 0, now.Location()) + + } else if queryType == "current_year" { + endTime = now + beginTime = time.Date(endTime.Year(), 1, 1, 0, 0, 0, 0, now.Location()) + } else if queryType == "last_month" { + lastMonthTime := now.AddDate(0, -1, 0) + beginTime = time.Date(lastMonthTime.Year(), lastMonthTime.Month(), 1, 0, 0, 0, 0, now.Location()) + endTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()) + } + + } else { + if beginTimeStr == "" || endTimeStr == "" { + //如果查询类型和开始时间结束时间都未设置,按queryType=all处理 + recordCloudbrainDuration, err := models.GetDurationRecordBeginTime() + if err != nil { + log.Error("Can not get recordCloudbrain", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) + return beginTime, endTime + } + brainRecordBeginTime := recordCloudbrainDuration[0].CreatedUnix.AsTime() + beginTime = brainRecordBeginTime + endTime = now + } else { + beginTime, err = time.ParseInLocation("2006-01-02", beginTimeStr, time.Local) + if err != nil { + log.Error("Can not ParseInLocation.", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("ParseInLocation_get_error")) + return beginTime, endTime + } + endTime, err = time.ParseInLocation("2006-01-02", endTimeStr, time.Local) + if err != nil { + log.Error("Can not ParseInLocation.", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("ParseInLocation_get_error")) + return beginTime, endTime + } + if endTime.After(time.Now()) { + endTime = time.Now() + } + } + + } + return beginTime, endTime +} + +func getAiCenterUsageDuration(beginTime time.Time, endTime time.Time, cloudbrainStatistics []*models.CloudbrainDurationStatistic) (int, int, float64) { + totalDuration := int(0) + usageDuration := int(0) + usageRate := float64(0) + + for _, cloudbrainStatistic := range cloudbrainStatistics { + if int64(cloudbrainStatistic.CreatedUnix) >= beginTime.Unix() && int64(cloudbrainStatistic.CreatedUnix) < endTime.Unix() { + totalDuration += cloudbrainStatistic.CardsTotalDuration + usageDuration += cloudbrainStatistic.CardsUseDuration + } + } + if totalDuration == 0 || usageDuration == 0 { + usageRate = 0 + } else { + usageRate = float64(usageDuration) / float64(totalDuration) + } + + return totalDuration, usageDuration, usageRate +} + +func getDurationStatistic(beginTime time.Time, endTime time.Time) (models.DurationRateStatistic, models.DurationRateStatistic, float64) { + OpenITotalDuration := make(map[string]int) + OpenIUsageDuration := make(map[string]int) + OpenIUsageRate := make(map[string]float64) + + C2NetTotalDuration := make(map[string]int) + C2NetUsageDuration := make(map[string]int) + OpenIDurationRate := models.DurationRateStatistic{} + C2NetDurationRate := models.DurationRateStatistic{} + cardDurationStatistics, err := models.GetCardDurationStatistics(&models.DurationStatisticOptions{ + BeginTime: beginTime, + EndTime: endTime, + }) + if err != nil { + log.Error("GetCardDurationStatistics error:", err) + return OpenIDurationRate, C2NetDurationRate, 0 + } + for _, cloudbrainStatistic := range cardDurationStatistics { + if cloudbrainStatistic.Cluster == models.OpenICluster { + if _, ok := OpenITotalDuration[cloudbrainStatistic.AiCenterName]; !ok { + OpenITotalDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsTotalDuration + } else { + OpenITotalDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsTotalDuration + } + if _, ok := OpenIUsageDuration[cloudbrainStatistic.AiCenterName]; !ok { + OpenIUsageDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsUseDuration + } else { + OpenIUsageDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsUseDuration + } + } + if cloudbrainStatistic.Cluster == models.C2NetCluster { + if _, ok := C2NetTotalDuration[cloudbrainStatistic.AiCenterName]; !ok { + C2NetTotalDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsTotalDuration + } else { + C2NetTotalDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsTotalDuration + } + if _, ok := C2NetUsageDuration[cloudbrainStatistic.AiCenterName]; !ok { + C2NetUsageDuration[cloudbrainStatistic.AiCenterName] = cloudbrainStatistic.CardsUseDuration + } else { + C2NetUsageDuration[cloudbrainStatistic.AiCenterName] += cloudbrainStatistic.CardsUseDuration + } + } + } + ResourceAiCenterRes, err := models.GetResourceAiCenters() + if err != nil { + log.Error("Can not get ResourceAiCenterRes.", err) + return OpenIDurationRate, C2NetDurationRate, 0 + } + for _, v := range ResourceAiCenterRes { + if cutString(v.AiCenterCode, 4) == cutString(models.AICenterOfCloudBrainOne, 4) { + if _, ok := OpenIUsageDuration[v.AiCenterName]; !ok { + OpenIUsageDuration[v.AiCenterName] = 0 + } + if _, ok := OpenITotalDuration[v.AiCenterName]; !ok { + OpenITotalDuration[v.AiCenterName] = 0 + } + } else { + if _, ok := C2NetUsageDuration[v.AiCenterName]; !ok { + C2NetUsageDuration[v.AiCenterName] = 0 + } + } + } + totalCanUse := float64(0) + totalUse := float64(0) + totalUsageRate := float64(0) + for k, v := range OpenITotalDuration { + for i, j := range OpenIUsageDuration { + if k == i { + OpenIUsageRate[k] = float64(j) / float64(v) + } + } + } + for _, v := range OpenITotalDuration { + totalCanUse += float64(v) + } + for _, v := range OpenIUsageRate { + totalUse += float64(v) + } + if totalCanUse == 0 || totalUse == 0 { + totalUsageRate = 0 + } else { + totalUsageRate = totalUse / totalCanUse + } + + OpenIDurationRate.AiCenterTotalDurationStat = OpenITotalDuration + OpenIDurationRate.AiCenterUsageDurationStat = OpenIUsageDuration + OpenIDurationRate.UsageRate = OpenIUsageRate + C2NetDurationRate.AiCenterTotalDurationStat = C2NetTotalDuration + C2NetDurationRate.AiCenterUsageDurationStat = C2NetUsageDuration + return OpenIDurationRate, C2NetDurationRate, totalUsageRate +} + +func cutString(str string, lens int) string { + if len(str) < lens { + return str + } + return str[:lens] +} + +func getDayCloudbrainDuration(beginTime time.Time, endTime time.Time, aiCenterCode string) ([]models.DateUsageStatistic, int, error) { + now := time.Now() + endTimeTemp := time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location()) + if endTimeTemp.Equal(endTime) { + endTimeTemp = endTimeTemp.AddDate(0, 0, -1) + } + cardDurationStatistics, err := models.GetCardDurationStatistics(&models.DurationStatisticOptions{ + BeginTime: beginTime, + EndTime: endTime, + AiCenterCode: aiCenterCode, + }) + if err != nil { + log.Error("GetCardDurationStatistics error:", err) + return nil, 0, err + } + + dayCloudbrainInfo := make([]models.DateUsageStatistic, 0) + count := 0 + for beginTime.Before(endTimeTemp) || beginTime.Equal(endTimeTemp) { + TotalDuration, UsageDuration, UsageRate := getAiCenterUsageDuration(endTimeTemp, endTime, cardDurationStatistics) + dayCloudbrainInfo = append(dayCloudbrainInfo, models.DateUsageStatistic{ + Date: endTimeTemp.Format("2006/01/02"), + UsageDuration: UsageDuration, + TotalDuration: TotalDuration, + UsageRate: UsageRate, + }) + endTime = endTimeTemp + endTimeTemp = endTimeTemp.AddDate(0, 0, -1) + if endTimeTemp.Before(beginTime) && beginTime.Before(endTime) { + endTimeTemp = beginTime + } + count += 1 + } + return dayCloudbrainInfo, count, nil +} + +func getHourCloudbrainDuration(beginTime time.Time, endTime time.Time, aiCenterCode string) (models.HourTimeStatistic, error) { + hourTimeTotalDuration := make(map[string]int) + hourTimeUsageDuration := make(map[string]int) + hourTimeUsageRate := make(map[string]float64) + hourTimeStatistic := models.HourTimeStatistic{} + + cardDurationStatistics, err := models.GetCardDurationStatistics(&models.DurationStatisticOptions{ + BeginTime: beginTime, + EndTime: endTime, + }) + if err != nil { + log.Error("GetCardDurationStatistics error:", err) + return hourTimeStatistic, err + } + for _, cloudbrainStatistic := range cardDurationStatistics { + if cloudbrainStatistic.AiCenterCode == aiCenterCode { + if _, ok := hourTimeTotalDuration[strconv.Itoa(cloudbrainStatistic.HourTime)]; !ok { + hourTimeTotalDuration[strconv.Itoa(cloudbrainStatistic.HourTime)] = cloudbrainStatistic.CardsTotalDuration + } else { + hourTimeTotalDuration[strconv.Itoa(cloudbrainStatistic.HourTime)] += cloudbrainStatistic.CardsTotalDuration + } + if _, ok := hourTimeUsageDuration[strconv.Itoa(cloudbrainStatistic.HourTime)]; !ok { + hourTimeUsageDuration[strconv.Itoa(cloudbrainStatistic.HourTime)] = cloudbrainStatistic.CardsUseDuration + } else { + hourTimeUsageDuration[strconv.Itoa(cloudbrainStatistic.HourTime)] += cloudbrainStatistic.CardsUseDuration + } + } + } + hourTimeList := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"} + for _, v := range hourTimeList { + if _, ok := hourTimeUsageDuration[v]; !ok { + hourTimeUsageDuration[v] = 0 + } + if _, ok := hourTimeTotalDuration[v]; !ok { + hourTimeTotalDuration[v] = 0 + } + } + + for k, v := range hourTimeTotalDuration { + for i, j := range hourTimeUsageDuration { + if k == i { + if v == 0 || j == 0 { + hourTimeUsageRate[k] = 0 + } else { + hourTimeUsageRate[k] = float64(j) / float64(v) + } + } + } + } + + hourTimeStatistic.HourTimeTotalDuration = hourTimeTotalDuration + hourTimeStatistic.HourTimeUsageDuration = hourTimeUsageDuration + hourTimeStatistic.HourTimeUsageRate = hourTimeUsageRate + return hourTimeStatistic, nil +} diff --git a/routers/home.go b/routers/home.go index ac607b5be..aab760611 100755 --- a/routers/home.go +++ b/routers/home.go @@ -41,6 +41,7 @@ const ( tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis" tplHomeTerm base.TplName = "terms" tplHomePrivacy base.TplName = "privacy" + tplResoruceDesc base.TplName = "resource_desc" ) // Home render home page @@ -820,3 +821,7 @@ func HomeTerm(ctx *context.Context) { func HomePrivacy(ctx *context.Context) { ctx.HTML(200, tplHomePrivacy) } + +func HomeResoruceDesc(ctx *context.Context) { + ctx.HTML(200, tplResoruceDesc) +} \ No newline at end of file diff --git a/routers/repo/ai_model_convert.go b/routers/repo/ai_model_convert.go index 9a5874956..bd6a01072 100644 --- a/routers/repo/ai_model_convert.go +++ b/routers/repo/ai_model_convert.go @@ -29,7 +29,9 @@ const ( tplModelConvertInfo = "repo/modelmanage/convertshowinfo" PYTORCH_ENGINE = 0 TENSORFLOW_ENGINE = 1 - MINDSPORE_ENGIN = 2 + MINDSPORE_ENGINE = 2 + PADDLE_ENGINE = 4 + MXNET_ENGINE = 6 ModelMountPath = "/model" CodeMountPath = "/code" DataSetMountPath = "/dataset" @@ -395,6 +397,20 @@ func createGpuTrainJob(modelConvert *models.AiModelConvert, ctx *context.Context deleteLocalDir(relatetiveModelPath) dataActualPath = setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + modelConvert.ID + "/dataset" } + } else if modelConvert.SrcEngine == PADDLE_ENGINE { + IMAGE_URL = setting.ModelConvert.GPU_PADDLE_IMAGE + if modelConvert.DestFormat == CONVERT_FORMAT_ONNX { + command = getGpuModelConvertCommand(modelConvert.ID, modelConvert.ModelPath, modelConvert, setting.ModelConvert.PaddleOnnxBootFile) + } else { + return errors.New("Not support the format.") + } + } else if modelConvert.SrcEngine == MXNET_ENGINE { + IMAGE_URL = setting.ModelConvert.GPU_MXNET_IMAGE + if modelConvert.DestFormat == CONVERT_FORMAT_ONNX { + command = getGpuModelConvertCommand(modelConvert.ID, modelConvert.ModelPath, modelConvert, setting.ModelConvert.MXnetOnnxBootFile) + } else { + return errors.New("Not support the format.") + } } log.Info("dataActualPath=" + dataActualPath) diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 5b358b83b..f2b0fc6d1 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/services/cloudbrain/resource" uuid "github.com/satori/go.uuid" ) @@ -69,13 +70,10 @@ func saveModelByParameters(jobId string, versionName string, name string, versio cloudType = models.TypeCloudBrainTwo } else if aiTask.ComputeResource == models.GPUResource { cloudType = models.TypeCloudBrainOne - var ResourceSpecs *models.ResourceSpecs - json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) - for _, tmp := range ResourceSpecs.ResourceSpec { - if tmp.Id == aiTask.ResourceSpecId { - flaverName := ctx.Tr("cloudbrain.gpu_num") + ": " + fmt.Sprint(tmp.GpuNum) + " " + ctx.Tr("cloudbrain.cpu_num") + ": " + fmt.Sprint(tmp.CpuNum) + " " + ctx.Tr("cloudbrain.memory") + "(MB): " + fmt.Sprint(tmp.MemMiB) + " " + ctx.Tr("cloudbrain.shared_memory") + "(MB): " + fmt.Sprint(tmp.ShareMemMiB) - aiTask.FlavorName = flaverName - } + spec, err := resource.GetCloudbrainSpec(aiTask.ID) + if err == nil { + flaverName := "GPU: " + fmt.Sprint(spec.AccCardsNum) + "*" + spec.AccCardType + ",CPU: " + fmt.Sprint(spec.CpuCores) + "," + ctx.Tr("cloudbrain.memory") + ": " + fmt.Sprint(spec.MemGiB) + "GB," + ctx.Tr("cloudbrain.shared_memory") + ": " + fmt.Sprint(spec.ShareMemGiB) + "GB" + aiTask.FlavorName = flaverName } } diff --git a/routers/repo/aisafety.go b/routers/repo/aisafety.go index 5102a6722..e274f808e 100644 --- a/routers/repo/aisafety.go +++ b/routers/repo/aisafety.go @@ -26,7 +26,6 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/cloudbrain/resource" "code.gitea.io/gitea/services/reward/point/account" - uuid "github.com/satori/go.uuid" ) const ( @@ -37,39 +36,6 @@ const ( tplModelSafetyTestShow = "repo/modelsafety/show" ) -func CloudBrainAiSafetyCreateTest(ctx *context.Context) { - log.Info("start to create CloudBrainAiSafetyCreate") - uuid := uuid.NewV4() - id := uuid.String() - seriaNoParas := ctx.Query("serialNo") - fileName := ctx.Query("fileName") - - //if jobType == string(models.JobTypeBenchmark) { - req := aisafety.TaskReq{ - UnionId: id, - EvalName: "test1", - EvalContent: "test1", - TLPath: "test1", - Indicators: []string{"ACC", "ASS"}, - CDName: "CIFAR10_1000_FGSM", - BDName: "CIFAR10_1000基础数据集", - } - aisafety.GetAlgorithmList() - if seriaNoParas != "" { - aisafety.GetTaskStatus(seriaNoParas) - } else { - jsonStr, err := getJsonContent("http://192.168.207.34:8065/Test_zap1234/openi_aisafety/raw/branch/master/result/" + fileName) - serialNo, err := aisafety.CreateSafetyTask(req, jsonStr) - if err == nil { - log.Info("serialNo=" + serialNo) - time.Sleep(time.Duration(2) * time.Second) - aisafety.GetTaskStatus(serialNo) - } else { - log.Info("CreateSafetyTask error," + err.Error()) - } - } -} - func GetAiSafetyTaskByJob(job *models.Cloudbrain) { if job == nil { log.Error("GetCloudbrainByJobID failed") @@ -325,6 +291,7 @@ func queryTaskStatusFromCloudbrain(job *models.Cloudbrain) { } else { // job.Status = string(models.ModelSafetyTesting) + job.EndTime = 0 err = models.UpdateJob(job) if err != nil { log.Error("UpdateJob failed:", err) @@ -341,6 +308,9 @@ func queryTaskStatusFromModelSafetyTestServer(job *models.Cloudbrain) { if result.Data.Status == 1 { log.Info("The task is running....") } else { + job.EndTime = timeutil.TimeStampNow() + job.Duration = (job.EndTime.AsTime().Unix() - job.StartTime.AsTime().Unix()) / 1000 + job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) if result.Data.Code == 0 { job.ResultJson = result.Data.StandardJson job.Status = string(models.JobSucceeded) @@ -474,6 +444,9 @@ func updateJobFailed(job *models.Cloudbrain, msg string) { //update task failed. job.Status = string(models.ModelArtsTrainJobFailed) job.ResultJson = msg + job.EndTime = timeutil.TimeStampNow() + job.Duration = (job.EndTime.AsTime().Unix() - job.StartTime.AsTime().Unix()) / 1000 + job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) err := models.UpdateJob(job) if err != nil { log.Error("UpdateJob failed:", err) @@ -535,6 +508,8 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) { } else { log.Info("The GPU WaitCount not get") } + NotStopTaskCount, _ := models.GetModelSafetyCountByUserID(ctx.User.ID) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount ctx.HTML(200, tplModelSafetyTestCreateGpu) } @@ -578,6 +553,8 @@ func AiSafetyCreateForGetNPU(ctx *context.Context) { waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") ctx.Data["WaitCount"] = waitCount log.Info("The NPU WaitCount is " + fmt.Sprint(waitCount)) + NotStopTaskCount, _ := models.GetModelSafetyCountByUserID(ctx.User.ID) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount ctx.HTML(200, tplModelSafetyTestCreateNpu) } @@ -980,6 +957,8 @@ func modelSafetyNewDataPrepare(ctx *context.Context) error { ctx.Data["ckpt_name"] = ctx.Query("ckpt_name") ctx.Data["model_name"] = ctx.Query("model_name") ctx.Data["model_version"] = ctx.Query("model_version") + NotStopTaskCount, _ := models.GetModelSafetyCountByUserID(ctx.User.ID) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount if ctx.QueryInt("type") == models.TypeCloudBrainOne { ctx.Data["type"] = models.TypeCloudBrainOne diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go index a2ea7d51b..95c708e03 100755 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/dataset" + "code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" "code.gitea.io/gitea/services/cloudbrain/resource" "code.gitea.io/gitea/services/reward/point/account" @@ -107,7 +108,7 @@ func jobNamePrefixValid(s string) string { } -func cloudBrainNewDataPrepare(ctx *context.Context) error { +func cloudBrainNewDataPrepare(ctx *context.Context, jobType string) error { ctx.Data["PageIsCloudBrain"] = true t := time.Now() var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] @@ -148,6 +149,8 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { defaultMode = "alogrithm" } ctx.Data["benchmarkMode"] = defaultMode + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount if ctx.Cloudbrain != nil { ctx.Data["branch_name"] = ctx.Cloudbrain.BranchName @@ -210,7 +213,7 @@ func prepareCloudbrainOneSpecs(ctx *context.Context) { } func CloudBrainNew(ctx *context.Context) { - err := cloudBrainNewDataPrepare(ctx) + err := cloudBrainNewDataPrepare(ctx, string(models.JobTypeDebug)) if err != nil { ctx.ServerError("get new cloudbrain info failed", err) return @@ -244,7 +247,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { isOk, err := lock.Lock(models.CloudbrainKeyDuration) if !isOk { log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form) return } @@ -254,42 +257,42 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { if err == nil { if len(tasks) != 0 { log.Error("the job name did already exist", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("the job name did already exist", tpl, &form) return } } else { if !models.IsErrJobNotExist(err) { log.Error("system error, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tpl, &form) return } } if !jobNamePattern.MatchString(displayJobName) { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) return } if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeTrain) { log.Error("jobtype error:", jobType, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("jobtype error", tpl, &form) return } - count, err := models.GetCloudbrainCountByUserID(ctx.User.ID, jobType) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType) if err != nil { log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tpl, &form) return } else { if count >= 1 { log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form) return } @@ -301,7 +304,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { datasetInfos, datasetNames, err = models.GetDatasetInfo(uuids) if err != nil { log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) return } @@ -312,7 +315,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) if err != nil || !bootFileExist { log.Error("Get bootfile error:", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tpl, &form) return } @@ -320,7 +323,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { commandTrain, err := getTrainJobCommand(form) if err != nil { log.Error("getTrainJobCommand failed: %v", err) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(err.Error(), tpl, &form) return } @@ -333,7 +336,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { } errStr := loadCodeAndMakeModelPath(repo, codePath, branchName, jobName, cloudbrain.ModelMountPath) if errStr != "" { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr(errStr), tpl, &form) return } @@ -346,14 +349,14 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { Cluster: models.OpenICluster, AiCenterCode: models.AICenterOfCloudBrainOne}) if err != nil || spec == nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("Resource specification not available", tpl, &form) return } if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form) return } @@ -396,7 +399,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { err = cloudbrain.GenerateTask(req) if err != nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(err.Error(), tpl, &form) return } @@ -454,7 +457,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra isOk, err := lock.Lock(models.CloudbrainKeyDuration) if !isOk { log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form) return } @@ -465,7 +468,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra command, err := getInferenceJobCommand(form) if err != nil { log.Error("getTrainJobCommand failed: %v", err) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(err.Error(), tpl, &form) return } @@ -474,21 +477,21 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra if err == nil { if len(tasks) != 0 { log.Error("the job name did already exist", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("the job name did already exist", tpl, &form) return } } else { if !models.IsErrJobNotExist(err) { log.Error("system error, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tpl, &form) return } } if !jobNamePattern.MatchString(displayJobName) { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) return } @@ -496,21 +499,21 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra bootFileExist, err := ctx.Repo.FileExists(bootFile, branchName) if err != nil || !bootFileExist { log.Error("Get bootfile error:", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_bootfile_err"), tpl, &form) return } - count, err := models.GetCloudbrainCountByUserID(ctx.User.ID, jobType) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType) if err != nil { log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tpl, &form) return } else { if count >= 1 { log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form) return } @@ -521,7 +524,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra } errStr := loadCodeAndMakeModelPath(repo, codePath, branchName, jobName, cloudbrain.ResultPath) if errStr != "" { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr(errStr), tpl, &form) return } @@ -531,7 +534,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid) if err != nil { log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) return } @@ -541,13 +544,13 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra Cluster: models.OpenICluster, AiCenterCode: models.AICenterOfCloudBrainOne}) if err != nil || spec == nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("Resource specification not available", tpl, &form) return } if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form) return } @@ -582,7 +585,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra err = cloudbrain.GenerateTask(req) if err != nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(err.Error(), tpl, &form) return } @@ -682,7 +685,7 @@ func CloudBrainRestart(ctx *context.Context) { break } - count, err := models.GetCloudbrainCountByUserID(ctx.User.ID, string(models.JobTypeDebug)) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, string(models.JobTypeDebug)) if err != nil { log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) resultCode = "-1" @@ -749,47 +752,48 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo ctx.NotFound(ctx.Req.URL.RequestURI(), nil) return } - - result, err := cloudbrain.GetJob(task.JobID) - if err != nil { - log.Info("error:" + err.Error()) - ctx.NotFound(ctx.Req.URL.RequestURI(), nil) - return - } prepareSpec4Show(ctx, task) if ctx.Written() { return } + if task.Status==string(models.JobWaiting) || task.Status==string(models.JobRunning) { + result, err := cloudbrain.GetJob(task.JobID) + if err != nil { + log.Info("error:" + err.Error()) + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + return + } + + if result != nil { + jobRes, _ := models.ConvertToJobResultPayload(result.Payload) + taskRoles := jobRes.TaskRoles + taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) + ctx.Data["taskRes"] = taskRes + ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics + oldStatus := task.Status + task.Status = taskRes.TaskStatuses[0].State + task.ContainerIp = "" + task.ContainerID = taskRes.TaskStatuses[0].ContainerID + models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) + + if task.DeletedAt.IsZero() { //normal record + if oldStatus != task.Status { + notification.NotifyChangeCloudbrainStatus(task, oldStatus) + } + err = models.UpdateJob(task) + if err != nil { + ctx.Data["error"] = err.Error() + return + } + } else { //deleted record - if result != nil { - jobRes, _ := models.ConvertToJobResultPayload(result.Payload) - taskRoles := jobRes.TaskRoles - taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) - ctx.Data["taskRes"] = taskRes - ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics - oldStatus := task.Status - task.Status = taskRes.TaskStatuses[0].State - task.ContainerIp = "" - task.ContainerID = taskRes.TaskStatuses[0].ContainerID - models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) - - if task.DeletedAt.IsZero() { //normal record - if oldStatus != task.Status { - notification.NotifyChangeCloudbrainStatus(task, oldStatus) - } - err = models.UpdateJob(task) - if err != nil { - ctx.Data["error"] = err.Error() - return } - } else { //deleted record + ctx.Data["result"] = jobRes + } else { + log.Info("error:" + err.Error()) + return } - - ctx.Data["result"] = jobRes - } else { - log.Info("error:" + err.Error()) - return } user, err := models.GetUserByID(task.UserID) @@ -2222,7 +2226,7 @@ func CloudBrainBenchmarkNew(ctx *context.Context) { ctx.Data["description"] = "" ctx.Data["benchmarkTypeID"] = -1 ctx.Data["benchmark_child_types_id_hidden"] = -1 - err := cloudBrainNewDataPrepare(ctx) + err := cloudBrainNewDataPrepare(ctx, string(models.JobTypeBenchmark)) if err != nil { ctx.ServerError("get new cloudbrain info failed", err) return @@ -2327,6 +2331,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo benchmarkTypeID := form.BenchmarkTypeID benchmarkChildTypeID := form.BenchmarkChildTypeID repo := ctx.Repo.Repository + jobType := form.JobType ctx.Data["description"] = form.Description ctx.Data["benchmarkTypeID"] = benchmarkTypeID @@ -2336,31 +2341,31 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo isOk, err := lock.Lock(models.CloudbrainKeyDuration) if !isOk { log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplCloudBrainBenchmarkNew, &form) return } defer lock.UnLock() - tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeBenchmark), displayJobName) + tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) if err == nil { if len(tasks) != 0 { log.Error("the job name did already exist", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("the job name did already exist", tplCloudBrainBenchmarkNew, &form) return } } else { if !models.IsErrJobNotExist(err) { log.Error("system error, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) return } } if !jobNamePattern.MatchString(jobName) { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainBenchmarkNew, &form) return } @@ -2368,7 +2373,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo childInfo, err := getBenchmarkAttachment(benchmarkTypeID, benchmarkChildTypeID, ctx) if err != nil { log.Error("getBenchmarkAttachment failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("benchmark type error", tplCloudBrainBenchmarkNew, &form) return } @@ -2379,27 +2384,27 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo Cluster: models.OpenICluster, AiCenterCode: models.AICenterOfCloudBrainOne}) if err != nil || spec == nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("Resource specification not available", tplCloudBrainBenchmarkNew, &form) return } if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplCloudBrainBenchmarkNew, &form) return } - count, err := models.GetBenchmarkCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType) if err != nil { log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) return } else { if count >= 1 { log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tplCloudBrainBenchmarkNew, &form) return } @@ -2408,7 +2413,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo os.RemoveAll(codePath) if err := downloadCode(repo, codePath, cloudbrain.DefaultBranchName); err != nil { log.Error("downloadCode failed, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) return } @@ -2417,11 +2422,11 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo if os.IsNotExist(err) { // file does not exist log.Error("train.py does not exist, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("train.py does not exist", tplCloudBrainBenchmarkNew, &form) } else { log.Error("Stat failed, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) } return @@ -2429,11 +2434,11 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo if os.IsNotExist(err) { // file does not exist log.Error("test.py does not exist, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("test.py does not exist", tplCloudBrainBenchmarkNew, &form) } else { log.Error("Stat failed, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) } return @@ -2441,7 +2446,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo if err := uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/"); err != nil { log.Error("uploadCodeToMinio failed, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) return } @@ -2466,7 +2471,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid) if err != nil { log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tplCloudBrainBenchmarkNew, &form) return } @@ -2500,7 +2505,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo err = cloudbrain.GenerateTask(req) if err != nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(err.Error(), tplCloudBrainBenchmarkNew, &form) return } @@ -2526,7 +2531,7 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) isOk, err := lock.Lock(models.CloudbrainKeyDuration) if !isOk { log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form) return } @@ -2536,42 +2541,42 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) if err == nil { if len(tasks) != 0 { log.Error("the job name did already exist", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("the job name did already exist", tpl, &form) return } } else { if !models.IsErrJobNotExist(err) { log.Error("system error, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tpl, &form) return } } if !jobNamePattern.MatchString(displayJobName) { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) return } if jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) { log.Error("jobtype error:", jobType, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("jobtype error", tpl, &form) return } - count, err := models.GetBenchmarkCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType) if err != nil { log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("system error", tpl, &form) return } else { if count >= 1 { log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form) return } @@ -2603,7 +2608,7 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid) if err != nil { log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) return } @@ -2613,14 +2618,14 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) Cluster: models.OpenICluster, AiCenterCode: models.AICenterOfCloudBrainOne}) if err != nil || spec == nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr("Resource specification not available", tpl, &form) return } if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID) - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form) return } @@ -2654,7 +2659,7 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) err = cloudbrain.GenerateTask(req) if err != nil { - cloudBrainNewDataPrepare(ctx) + cloudBrainNewDataPrepare(ctx, jobType) ctx.RenderWithErr(err.Error(), tpl, &form) return } @@ -2701,7 +2706,7 @@ func CloudBrainTrainJobVersionNew(ctx *context.Context) { } func cloudBrainTrainJobCreate(ctx *context.Context) { - err := cloudBrainNewDataPrepare(ctx) + err := cloudBrainNewDataPrepare(ctx, string(models.JobTypeTrain)) if err != nil { ctx.ServerError("get new train-job info failed", err) return @@ -2710,7 +2715,7 @@ func cloudBrainTrainJobCreate(ctx *context.Context) { } func InferenceCloudBrainJobNew(ctx *context.Context) { - err := cloudBrainNewDataPrepare(ctx) + err := cloudBrainNewDataPrepare(ctx, string(models.JobTypeInference)) if err != nil { ctx.ServerError("get new train-job info failed", err) return diff --git a/routers/repo/cloudbrain_statistic.go b/routers/repo/cloudbrain_statistic.go new file mode 100644 index 000000000..3814c2daf --- /dev/null +++ b/routers/repo/cloudbrain_statistic.go @@ -0,0 +1,169 @@ +package repo + +import ( + "strings" + "time" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" +) + +func CloudbrainDurationStatisticHour() { + + dateTime := time.Now().Format("2006-01-02 15:04:05") + dayTime := time.Now().Format("2006-01-02") + now := time.Now() + + currentTime := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location()) + + m, _ := time.ParseDuration("-1h") + beginTime := currentTime.Add(m).Unix() + endTime := currentTime.Unix() + hourTime := currentTime.Add(m).Hour() + + ciTasks, err := models.GetCloudbrainByTime(beginTime, endTime) + if err != nil { + log.Info("GetCloudbrainByTime err: %v", err) + return + } + specMap := make(map[string]*models.Specification) + models.LoadSpecs4CloudbrainInfo(ciTasks) + for _, cloudbrain := range ciTasks { + if _, ok := specMap[cloudbrain.Cloudbrain.Spec.AiCenterCode+"/"+cloudbrain.Cloudbrain.Spec.AccCardType]; !ok { + if cloudbrain.Cloudbrain.Spec != nil { + specMap[cloudbrain.Cloudbrain.Spec.AiCenterCode+"/"+cloudbrain.Cloudbrain.Spec.AccCardType] = cloudbrain.Cloudbrain.Spec + } + } + } + + cloudBrainCenterCodeAndCardTypeInfo := getcloudBrainCenterCodeAndCardTypeInfo(ciTasks, beginTime, endTime) + + resourceQueues, err := models.GetCanUseCardInfo() + if err != nil { + log.Info("GetCanUseCardInfo err: %v", err) + return + } + cardsTotalDurationMap := make(map[string]int) + for _, resourceQueue := range resourceQueues { + cardsTotalDurationMap[resourceQueue.Cluster+"/"+resourceQueue.AiCenterName+"/"+resourceQueue.AiCenterCode+"/"+resourceQueue.AccCardType+"/"+resourceQueue.ComputeResource] = resourceQueue.CardsTotalNum * 1 * 60 * 60 + } + + for centerCode, CardTypeInfo := range cloudBrainCenterCodeAndCardTypeInfo { + for cardType, cardDuration := range CardTypeInfo { + spec := specMap[centerCode+"/"+cardType] + if spec != nil { + if err := models.DeleteCloudbrainDurationStatisticHour(dayTime, hourTime, centerCode, cardType); err != nil { + log.Error("DeleteCloudbrainDurationStatisticHour failed: %v", err.Error()) + return + } + if _, ok := cardsTotalDurationMap[spec.Cluster+"/"+spec.AiCenterName+"/"+centerCode+"/"+cardType+"/"+spec.ComputeResource]; !ok { + cardsTotalDurationMap[spec.Cluster+"/"+spec.AiCenterName+"/"+centerCode+"/"+cardType+"/"+spec.ComputeResource] = 0 + } + cloudbrainDurationStat := models.CloudbrainDurationStatistic{ + DateTime: dateTime, + DayTime: dayTime, + HourTime: hourTime, + Cluster: spec.Cluster, + AiCenterName: spec.AiCenterName, + AiCenterCode: centerCode, + AccCardType: cardType, + ComputeResource: spec.ComputeResource, + CardsUseDuration: cardDuration, + CardsTotalDuration: cardsTotalDurationMap[spec.Cluster+"/"+spec.AiCenterName+"/"+centerCode+"/"+cardType+"/"+spec.ComputeResource], + CreatedUnix: timeutil.TimeStampNow(), + } + if _, err = models.InsertCloudbrainDurationStatistic(&cloudbrainDurationStat); err != nil { + log.Error("Insert cloudbrainDurationStat failed: %v", err.Error()) + } + delete(cardsTotalDurationMap, spec.Cluster+"/"+spec.AiCenterName+"/"+centerCode+"/"+cardType+"/"+spec.ComputeResource) + } + } + } + + for key, cardsTotalDuration := range cardsTotalDurationMap { + if err := models.DeleteCloudbrainDurationStatisticHour(dayTime, hourTime, strings.Split(key, "/")[2], strings.Split(key, "/")[3]); err != nil { + log.Error("DeleteCloudbrainDurationStatisticHour failed: %v", err.Error()) + return + } + cloudbrainDurationStat := models.CloudbrainDurationStatistic{ + DateTime: dateTime, + DayTime: dayTime, + HourTime: hourTime, + Cluster: strings.Split(key, "/")[0], + AiCenterName: strings.Split(key, "/")[1], + AiCenterCode: strings.Split(key, "/")[2], + AccCardType: strings.Split(key, "/")[3], + ComputeResource: strings.Split(key, "/")[4], + CardsUseDuration: 0, + CardsTotalDuration: cardsTotalDuration, + CreatedUnix: timeutil.TimeStampNow(), + } + if _, err = models.InsertCloudbrainDurationStatistic(&cloudbrainDurationStat); err != nil { + log.Error("Insert cloudbrainDurationStat failed: %v", err.Error()) + } + } + + log.Info("finish summary cloudbrainDurationStat") +} + +func getcloudBrainCenterCodeAndCardTypeInfo(ciTasks []*models.CloudbrainInfo, beginTime int64, endTime int64) map[string]map[string]int { + var WorkServerNumber int + var AccCardsNum int + cloudBrainCenterCodeAndCardType := make(map[string]map[string]int) + for _, cloudbrain := range ciTasks { + + if cloudbrain.Cloudbrain.StartTime == 0 { + cloudbrain.Cloudbrain.StartTime = cloudbrain.Cloudbrain.CreatedUnix + } + if cloudbrain.Cloudbrain.EndTime == 0 { + cloudbrain.Cloudbrain.EndTime = cloudbrain.Cloudbrain.UpdatedUnix + } + if cloudbrain.Cloudbrain.WorkServerNumber >= 1 { + WorkServerNumber = cloudbrain.Cloudbrain.WorkServerNumber + } else { + WorkServerNumber = 1 + } + if cloudbrain.Cloudbrain.Spec == nil { + AccCardsNum = 1 + } else { + AccCardsNum = cloudbrain.Cloudbrain.Spec.AccCardsNum + } + if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode]; !ok { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode] = make(map[string]int) + } + + if cloudbrain.Cloudbrain.Status == string(models.ModelArtsRunning) { + if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType]; !ok { + if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) + } else { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) + } + } else { + if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(beginTime)) + } else { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(endTime) - int(cloudbrain.Cloudbrain.StartTime)) + } + } + } else { + if _, ok := cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType]; !ok { + if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(beginTime)) + } else { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] = AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(cloudbrain.Cloudbrain.StartTime)) + } + } else { + if int64(cloudbrain.Cloudbrain.StartTime) < beginTime { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(beginTime)) + } else { + cloudBrainCenterCodeAndCardType[cloudbrain.Cloudbrain.Spec.AiCenterCode][cloudbrain.Cloudbrain.Spec.AccCardType] += AccCardsNum * WorkServerNumber * (int(cloudbrain.Cloudbrain.EndTime) - int(cloudbrain.Cloudbrain.StartTime)) + } + } + + } + } + + return cloudBrainCenterCodeAndCardType +} diff --git a/routers/repo/dataset.go b/routers/repo/dataset.go index f0e41024b..16e21e43b 100755 --- a/routers/repo/dataset.go +++ b/routers/repo/dataset.go @@ -523,6 +523,7 @@ func ReferenceDatasetAvailable(ctx *context.Context) { PublicOnly: true, NeedAttachment: false, CloudBrainType: models.TypeCloudBrainAll, + SearchOrderBy: models.SearchOrderByDefault, } dataset, _ := models.GetDatasetByRepo(&models.Repository{ID: ctx.Repo.Repository.ID}) if dataset != nil { @@ -538,6 +539,7 @@ func PublicDatasetMultiple(ctx *context.Context) { PublicOnly: true, NeedAttachment: true, CloudBrainType: ctx.QueryInt("type"), + SearchOrderBy: models.SearchOrderByDefault, } datasetMultiple(ctx, opts) diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go index b78bdebd3..e29bf0abc 100755 --- a/routers/repo/grampus.go +++ b/routers/repo/grampus.go @@ -12,6 +12,8 @@ import ( "strings" "time" + "code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" + "code.gitea.io/gitea/modules/dataset" "code.gitea.io/gitea/services/cloudbrain/resource" @@ -35,6 +37,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + cloudbrainService "code.gitea.io/gitea/services/cloudbrain" ) const ( @@ -135,10 +138,15 @@ func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) err ctx.Data["datasetType"] = models.TypeCloudBrainOne waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, models.GPUResource, models.JobTypeTrain) ctx.Data["WaitCount"] = waitCount + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.GPUResource) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount + } else if processType == grampus.ProcessorTypeNPU { ctx.Data["datasetType"] = models.TypeCloudBrainTwo waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, models.NPUResource, models.JobTypeTrain) ctx.Data["WaitCount"] = waitCount + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.NPUResource) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount } if ctx.Cloudbrain != nil { @@ -300,7 +308,7 @@ func grampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain } //check count limit - count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.GPUResource) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.GPUResource) if err != nil { log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"]) grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) @@ -570,7 +578,7 @@ func grampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain } //check count limit - count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.NPUResource) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.NPUResource) if err != nil { log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"]) grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) @@ -908,10 +916,7 @@ func GrampusTrainJobShow(ctx *context.Context) { ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task) ctx.Data["displayJobName"] = task.DisplayJobName - aiCenterInfo := strings.Split(task.AiCenter, "+") - if len(aiCenterInfo) == 2 { - ctx.Data["ai_center"] = aiCenterInfo[1] - } + ctx.Data["ai_center"] = cloudbrainService.GetAiCenterShow(task.AiCenter,ctx) ctx.HTML(http.StatusOK, tplGrampusTrainJobShow) } diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index 6e44b3cd2..be59b0f3f 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -15,6 +15,8 @@ import ( "time" "unicode/utf8" + "code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" + "code.gitea.io/gitea/modules/dataset" "code.gitea.io/gitea/modules/modelarts_cd" @@ -144,6 +146,8 @@ func notebookNewDataPrepare(ctx *context.Context) error { waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") ctx.Data["WaitCount"] = waitCount + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug)) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount return nil } @@ -162,50 +166,6 @@ func prepareCloudbrainTwoDebugSpecs(ctx *context.Context) { ctx.Data["Specs"] = noteBookSpecs } -func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) { - ctx.Data["PageIsNotebook"] = true - jobName := form.JobName - uuid := form.Attachment - description := form.Description - flavor := form.Flavor - - count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) - if err != nil { - log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) - ctx.RenderWithErr("system error", tplModelArtsNotebookNew, &form) - return - } else { - if count >= 1 { - log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) - ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplModelArtsNotebookNew, &form) - return - } - } - _, err = models.GetCloudbrainByName(jobName) - if err == nil { - log.Error("the job name did already exist", ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) - ctx.RenderWithErr("the job name did already exist", tplModelArtsNotebookNew, &form) - return - } else { - if !models.IsErrJobNotExist(err) { - log.Error("system error, %v", err, ctx.Data["MsgID"]) - cloudBrainNewDataPrepare(ctx) - ctx.RenderWithErr("system error", tplModelArtsNotebookNew, &form) - return - } - } - - err = modelarts.GenerateTask(ctx, jobName, uuid, description, flavor) - if err != nil { - ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form) - return - } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") -} - func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm) { ctx.Data["PageIsNotebook"] = true displayJobName := form.DisplayJobName @@ -225,7 +185,8 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm } defer lock.UnLock() - count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug)) + if err != nil { log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) notebookNewDataPrepare(ctx) @@ -272,7 +233,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm } if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID) - cloudBrainNewDataPrepare(ctx) + notebookNewDataPrepare(ctx) ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsNotebookNew, &form) return } @@ -450,7 +411,8 @@ func NotebookRestart(ctx *context.Context) { break } - count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug)) + if err != nil { log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) errorMsg = "system error" @@ -798,6 +760,8 @@ func trainJobNewDataPrepare(ctx *context.Context) error { ctx.Data["datasetType"] = models.TypeCloudBrainTwo waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") ctx.Data["WaitCount"] = waitCount + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain)) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount setMultiNodeIfConfigureMatch(ctx) @@ -966,6 +930,8 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { ctx.Data["config_list"] = configList.ParaConfigs waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") ctx.Data["WaitCount"] = waitCount + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain)) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount return nil } @@ -1012,7 +978,8 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) } defer lock.UnLock() - count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain)) + if err != nil { log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) trainJobNewDataPrepare(ctx) @@ -1345,6 +1312,36 @@ func getUserCommand(engineId int, req *modelarts.GenerateTrainJobReq) (string, s return userCommand, userImageUrl } +func getInfJobUserCommand(engineId int, req *modelarts.GenerateInferenceJobReq) (string, string) { + userImageUrl := "" + userCommand := "" + if engineId < 0 { + tmpCodeObsPath := strings.Trim(req.CodeObsPath, "/") + tmpCodeObsPaths := strings.Split(tmpCodeObsPath, "/") + lastCodeDir := "code" + if len(tmpCodeObsPaths) > 0 { + lastCodeDir = tmpCodeObsPaths[len(tmpCodeObsPaths)-1] + } + userCommand = "/bin/bash /home/work/run_train.sh 's3://" + req.CodeObsPath + "' '" + lastCodeDir + "/" + req.BootFile + "' '/tmp/log/train.log' --'data_url'='s3://" + req.DataUrl + "' --'train_url'='s3://" + req.TrainUrl + "'" + var versionInfos modelarts.VersionInfo + if err := json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { + log.Info("json parse err." + err.Error()) + } else { + for _, engine := range versionInfos.Version { + if engine.ID == engineId { + userImageUrl = engine.Url + break + } + } + } + for _, param := range req.Parameters { + userCommand += " --'" + param.Label + "'='" + param.Value + "'" + } + return userCommand, userImageUrl + } + return userCommand, userImageUrl +} + func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) { ctx.Data["PageIsTrainJob"] = true var jobID = ctx.Params(":jobid") @@ -1356,7 +1353,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ return } - count, err := models.GetCloudbrainTrainJobCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain)) if err != nil { log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) trainJobNewVersionDataPrepare(ctx) @@ -2007,7 +2004,8 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference } defer lock.UnLock() - count, err := models.GetCloudbrainInferenceJobCountByUserID(ctx.User.ID) + count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeInference)) + if err != nil { log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"]) inferenceJobErrorNewDataPrepare(ctx, form) @@ -2203,6 +2201,10 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference JobType: string(models.JobTypeInference), } + userCommand, userImageUrl := getInfJobUserCommand(engineID, req) + req.UserCommand = userCommand + req.UserImageUrl = userImageUrl + err = modelarts.GenerateInferenceJob(ctx, req) if err != nil { log.Error("GenerateTrainJob failed:%v", err.Error()) @@ -2409,6 +2411,8 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error { ctx.Data["datasetType"] = models.TypeCloudBrainTwo waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") ctx.Data["WaitCount"] = waitCount + NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeInference)) + ctx.Data["NotStopTaskCount"] = NotStopTaskCount return nil } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 193555ffd..fd8b274e6 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -6,17 +6,18 @@ package routes import ( "bytes" - "code.gitea.io/gitea/routers/badge" - "code.gitea.io/gitea/routers/reward/point" - "code.gitea.io/gitea/routers/task" - badge_service "code.gitea.io/gitea/services/badge" - "code.gitea.io/gitea/services/reward" "encoding/gob" "net/http" "path" "text/template" "time" + "code.gitea.io/gitea/routers/badge" + "code.gitea.io/gitea/routers/reward/point" + "code.gitea.io/gitea/routers/task" + badge_service "code.gitea.io/gitea/services/badge" + "code.gitea.io/gitea/services/reward" + "code.gitea.io/gitea/routers/modelapp" "code.gitea.io/gitea/modules/slideimage" @@ -348,6 +349,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/action/notification", routers.ActionNotification) m.Get("/recommend/home", routers.RecommendHomeInfo) m.Get("/dashboard/invitation", routers.GetMapInfo) + m.Get("/resource_desc", routers.HomeResoruceDesc) //m.Get("/recommend/org", routers.RecommendOrgFromPromote) //m.Get("/recommend/repo", routers.RecommendRepoFromPromote) m.Get("/recommend/userrank/:index", routers.GetUserRankFromPromote) diff --git a/services/cloudbrain/cloudbrainTask/count.go b/services/cloudbrain/cloudbrainTask/count.go new file mode 100644 index 000000000..a9b254618 --- /dev/null +++ b/services/cloudbrain/cloudbrainTask/count.go @@ -0,0 +1,86 @@ +package cloudbrainTask + +import ( + "fmt" + "strconv" + + "code.gitea.io/gitea/models" +) + +type StatusInfo struct { + CloudBrainTypes []int + JobType []models.JobType + NotFinalStatuses []string + ComputeResource string +} + +var cloudbrainOneNotFinalStatuses = []string{string(models.JobWaiting), string(models.JobRunning)} +var cloudbrainTwoNotFinalStatuses = []string{string(models.ModelArtsTrainJobInit), string(models.ModelArtsTrainJobImageCreating), string(models.ModelArtsTrainJobSubmitTrying), string(models.ModelArtsTrainJobWaiting), string(models.ModelArtsTrainJobRunning), string(models.ModelArtsTrainJobScaling), string(models.ModelArtsTrainJobCheckInit), string(models.ModelArtsTrainJobCheckRunning), string(models.ModelArtsTrainJobCheckRunningCompleted)} +var grampusTwoNotFinalStatuses = []string{models.GrampusStatusWaiting, models.GrampusStatusRunning} +var StatusInfoDict = map[string]StatusInfo{string(models.JobTypeDebug) + "-" + strconv.Itoa(models.TypeCloudBrainOne): { + CloudBrainTypes: []int{models.TypeCloudBrainOne}, + JobType: []models.JobType{models.JobTypeDebug}, + NotFinalStatuses: cloudbrainOneNotFinalStatuses, + ComputeResource: models.GPUResource, +}, string(models.JobTypeTrain) + "-" + strconv.Itoa(models.TypeCloudBrainOne): { + CloudBrainTypes: []int{models.TypeCloudBrainOne}, + JobType: []models.JobType{models.JobTypeTrain}, + NotFinalStatuses: cloudbrainOneNotFinalStatuses, + ComputeResource: models.GPUResource, +}, string(models.JobTypeInference) + "-" + strconv.Itoa(models.TypeCloudBrainOne): { + CloudBrainTypes: []int{models.TypeCloudBrainOne}, + JobType: []models.JobType{models.JobTypeInference}, + NotFinalStatuses: cloudbrainOneNotFinalStatuses, + ComputeResource: models.GPUResource, +}, string(models.JobTypeBenchmark) + "-" + strconv.Itoa(models.TypeCloudBrainOne): { + CloudBrainTypes: []int{models.TypeCloudBrainOne}, + JobType: []models.JobType{models.JobTypeBenchmark, models.JobTypeBrainScore, models.JobTypeSnn4imagenet}, + NotFinalStatuses: cloudbrainOneNotFinalStatuses, + ComputeResource: models.GPUResource, +}, string(models.JobTypeDebug) + "-" + strconv.Itoa(models.TypeCloudBrainTwo): { + CloudBrainTypes: []int{models.TypeCloudBrainTwo, models.TypeCDCenter}, + JobType: []models.JobType{models.JobTypeDebug}, + NotFinalStatuses: []string{string(models.ModelArtsCreateQueue), string(models.ModelArtsCreating), string(models.ModelArtsStarting), string(models.ModelArtsReadyToStart), string(models.ModelArtsResizing), string(models.ModelArtsStartQueuing), string(models.ModelArtsRunning), string(models.ModelArtsRestarting)}, + ComputeResource: models.NPUResource, +}, string(models.JobTypeTrain) + "-" + strconv.Itoa(models.TypeCloudBrainTwo): { + CloudBrainTypes: []int{models.TypeCloudBrainTwo}, + JobType: []models.JobType{models.JobTypeTrain}, + NotFinalStatuses: cloudbrainTwoNotFinalStatuses, + ComputeResource: models.NPUResource, +}, string(models.JobTypeInference) + "-" + strconv.Itoa(models.TypeCloudBrainTwo): { + CloudBrainTypes: []int{models.TypeCloudBrainTwo}, + JobType: []models.JobType{models.JobTypeInference}, + NotFinalStatuses: cloudbrainTwoNotFinalStatuses, + ComputeResource: models.NPUResource, +}, string(models.JobTypeTrain) + "-" + strconv.Itoa(models.TypeC2Net) + "-" + models.GPUResource: { + CloudBrainTypes: []int{models.TypeC2Net}, + JobType: []models.JobType{models.JobTypeTrain}, + NotFinalStatuses: grampusTwoNotFinalStatuses, + ComputeResource: models.GPUResource, +}, string(models.JobTypeTrain) + "-" + strconv.Itoa(models.TypeC2Net) + "-" + models.NPUResource: { + CloudBrainTypes: []int{models.TypeC2Net}, + JobType: []models.JobType{models.JobTypeTrain}, + NotFinalStatuses: grampusTwoNotFinalStatuses, + ComputeResource: models.NPUResource, +}} + +func GetNotFinalStatusTaskCount(uid int64, cloudbrainType int, jobType string, computeResource ...string) (int, error) { + jobNewType := jobType + if jobType == string(models.JobTypeSnn4imagenet) || jobType == string(models.JobTypeBrainScore) { + jobNewType = string(models.JobTypeBenchmark) + } + + key := jobNewType + "-" + strconv.Itoa(cloudbrainType) + if len(computeResource) > 0 { + key = key + "-" + computeResource[0] + } + + if statusInfo, ok := StatusInfoDict[key]; ok { + + return models.GetNotFinalStatusTaskCount(uid, statusInfo.NotFinalStatuses, statusInfo.JobType, statusInfo.CloudBrainTypes, statusInfo.ComputeResource) + + } else { + return 0, fmt.Errorf("Can not find the status info.") + } + +} diff --git a/services/cloudbrain/util.go b/services/cloudbrain/util.go new file mode 100644 index 000000000..ab738927e --- /dev/null +++ b/services/cloudbrain/util.go @@ -0,0 +1,33 @@ +package cloudbrain + +import ( + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + "strings" +) + +func GetAiCenterShow(aiCenter string,ctx *context.Context) string{ + aiCenterInfo := strings.Split(aiCenter, "+") + + if len(aiCenterInfo) == 2{ + if setting.C2NetMapInfo!=nil { + if info,ok:=setting.C2NetMapInfo[aiCenterInfo[0]];ok { + if ctx.Language() == "zh-CN" { + return info.Content + } else { + return info.ContentEN + } + }else{ + return aiCenterInfo[1] + } + + }else{ + return aiCenterInfo[1] + } + + } + + return "" + + +} diff --git a/templates/base/footer_content.tmpl b/templates/base/footer_content.tmpl index cdc2cf549..cb732bbbe 100755 --- a/templates/base/footer_content.tmpl +++ b/templates/base/footer_content.tmpl @@ -36,7 +36,8 @@ {{else}} {{.i18n.Tr "custom.foot.advice_feedback"}} {{end}} - + {{.i18n.Tr "custom.resource_description"}} + {{template "custom/extra_links_footer" .}} @@ -44,7 +45,7 @@
{{.i18n.Tr "custom.foot.copyright"}} 京ICP备18004880号
- {{.i18n.Tr "Powered_by 鹏城实验室云脑、"}}Trustie确实{{.i18n.Tr "、gitea"}} + {{.i18n.Tr "home.powerdby"}}Trustie确实{{.i18n.Tr "、Gitea"}}
diff --git a/templates/base/footer_content_fluid.tmpl b/templates/base/footer_content_fluid.tmpl index 24b18e94d..723c78045 100755 --- a/templates/base/footer_content_fluid.tmpl +++ b/templates/base/footer_content_fluid.tmpl @@ -33,6 +33,7 @@ {{else}} {{.i18n.Tr "custom.foot.advice_feedback"}} {{end}} + {{.i18n.Tr "custom.resource_description"}} {{template "custom/extra_links_footer" .}} diff --git a/templates/custom/alert_cb.tmpl b/templates/custom/alert_cb.tmpl new file mode 100644 index 000000000..c4c8d9998 --- /dev/null +++ b/templates/custom/alert_cb.tmpl @@ -0,0 +1,11 @@ +{{if .NotStopTaskCount}} +
+
+ +
+
{{.i18n.Tr "repo.cloudbrain.morethanonejob1" | Safe }}
+
{{.i18n.Tr "repo.cloudbrain.morethanonejob2" | Safe}}
+
+
+
+{{end}} \ No newline at end of file diff --git a/templates/custom/max_log.tmpl b/templates/custom/max_log.tmpl new file mode 100644 index 000000000..978274f4e --- /dev/null +++ b/templates/custom/max_log.tmpl @@ -0,0 +1,40 @@ +
+ +
+ \ No newline at end of file diff --git a/templates/repo/badge.tmpl b/templates/repo/badge.tmpl index 61b542be8..86b482c4a 100644 --- a/templates/repo/badge.tmpl +++ b/templates/repo/badge.tmpl @@ -1,7 +1,7 @@
{{range .AllBadges }}
-
{{.CategoryName}}   (已点亮{{.LightedNum}}个)
+
{{.CategoryName}}   (已点亮 {{.LightedNum}} 个)
diff --git a/templates/repo/cloudbrain/benchmark/new.tmpl b/templates/repo/cloudbrain/benchmark/new.tmpl index 13665c036..03583779e 100755 --- a/templates/repo/cloudbrain/benchmark/new.tmpl +++ b/templates/repo/cloudbrain/benchmark/new.tmpl @@ -32,7 +32,10 @@
{{template "repo/header" .}}
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.evaluate_job.new_job"}}

@@ -136,6 +139,8 @@ {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} name="spec_id"> + + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -148,7 +153,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} @@ -248,6 +253,8 @@ {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} name="spec_id"> + + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -278,7 +285,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} @@ -334,6 +341,8 @@ placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}" name="spec_id"> + + {{.i18n.Tr "custom.resource_description"}}
@@ -347,7 +356,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/cloudbrain/benchmark/show.tmpl b/templates/repo/cloudbrain/benchmark/show.tmpl index 84d16d00c..de68a3241 100755 --- a/templates/repo/cloudbrain/benchmark/show.tmpl +++ b/templates/repo/cloudbrain/benchmark/show.tmpl @@ -524,14 +524,17 @@
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} - +
+ + {{$.i18n.Tr "repo.modelarts.download_log"}} +
@@ -549,12 +552,16 @@
-
-
-
- - -

+                                
+
+
+ + + + + + +

                              
@@ -565,6 +572,7 @@
+ {{template "custom/max_log" .}} {{end}} {{template "base/paginate" .}}
diff --git a/templates/repo/cloudbrain/inference/new.tmpl b/templates/repo/cloudbrain/inference/new.tmpl index 630df7a2e..df737f995 100644 --- a/templates/repo/cloudbrain/inference/new.tmpl +++ b/templates/repo/cloudbrain/inference/new.tmpl @@ -40,7 +40,10 @@
{{template "repo/header" .}}
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.train_job.new_infer"}} @@ -256,6 +259,8 @@ + + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -269,7 +274,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/cloudbrain/inference/show.tmpl b/templates/repo/cloudbrain/inference/show.tmpl index 546f16848..fe127b89d 100644 --- a/templates/repo/cloudbrain/inference/show.tmpl +++ b/templates/repo/cloudbrain/inference/show.tmpl @@ -535,14 +535,17 @@
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} - +
+ + {{$.i18n.Tr "repo.modelarts.fullscreen_log_file"}} +
@@ -559,13 +562,17 @@
-
+ style="height: 300px !important; overflow: auto;"> +
-
- - -

+                                
+ + + + + + +

                              
@@ -589,7 +596,7 @@

- + {{template "custom/max_log" .}} {{end}}
diff --git a/templates/repo/cloudbrain/new.tmpl b/templates/repo/cloudbrain/new.tmpl index fb7ccbed1..b75e75cdf 100755 --- a/templates/repo/cloudbrain/new.tmpl +++ b/templates/repo/cloudbrain/new.tmpl @@ -24,10 +24,13 @@
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}
{{.CsrfTokenHtml}} @@ -149,6 +152,8 @@ {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} name="spec_id"> + + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -197,7 +202,7 @@
- - {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.train_job.new"}}

@@ -216,6 +219,8 @@ {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} name="spec_id"> + +
{{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -229,7 +234,7 @@
-
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} - +
+ + {{$.i18n.Tr "repo.modelarts.fullscreen_log_file"}} +
@@ -552,7 +555,11 @@
- + + + + +

                             
@@ -581,6 +588,7 @@
+ {{template "custom/max_log" .}} {{end}} {{template "base/paginate" .}}
diff --git a/templates/repo/grampus/trainjob/gpu/new.tmpl b/templates/repo/grampus/trainjob/gpu/new.tmpl index cd4970632..e3bb6ceb2 100755 --- a/templates/repo/grampus/trainjob/gpu/new.tmpl +++ b/templates/repo/grampus/trainjob/gpu/new.tmpl @@ -63,7 +63,10 @@ {{template "repo/header" .}}
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.train_job.new"}}

@@ -189,6 +192,8 @@
+ + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -202,7 +207,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/grampus/trainjob/npu/new.tmpl b/templates/repo/grampus/trainjob/npu/new.tmpl index 925ae3915..22cc6dc17 100755 --- a/templates/repo/grampus/trainjob/npu/new.tmpl +++ b/templates/repo/grampus/trainjob/npu/new.tmpl @@ -58,7 +58,10 @@ {{template "repo/header" .}}
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.train_job.new"}}

@@ -199,6 +202,8 @@
+ + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -226,7 +231,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/grampus/trainjob/show.tmpl b/templates/repo/grampus/trainjob/show.tmpl index 67c415488..0813cf477 100755 --- a/templates/repo/grampus/trainjob/show.tmpl +++ b/templates/repo/grampus/trainjob/show.tmpl @@ -520,14 +520,17 @@
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} - +
+ + {{$.i18n.Tr "repo.modelarts.fullscreen_log_file"}} +
@@ -548,7 +551,11 @@
- + + + + +

                             
@@ -576,6 +583,7 @@
+ {{template "custom/max_log" .}} {{end}} {{template "base/paginate" .}}
diff --git a/templates/repo/modelarts/inferencejob/new.tmpl b/templates/repo/modelarts/inferencejob/new.tmpl index d2f6a8194..48d64cf56 100644 --- a/templates/repo/modelarts/inferencejob/new.tmpl +++ b/templates/repo/modelarts/inferencejob/new.tmpl @@ -39,7 +39,10 @@
{{template "repo/header" .}}
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.train_job.new_infer"}} @@ -276,6 +279,8 @@
+ + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -297,7 +302,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/modelarts/inferencejob/show.tmpl b/templates/repo/modelarts/inferencejob/show.tmpl index 7d671ae4c..98240fbd4 100644 --- a/templates/repo/modelarts/inferencejob/show.tmpl +++ b/templates/repo/modelarts/inferencejob/show.tmpl @@ -460,14 +460,17 @@ td, th {
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} - +
+ + {{$.i18n.Tr "repo.modelarts.fullscreen_log_file"}} +
@@ -486,8 +489,12 @@ td, th {
- - + + + + + +

                                 
@@ -510,12 +517,8 @@ td, th {
+ {{template "custom/max_log" .}} {{end}} - - - - -

diff --git a/templates/repo/modelarts/notebook/new.tmpl b/templates/repo/modelarts/notebook/new.tmpl index f9c4670a5..e149d6095 100755 --- a/templates/repo/modelarts/notebook/new.tmpl +++ b/templates/repo/modelarts/notebook/new.tmpl @@ -11,10 +11,13 @@
- {{template "base/alert" .}} -
+ {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + + {{template "custom/alert_cb" .}} {{.CsrfTokenHtml}}

@@ -82,6 +85,8 @@ + + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -102,7 +107,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} @@ -178,9 +183,9 @@ document.getElementById("mask").style.display = "none" } } - $('select.dropdown') .dropdown(); + $(function() { $("#cloudbrain_job_type").change(function() { if ($(this).val() == 'BENCHMARK') { @@ -209,4 +214,5 @@ shared_memory: {{$.i18n.Tr "cloudbrain.shared_memory"}}, }); })(); + console.log("-------------:",{{.NotStopTaskCount}}) diff --git a/templates/repo/modelarts/trainjob/new.tmpl b/templates/repo/modelarts/trainjob/new.tmpl index 0e1e8eedb..d52ce26ab 100755 --- a/templates/repo/modelarts/trainjob/new.tmpl +++ b/templates/repo/modelarts/trainjob/new.tmpl @@ -63,7 +63,10 @@ {{template "repo/header" .}}
- {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.train_job.new"}}

@@ -247,6 +250,8 @@
+ + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -288,7 +293,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/modelarts/trainjob/show.tmpl b/templates/repo/modelarts/trainjob/show.tmpl index e95a1233d..74c124e76 100755 --- a/templates/repo/modelarts/trainjob/show.tmpl +++ b/templates/repo/modelarts/trainjob/show.tmpl @@ -548,14 +548,17 @@
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} - +
+ + {{$.i18n.Tr "repo.modelarts.fullscreen_log_file"}} +
@@ -577,7 +580,11 @@
+ + + +

                             
@@ -609,6 +616,7 @@
+ {{template "custom/max_log" .}} {{end}} {{template "base/paginate" .}}
@@ -715,6 +723,7 @@

+
{{template "base/footer" .}} diff --git a/templates/repo/modelarts/trainjob/version_new.tmpl b/templates/repo/modelarts/trainjob/version_new.tmpl index ea01d9739..a65537260 100644 --- a/templates/repo/modelarts/trainjob/version_new.tmpl +++ b/templates/repo/modelarts/trainjob/version_new.tmpl @@ -236,6 +236,8 @@
+ + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} diff --git a/templates/repo/modelmanage/convertIndex.tmpl b/templates/repo/modelmanage/convertIndex.tmpl index 92eefca2e..05b5306c8 100644 --- a/templates/repo/modelmanage/convertIndex.tmpl +++ b/templates/repo/modelmanage/convertIndex.tmpl @@ -103,7 +103,7 @@
- {{if eq .SrcEngine 0}}PyTorch {{else if eq .SrcEngine 1}}TensorFlow{{else if eq .SrcEngine 2}}MindSpore {{end}} + {{if eq .SrcEngine 0}}PyTorch {{else if eq .SrcEngine 1}}TensorFlow {{else if eq .SrcEngine 2}}MindSpore {{else if eq .SrcEngine 4}}PaddlePaddle {{else if eq .SrcEngine 6}}MXNet {{end}}
{{if eq .DestFormat 0}}ONNX {{else if eq .DestFormat 1}}TensorRT {{end}} @@ -532,7 +532,7 @@ } } function isModel(filename){ - var postfix=[".pth",".pkl",".onnx",".mindir",".ckpt",".pb"]; + var postfix=[".pth",".pkl",".onnx",".mindir",".ckpt",".pb",".pdmodel",".pdiparams",".params",".json"]; for(var i =0; iPyTorch"; html +=""; html +=""; + html +=""; + html +=""; $('#SrcEngine').html(html); srcEngineChanged(); } diff --git a/templates/repo/modelmanage/convertshowinfo.tmpl b/templates/repo/modelmanage/convertshowinfo.tmpl index 70aa301d5..f4db2237c 100644 --- a/templates/repo/modelmanage/convertshowinfo.tmpl +++ b/templates/repo/modelmanage/convertshowinfo.tmpl @@ -355,7 +355,7 @@ td, th {
- {{if eq .SrcEngine 0}}PyTorch {{else if eq .SrcEngine 1}}Tensorflow{{else if eq .SrcEngine 2}}MindSpore {{end}} + {{if eq .SrcEngine 0}}PyTorch {{else if eq .SrcEngine 1}}Tensorflow{{else if eq .SrcEngine 2}}MindSpore {{else if eq .SrcEngine 4}}PaddlePaddle{{else if eq .SrcEngine 6}} MXNet{{end}}
diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index b2994f0c2..062e1908f 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -565,4 +565,5 @@ $("#choice_Engine").removeClass('disabled'); } } + \ No newline at end of file diff --git a/templates/repo/modelmanage/showinfo.tmpl b/templates/repo/modelmanage/showinfo.tmpl index 4cc0305ed..6e4aa2b5a 100644 --- a/templates/repo/modelmanage/showinfo.tmpl +++ b/templates/repo/modelmanage/showinfo.tmpl @@ -285,7 +285,7 @@ function transObj(data){ DatasetName:TrainTaskInfo.DatasetName || '--', Parameters:TrainTaskInfo.Parameters || '--', FlavorName:TrainTaskInfo.FlavorName || '--', - WorkServerNumber:TrainTaskInfo.WorkServerNumber || '--', + WorkServerNumber:TrainTaskInfo.WorkServerNumber || '1', Parameters:Parameters, EngineName:EngineName, DisplayJobName:TrainTaskInfo.DisplayJobName || '--', diff --git a/templates/repo/modelsafety/new.tmpl b/templates/repo/modelsafety/new.tmpl index 07bcd311d..94f52cc1f 100644 --- a/templates/repo/modelsafety/new.tmpl +++ b/templates/repo/modelsafety/new.tmpl @@ -55,7 +55,10 @@
{{$Grampus := (or (eq (index (SubJumpablePath .Link) 1) "create_grampus_gpu") (eq (index (SubJumpablePath .Link) 1) "create_grampus_npu"))}} - {{template "base/alert" .}} + {{if eq .NotStopTaskCount 0}} + {{template "base/alert" .}} + {{end}} + {{template "custom/alert_cb" .}}

{{.i18n.Tr "repo.modelarts.evaluate_job.new_job"}}

@@ -299,6 +302,8 @@ {{if .CloudBrainPaySwitch}}blance="{{.PointAccount.Balance}}"{{end}} name="spec_id"> + + {{.i18n.Tr "custom.resource_description"}} {{if .CloudBrainPaySwitch}}
{{$.i18n.Tr "points.balance_of_points"}}{{.PointAccount.Balance}}{{$.i18n.Tr "points.points"}}{{$.i18n.Tr "points.expected_time"}}{{$.i18n.Tr "points.hours"}} @@ -311,7 +316,7 @@
- {{.i18n.Tr "repo.cloudbrain.cancel"}} diff --git a/templates/repo/modelsafety/show.tmpl b/templates/repo/modelsafety/show.tmpl index 6954f6f6b..1f0d2d3aa 100644 --- a/templates/repo/modelsafety/show.tmpl +++ b/templates/repo/modelsafety/show.tmpl @@ -467,13 +467,17 @@
-
+
{{$.i18n.Tr "repo.modelarts.download_log"}} +
+ + {{$.i18n.Tr "repo.modelarts.fullscreen_log_file"}} +
@@ -490,13 +494,17 @@
-
-
-
- - -

+                                style="height: 300px !important; overflow: auto;">
+                                
+
+
+ + + + + + +

                              
@@ -571,6 +579,7 @@
+ {{template "custom/max_log" .}} {{template "base/paginate" .}}
diff --git a/templates/resource_desc.tmpl b/templates/resource_desc.tmpl new file mode 100644 index 000000000..066f5d090 --- /dev/null +++ b/templates/resource_desc.tmpl @@ -0,0 +1,92 @@ +{{template "base/head_home" .}} + +
+

平台资源说明

+
+ + + + + + + + + + + + + + + + +
集群计算资源任务类型卡类型可用镜像网络类型数据集处理方式容器目录说明示例代码仓备注
+
+ +{{template "base/footer" .}} + diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index d4e97a961..1310069f6 100755 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -21,7 +21,7 @@
{{range $k,$v :=.RecentBadges}} {{if le $k 3}} -
+
{{else}} {{end}} diff --git a/web_src/js/features/cloudbrainShow.js b/web_src/js/features/cloudbrainShow.js index 3aafcc1a6..d3338523d 100644 --- a/web_src/js/features/cloudbrainShow.js +++ b/web_src/js/features/cloudbrainShow.js @@ -14,8 +14,8 @@ export default async function initCloudrainSow() { }; } - function logScroll(version_name, repoPath, ID) { - let container = document.querySelector(`#log${version_name}`); + function logScroll(version_name, repoPath, ID, max = "", lines = 60) { + let container = document.querySelector(`#log${max}${version_name}`); let scrollTop = container.scrollTop; let scrollHeight = container.scrollHeight; let clientHeight = container.clientHeight; @@ -26,46 +26,90 @@ export default async function initCloudrainSow() { parseInt(scrollTop) + clientHeight - 1 == scrollHeight) && scrollLeft === 0 ) { - let end_line = $(`#log${version_name} input[name=end_line]`).val(); + let end_line = $(`#log${version_name} input[name=end_line${max}]`).val(); + $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css({ + "background-color": "#fff", + display: "block", + }); $.get( - `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=${end_line}&lines=50&order=desc`, + `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=${end_line}&lines=${lines}&order=desc`, (data) => { + $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css( + "display", + "none" + ); if (data.Lines == 0) { - $(`.message${version_name} #header`).text("您已翻阅至日志底部"); - $(`.message${version_name}`).css("display", "block"); - setTimeout(function () { - $(`.message${version_name}`).css("display", "none"); - }, 1000); + if (max) { + $("body").toast({ + class: "info", + message: `您已翻阅至日志底部,请稍后再试!`, + }); + } else { + $(`.message${version_name} #header`).text("您已翻阅至日志底部"); + $(`.message${version_name}`).css("display", "block"); + setTimeout(function () { + $(`.message${version_name}`).css("display", "none"); + }, 1000); + } } else { if (end_line === data.EndLine) { return; } else { - $(`#log${version_name} input[name=end_line]`).val(data.EndLine); - $(`#log${version_name}`).append("
" + data.Content);
+              $(`#log${version_name} input[name=end_line${max}]`).val(
+                data.EndLine
+              );
+              $(`#log${max}${version_name}`).append("
" + data.Content);
             }
           }
         }
       ).fail(function (err) {
+        $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
+          "display",
+          "none"
+        );
         console.log(err);
       });
     }
     if (scrollTop == 0 && scrollLeft == 0) {
-      let start_line = $(`#log${version_name} input[name=start_line]`).val();
+      let start_line = $(
+        `#log${version_name} input[name=start_line${max}]`
+      ).val();
+      $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css({
+        "background-color": "#fff",
+        display: "block",
+      });
       $.get(
-        `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=${start_line}&lines=50&order=asc`,
+        `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=${start_line}&lines=${lines}&order=asc`,
         (data) => {
+          $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
+            "display",
+            "none"
+          );
           if (data.Lines == 0) {
-            $(`.message${version_name} #header`).text("您已翻阅至日志顶部");
-            $(`.message${version_name}`).css("display", "block");
-            setTimeout(function () {
-              $(`.message${version_name}`).css("display", "none");
-            }, 1000);
+            if (max) {
+              $("body").toast({
+                class: "info",
+                message: `您已翻阅至日志顶部,请稍后再试!`,
+              });
+            } else {
+              $(`.message${version_name} #header`).text("您已翻阅至日志顶部");
+              $(`.message${version_name}`).css("display", "block");
+              setTimeout(function () {
+                $(`.message${version_name}`).css("display", "none");
+              }, 1000);
+            }
           } else {
-            $(`#log${version_name} input[name=start_line]`).val(data.StartLine); //如果变动就改变所对应的值
-            $(`#log${version_name}`).prepend("
" + data.Content);
+            $(`#log${version_name} input[name=start_line${max}]`).val(
+              data.StartLine
+            ); //如果变动就改变所对应的值
+            $(`#log${max}${version_name}`).prepend("
" + data.Content);
           }
         }
       ).fail(function (err) {
+        $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
+          "display",
+          "none"
+        );
         console.log(err);
       });
     }
@@ -96,51 +140,71 @@ export default async function initCloudrainSow() {
     }, 1);
   }
 
-  $(".log_top").click(function () {
-    // let logContentDom = document.querySelector('.log')
-    // if(!logContentDom)
-    //     return
-    // let version_name = $('.log_top').data('version')
+  function logTop(e) {
+    let max = e.currentTarget.getAttribute("data-max") || "";
+    let lines = !!max ? 100 : 60;
     let version_name = $(this).data("version");
-    let logContentDom = document.querySelector(`#log${version_name}`);
+    let logContentDom = document.querySelector(`#log${max}${version_name}`);
     let ID = $(`#accordion${version_name}`).data("jobid");
     let repoPath = $(`#accordion${version_name}`).data("repopath");
-    $(`#log_file${version_name}`).siblings("pre").remove();
-    $(`#log${version_name} .ui.inverted.active.dimmer`).css("display", "block");
+    $(`#log_file${max}${version_name}`).siblings("pre").remove();
+    $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css({
+      "background-color": "#fff",
+      display: "block",
+    });
     $.get(
-      `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=&lines=50&order=asc`,
+      `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=&lines=${lines}&order=asc`,
       (data) => {
-        $(".ui.inverted.active.dimmer").css("display", "none");
-        $(`#log${version_name} input[name=end_line]`).val(data.EndLine); //如果变动就改变所对应的值
-        $(`#log${version_name} input[name=start_line]`).val(data.StartLine);
-        $(`#log${version_name}`).prepend("
" + data.Content);
-        $(`.message${version_name} #header`).text("您已翻阅至日志顶部");
-        $(`.message${version_name}`).css("display", "block");
-        setTimeout(function () {
-          $(`.message${version_name}`).css("display", "none");
-        }, 1000);
+        $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
+          "display",
+          "none"
+        );
+        $(`#log${version_name} input[name=end_line${max}]`).val(data.EndLine); //如果变动就改变所对应的值
+        $(`#log${version_name} input[name=start_line${max}]`).val(
+          data.StartLine
+        );
+        $(`#log${max}${version_name}`).prepend("
" + data.Content);
+        if (data.Lines == 0) {
+          if (max) {
+            $("body").toast({
+              class: "info",
+              message: `您已翻阅至日志顶部,请稍后再试!`,
+            });
+          } else {
+            $(`.message${version_name} #header`).text("您已翻阅至日志顶部");
+            $(`.message${version_name}`).css("display", "block");
+            setTimeout(function () {
+              $(`.message${version_name}`).css("display", "none");
+            }, 1000);
+          }
+        }
         scrollAnimation(logContentDom, logContentDom.scrollTop, 0);
       }
     ).fail((err) => {
-      $(`#log${version_name} .ui.inverted.active.dimmer`).css(
+      $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
         "display",
         "none"
       );
       throw err;
     });
-  });
-  $(".log_bottom").click(function (e) {
+  }
+  function logBottom(e) {
+    let max = e.currentTarget.getAttribute("data-max") || "";
+    let lines = !!max ? 100 : 60;
     let version_name = $(this).data("version");
-    let logContentDom = document.querySelector(`#log${version_name}`);
+    let logContentDom = document.querySelector(`#log${max}${version_name}`);
     let ID = $(`#accordion${version_name}`).data("jobid");
     let repoPath = $(`#accordion${version_name}`).data("repopath");
-    $(`#log_file${version_name}`).siblings("pre").remove();
-    let end_line = $(`#log${version_name} input[name=end_line]`).val();
-    $(`#log${version_name} .ui.inverted.active.dimmer`).css("display", "block");
+    $(`#log_file${max}${version_name}`).siblings("pre").remove();
+    let end_line = $(`#log${version_name} input[name=end_line${max}]`).val();
+    $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css({
+      "background-color": "#fff",
+      display: "block",
+    });
     $.get(
-      `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=&lines=50&order=desc`,
+      `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=&lines=${lines}&order=desc`,
       (data) => {
-        $(`#log${version_name} .ui.inverted.active.dimmer`).css(
+        $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
           "display",
           "none"
         );
@@ -153,39 +217,71 @@ export default async function initCloudrainSow() {
             .addClass("ti-download-file")
             .removeClass("disabled");
         }
-        $(`#log${version_name} input[name=end_line]`).val(data.EndLine); //如果变动就改变所对应的值
-        $(`#log${version_name} input[name=start_line]`).val(data.StartLine);
-        $(`#log${version_name}`).append("
" + data.Content);
+        $(`#log${version_name} input[name=end_line${max}]`).val(data.EndLine); //如果变动就改变所对应的值
+        if ($(this)[0].hasAttribute("data-tab")) {
+          $(`#log${version_name} input[name=end_line-max]`).val(data.EndLine);
+          $(`#log${version_name} input[name=start_line-max]`).val(
+            data.StartLine
+          );
+          $(`#log${version_name} input[name=start_line-max-copy]`).val(
+            data.StartLine
+          );
+        }
+        $(`#log${version_name} input[name=start_line${max}]`).val(
+          data.StartLine
+        );
+        $(`#log${max}${version_name}`).append("
" + data.Content);
         $.get(
-          `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=${data.EndLine}&lines=50&order=desc`,
+          `/api/v1/repos/${repoPath}/${ID}/log?version_name=${version_name}&base_line=${data.EndLine}&lines=${lines}&order=desc`,
           (data) => {
-            $(".ui.inverted.active.dimmer").css("display", "none");
+            $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
+              "display",
+              "none"
+            );
             if (data.Lines == 0) {
-              $(`.message${version_name} #header`).text("您已翻阅至日志底部");
-              $(`.message${version_name}`).css("display", "block");
-              setTimeout(function () {
-                $(`.message${version_name}`).css("display", "none");
-              }, 1000);
+              if (max) {
+                $("body").toast({
+                  class: "info",
+                  message: `您已翻阅至日志底部,请稍后再试!`,
+                });
+              } else {
+                $(`.message${version_name} #header`).text("您已翻阅至日志底部");
+                $(`.message${version_name}`).css("display", "block");
+                setTimeout(function () {
+                  $(`.message${version_name}`).css("display", "none");
+                }, 1000);
+              }
             } else {
               if (end_line === data.EndLine || end_line === "") {
                 return;
               } else {
-                $(`#log${version_name} input[name=end_line]`).val(data.EndLine);
-                $(`#log${version_name}`).append("
" + data.Content);
+                $(`#log${version_name} input[name=end_line${max}]`).val(
+                  data.EndLine
+                );
+                if ($(this)[0].hasAttribute("data-tab")) {
+                  $(`#log${version_name} input[name=end_line-max]`).val(
+                    data.EndLine
+                  );
+                }
+                $(`#log${max}${version_name}`).append("
" + data.Content);
               }
             }
           }
         ).fail(function (err) {
-          $(`#log${version_name} .ui.inverted.active.dimmer`).css(
+          $(`#log${max}${version_name} .ui.inverted.active.dimmer`).css(
             "display",
             "none"
           );
           console.log(err);
         });
+
+        let test = $(`#log_file${version_name}`).nextAll();
+        $(`#log${version_name} input[name=init_log]`).val(test[0].innerHTML);
+
         scrollAnimation(
           logContentDom,
           logContentDom.scrollTop + 1,
-          logContentDom.scrollHeight - logContentDom.clientHeight
+          logContentDom.scrollHeight - logContentDom.clientHeight - 10
         );
       }
     ).fail((err) => {
@@ -195,6 +291,68 @@ export default async function initCloudrainSow() {
       );
       throw err;
     });
+  }
+  $(".log_top").click(logTop);
+  $(".log_bottom").click(logBottom);
+
+  // $(".log-scroll-max").scroll();
+
+  $(".full-log-dialog").click(function () {
+    let version_name = $(this).data("version");
+    let log_type = $(this).data("log-type") || "";
+    let logContentDom = document.querySelector(`#log-max${version_name}`);
+    $(`.ui.modal.max-full-log${version_name}`)
+      .modal({
+        closable: false,
+        onShow: function () {
+          $(".ui.dimmer.modals").css({
+            "background-color": "rgb(136, 136, 136,0.7)",
+          });
+          $(".log-scroll-max .ui.inverted.active.dimmer").css(
+            "display",
+            "none"
+          );
+          $(".file-info #log-file-title").text(
+            $(".full-log-dialog").data("log")
+          );
+          $(".file-info #log-file-exit").text(
+            $(".full-log-dialog").data("exit")
+          );
+        },
+        onVisible: function () {
+          $(`#log-max${version_name}`).append(
+            "
" + $(`#log${version_name} input[name=init_log]`).val()
+          );
+          scrollAnimation(
+            logContentDom,
+            logContentDom.scrollTop + 1,
+            logContentDom.scrollHeight - logContentDom.clientHeight
+          );
+          if (log_type !== "c2Net") {
+            $(".log-scroll-max").bind("scroll", function () {
+              let version_name = $(this).data("version");
+              let ID = $(`#accordion${version_name}`).data("jobid");
+              let repoPath = $(`#accordion${version_name}`).data("repopath");
+              fn(version_name, repoPath, ID, "-max", 100);
+            });
+          }
+
+          $(".log_bottom-max").bind("click", logBottom);
+          $(".log_top-max").bind("click", logTop);
+        },
+        onHide: function () {
+          let startLine = $(
+            `#log${version_name} input[name=start_line-max-copy]`
+          ).val();
+          $(`#log_file-max${version_name}`).siblings("pre").remove();
+          $(`#log${version_name} input[name=start_line-max]`).val(startLine);
+
+          $(".log-scroll-max").unbind("scroll");
+          $(".log_bottom-max").unbind("click");
+          $(".log_top-max").unbind("click");
+        },
+      })
+      .modal("show");
   });
 
   function loadLog(version_name) {
@@ -245,7 +403,6 @@ export default async function initCloudrainSow() {
       .modal({
         onApprove: function () {
           $.post(url, { version_name: version_name }, (data) => {
-            console.log(data);
             if (data.StatusOK === 0) {
               if (data.VersionListCount === 0) {
                 location.href = `/${repoPath}`;
diff --git a/web_src/js/features/cloudrbanin.js b/web_src/js/features/cloudrbanin.js
index 698523d11..657ca1381 100644
--- a/web_src/js/features/cloudrbanin.js
+++ b/web_src/js/features/cloudrbanin.js
@@ -575,3 +575,6 @@ function AdaminSearchControll() {
 }
 userSearchControll();
 AdaminSearchControll();
+$(".message .close").on("click", function () {
+  $(this).closest(".message").transition("fade");
+});
diff --git a/web_src/js/standalone/phoneverify.js b/web_src/js/standalone/phoneverify.js
index 8280a5d89..cbaffcc7c 100644
--- a/web_src/js/standalone/phoneverify.js
+++ b/web_src/js/standalone/phoneverify.js
@@ -55,7 +55,7 @@
     if (!this.dom) return;
     var self = this;
     var clientX = 0, oLeft = 0, imgHideTimer = null;
-    this.dom.find('.slide-bar-bg').on('mouseenter', function (e) {
+    this.dom.find('.slide-bar-bg').on('mouseenter touchstart', function (e) {
       if (self.verifySucess) return;
       imgHideTimer && clearTimeout(imgHideTimer);
       self.dom.find('.slide-image-big').slideDown();
diff --git a/web_src/less/_form.less b/web_src/less/_form.less
index e41c428c8..d481d1cee 100644
--- a/web_src/less/_form.less
+++ b/web_src/less/_form.less
@@ -1,8 +1,8 @@
 .form {
     .help {
         color: #999999;
-        padding-top: .6em;
-        
+        padding-top: 0.6em;
+
         display: inline-block;
     }
 }
@@ -109,7 +109,7 @@
 @media screen and (max-height: 575px) {
     #rc-imageselect,
     .g-recaptcha {
-        transform: scale(.77);
+        transform: scale(0.77);
         transform-origin: 0 0;
     }
 }
@@ -141,7 +141,7 @@
             }
         }
 
-        input[type=number] {
+        input[type="number"] {
             -moz-appearance: textfield;
         }
 
@@ -157,6 +157,13 @@
     &.new.repo,
     &.new.migrate,
     &.new.fork {
+        .ui.message {
+            @media only screen and (min-width: 768px) {
+                width: 800px !important;
+            }
+            margin: 0 auto;
+            margin-bottom: 1rem;
+        }
         #create-page-form;
 
         form {
diff --git a/web_src/less/_user.less b/web_src/less/_user.less
index 29ca96255..7afa72383 100644
--- a/web_src/less/_user.less
+++ b/web_src/less/_user.less
@@ -233,14 +233,4 @@
         -webkit-line-clamp: 2;
         -webkit-box-orient: vertical;
     }
-    .badge-section-title:before {
-        content: "";
-        position: absolute;
-        top: 50%;
-        left: 0;
-        transform: translateY(-50%);
-        width: 3px;
-        height: 1em;
-        background-color: #000;
-    }
 }